mirror of
https://github.com/nzbget/nzbget.git
synced 2026-01-06 13:09:53 -05:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d6a9c08dc7 |
2
AUTHORS
2
AUTHORS
@@ -1,4 +1,4 @@
|
||||
nzbget:
|
||||
Sven Henkel <sidddy@users.sourceforge.net> (versions 0.1.0 - ?)
|
||||
Bo Cordes Petersen <placebodk@users.sourceforge.net> (versions ? - 0.2.3)
|
||||
Andrei Prygounkov <hugbug@users.sourceforge.net> (versions 0.3.0 and later)
|
||||
Andrei Prygounkov <hugbug@users.sourceforge.net> (versions 0.3.0 - 0.3.*)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007-2010 Andrei Prygounkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007 Andrei Prygounkov <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
|
||||
@@ -53,7 +53,6 @@
|
||||
#include "Util.h"
|
||||
|
||||
extern DownloadSpeedMeter* g_pDownloadSpeedMeter;
|
||||
extern DownloadQueueHolder* g_pDownloadQueueHolder;
|
||||
extern Options* g_pOptions;
|
||||
extern ServerPool* g_pServerPool;
|
||||
|
||||
@@ -135,19 +134,7 @@ void ArticleDownloader::Run()
|
||||
}
|
||||
}
|
||||
|
||||
int iRemainedDownloadRetries = g_pOptions->GetRetries() > 0 ? g_pOptions->GetRetries() : 1;
|
||||
|
||||
#ifdef THREADCONNECT_WORKAROUND
|
||||
// NOTE: about iRemainedConnectRetries:
|
||||
// Sometimes connections just do not want to work in a particular thread,
|
||||
// regardless of retry count. However they work in other threads.
|
||||
// If ArticleDownloader can't start download after many attempts, it terminates
|
||||
// and let QueueCoordinator retry the article in a new thread.
|
||||
// It wasn't confirmed that this workaround actually helps.
|
||||
// Therefore it is disabled by default. Define symbol "THREADCONNECT_WORKAROUND"
|
||||
// to activate the workaround.
|
||||
int iRemainedConnectRetries = iRemainedDownloadRetries > 5 ? iRemainedDownloadRetries * 2 : 10;
|
||||
#endif
|
||||
int retry = g_pOptions->GetRetries();
|
||||
|
||||
EStatus Status = adFailed;
|
||||
int iMaxLevel = g_pServerPool->GetMaxLevel();
|
||||
@@ -158,16 +145,15 @@ void ArticleDownloader::Run()
|
||||
}
|
||||
int level = 0;
|
||||
|
||||
while (!IsStopped() && iRemainedDownloadRetries > 0)
|
||||
while (!IsStopped() && (retry > 0))
|
||||
{
|
||||
SetLastUpdateTimeNow();
|
||||
|
||||
Status = adFailed;
|
||||
|
||||
while (!IsStopped() && !m_pConnection)
|
||||
if (!m_pConnection)
|
||||
{
|
||||
m_pConnection = g_pServerPool->GetConnection(level);
|
||||
usleep(5 * 1000);
|
||||
m_pConnection = g_pServerPool->GetConnection(level, true);
|
||||
}
|
||||
|
||||
if (IsStopped())
|
||||
@@ -176,16 +162,14 @@ void ArticleDownloader::Run()
|
||||
break;
|
||||
}
|
||||
|
||||
if (g_pOptions->GetPauseDownload() || g_pOptions->GetPauseDownload2())
|
||||
if (!m_pConnection)
|
||||
{
|
||||
Status = adRetry;
|
||||
break;
|
||||
debug("m_pConnection is NULL");
|
||||
error("Serious error: Connection is NULL");
|
||||
}
|
||||
|
||||
m_pConnection->SetSuppressErrors(false);
|
||||
|
||||
|
||||
// test connection
|
||||
bool bConnected = m_pConnection && m_pConnection->Connect();
|
||||
bool bConnected = m_pConnection && m_pConnection->Connect() >= 0;
|
||||
if (bConnected && !IsStopped())
|
||||
{
|
||||
// Okay, we got a Connection. Now start downloading.
|
||||
@@ -200,9 +184,6 @@ void ArticleDownloader::Run()
|
||||
m_pConnection->Disconnect();
|
||||
bConnected = false;
|
||||
Status = adFailed;
|
||||
#ifdef THREADCONNECT_WORKAROUND
|
||||
iRemainedConnectRetries--;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -215,28 +196,9 @@ void ArticleDownloader::Run()
|
||||
FreeConnection(Status == adFinished);
|
||||
}
|
||||
}
|
||||
#ifdef THREADCONNECT_WORKAROUND
|
||||
else
|
||||
{
|
||||
iRemainedConnectRetries--;
|
||||
}
|
||||
|
||||
if (iRemainedConnectRetries == 0)
|
||||
{
|
||||
debug("Can't connect from this thread, retry later from another");
|
||||
Status = adRetry;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (g_pOptions->GetPauseDownload() || g_pOptions->GetPauseDownload2())
|
||||
{
|
||||
Status = adRetry;
|
||||
break;
|
||||
}
|
||||
|
||||
if (((Status == adFailed) || (Status == adCrcError && g_pOptions->GetRetryOnCrcError())) &&
|
||||
(iRemainedDownloadRetries > 1 || !bConnected) && !IsStopped())
|
||||
(retry > 1 || !bConnected) && !IsStopped())
|
||||
{
|
||||
detail("Waiting %i sec to retry", g_pOptions->GetRetryInterval());
|
||||
int msec = 0;
|
||||
@@ -287,7 +249,7 @@ void ArticleDownloader::Run()
|
||||
{
|
||||
level = 0;
|
||||
}
|
||||
iRemainedDownloadRetries--;
|
||||
retry--;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -300,7 +262,7 @@ void ArticleDownloader::Run()
|
||||
Status = adFinished;
|
||||
}
|
||||
|
||||
if (Status != adFinished && Status != adRetry)
|
||||
if (Status != adFinished)
|
||||
{
|
||||
Status = adFailed;
|
||||
}
|
||||
@@ -327,23 +289,20 @@ ArticleDownloader::EStatus ArticleDownloader::Download()
|
||||
const char* szResponse = NULL;
|
||||
EStatus Status = adRunning;
|
||||
|
||||
if (m_pConnection->GetNewsServer()->GetJoinGroup())
|
||||
// at first, change group
|
||||
for (FileInfo::Groups::iterator it = m_pFileInfo->GetGroups()->begin(); it != m_pFileInfo->GetGroups()->end(); it++)
|
||||
{
|
||||
// change group
|
||||
for (FileInfo::Groups::iterator it = m_pFileInfo->GetGroups()->begin(); it != m_pFileInfo->GetGroups()->end(); it++)
|
||||
szResponse = m_pConnection->JoinGroup(*it);
|
||||
if (szResponse && !strncmp(szResponse, "2", 1))
|
||||
{
|
||||
szResponse = m_pConnection->JoinGroup(*it);
|
||||
if (szResponse && !strncmp(szResponse, "2", 1))
|
||||
{
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Status = CheckResponse(szResponse, "could not join group");
|
||||
if (Status != adFinished)
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
Status = CheckResponse(szResponse, "could not join group");
|
||||
if (Status != adFinished)
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
// retrieve article
|
||||
@@ -393,7 +352,7 @@ ArticleDownloader::EStatus ArticleDownloader::Download()
|
||||
(g_pDownloadSpeedMeter->CalcCurrentDownloadSpeed() > g_pOptions->GetDownloadRate()))
|
||||
{
|
||||
SetLastUpdateTimeNow();
|
||||
usleep(10 * 1000);
|
||||
usleep(200 * 1000);
|
||||
}
|
||||
|
||||
int iLen = 0;
|
||||
@@ -422,7 +381,6 @@ ArticleDownloader::EStatus ArticleDownloader::Download()
|
||||
if (!strncmp(line, "..", 2))
|
||||
{
|
||||
line++;
|
||||
iLen--;
|
||||
}
|
||||
|
||||
if (!bBody)
|
||||
@@ -503,7 +461,7 @@ ArticleDownloader::EStatus ArticleDownloader::CheckResponse(const char* szRespon
|
||||
warn("Article %s @ %s failed, %s: %s", m_szInfoName, m_pConnection->GetServer()->GetHost(), szComment, szResponse);
|
||||
return adConnectError;
|
||||
}
|
||||
else if (!strncmp(szResponse, "41", 2) || !strncmp(szResponse, "42", 2) || !strncmp(szResponse, "43", 2))
|
||||
else if (!strncmp(szResponse, "41", 2) || !strncmp(szResponse, "42", 2))
|
||||
{
|
||||
warn("Article %s @ %s failed, %s: %s", m_szInfoName, m_pConnection->GetServer()->GetHost(), szComment, szResponse);
|
||||
return adNotFound;
|
||||
@@ -530,26 +488,18 @@ bool ArticleDownloader::Write(char* szLine, int iLen)
|
||||
|
||||
if (g_pOptions->GetDecode())
|
||||
{
|
||||
bool bOK = false;
|
||||
if (m_eFormat == Decoder::efYenc)
|
||||
{
|
||||
bOK = m_YDecoder.Write(szLine, iLen, m_pOutFile);
|
||||
return m_YDecoder.Write(szLine, iLen, m_pOutFile);
|
||||
}
|
||||
else if (m_eFormat == Decoder::efUx)
|
||||
{
|
||||
bOK = m_UDecoder.Write(szLine, iLen, m_pOutFile);
|
||||
return m_UDecoder.Write(szLine, iLen, m_pOutFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
warn("Decoding %s failed: unsupported encoding", m_szInfoName);
|
||||
return false;
|
||||
}
|
||||
if (!bOK)
|
||||
{
|
||||
debug("Failed line: %s", szLine);
|
||||
warn("Decoding %s failed", m_szInfoName);
|
||||
}
|
||||
return bOK;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -633,7 +583,7 @@ bool ArticleDownloader::PrepareFile(char* szLine)
|
||||
{
|
||||
bool bDirectWrite = g_pOptions->GetDirectWrite() && m_eFormat == Decoder::efYenc;
|
||||
const char* szFilename = bDirectWrite ? m_szOutputFilename : m_szTempFilename;
|
||||
m_pOutFile = fopen(szFilename, bDirectWrite ? "rb+" : "wb");
|
||||
m_pOutFile = fopen(szFilename, bDirectWrite ? "r+" : "w");
|
||||
if (!m_pOutFile)
|
||||
{
|
||||
error("Could not %s file %s", bDirectWrite ? "open" : "create", szFilename);
|
||||
@@ -701,7 +651,7 @@ ArticleDownloader::EStatus ArticleDownloader::DecodeCheck()
|
||||
if (bDirectWrite && g_pOptions->GetContinuePartial())
|
||||
{
|
||||
// create empty flag-file to indicate that the artcile was downloaded
|
||||
FILE* flagfile = fopen(m_szResultFilename, "wb");
|
||||
FILE* flagfile = fopen(m_szResultFilename, "w");
|
||||
if (!flagfile)
|
||||
{
|
||||
error("Could not create file %s", m_szResultFilename);
|
||||
@@ -776,7 +726,6 @@ void ArticleDownloader::Stop()
|
||||
m_mutexConnection.Lock();
|
||||
if (m_pConnection)
|
||||
{
|
||||
m_pConnection->SetSuppressErrors(true);
|
||||
m_pConnection->Cancel();
|
||||
}
|
||||
m_mutexConnection.Unlock();
|
||||
@@ -790,7 +739,6 @@ bool ArticleDownloader::Terminate()
|
||||
if (terminated && pConnection)
|
||||
{
|
||||
debug("Terminating connection");
|
||||
pConnection->SetSuppressErrors(true);
|
||||
pConnection->Cancel();
|
||||
pConnection->Disconnect();
|
||||
g_pServerPool->FreeConnection(pConnection, true);
|
||||
@@ -843,31 +791,24 @@ void ArticleDownloader::CompleteFileParts()
|
||||
detail("Joining articles for %s", InfoFilename);
|
||||
}
|
||||
|
||||
char szNZBDestDir[1024];
|
||||
// the locking is needed for accessing the memebers of NZBInfo
|
||||
g_pDownloadQueueHolder->LockQueue();
|
||||
strncpy(szNZBDestDir, m_pFileInfo->GetNZBInfo()->GetDestDir(), 1024);
|
||||
g_pDownloadQueueHolder->UnlockQueue();
|
||||
szNZBDestDir[1024-1] = '\0';
|
||||
char ofn[1024];
|
||||
snprintf(ofn, 1024, "%s%c%s", m_pFileInfo->GetNZBInfo()->GetDestDir(), (int)PATH_SEPARATOR, m_pFileInfo->GetFilename());
|
||||
ofn[1024-1] = '\0';
|
||||
|
||||
// Ensure the DstDir is created
|
||||
if (!Util::ForceDirectories(szNZBDestDir))
|
||||
if (!Util::CreateDirectory(m_pFileInfo->GetNZBInfo()->GetDestDir()))
|
||||
{
|
||||
error("Could not create directory %s! Errcode: %i", szNZBDestDir, errno);
|
||||
error("Could not create directory %s! Errcode: %i", m_pFileInfo->GetNZBInfo()->GetDestDir(), errno);
|
||||
SetStatus(adJoined);
|
||||
return;
|
||||
}
|
||||
|
||||
char ofn[1024];
|
||||
snprintf(ofn, 1024, "%s%c%s", szNZBDestDir, (int)PATH_SEPARATOR, m_pFileInfo->GetFilename());
|
||||
ofn[1024-1] = '\0';
|
||||
|
||||
// prevent overwriting existing files
|
||||
int dupcount = 0;
|
||||
while (Util::FileExists(ofn))
|
||||
{
|
||||
dupcount++;
|
||||
snprintf(ofn, 1024, "%s%c%s_duplicate%d", szNZBDestDir, (int)PATH_SEPARATOR, m_pFileInfo->GetFilename(), dupcount);
|
||||
snprintf(ofn, 1024, "%s%c%s_duplicate%d", m_pFileInfo->GetNZBInfo()->GetDestDir(), (int)PATH_SEPARATOR, m_pFileInfo->GetFilename(), dupcount);
|
||||
ofn[1024-1] = '\0';
|
||||
}
|
||||
|
||||
@@ -879,7 +820,7 @@ void ArticleDownloader::CompleteFileParts()
|
||||
if (g_pOptions->GetDecode() && !bDirectWrite)
|
||||
{
|
||||
remove(tmpdestfile);
|
||||
outfile = fopen(tmpdestfile, "wb+");
|
||||
outfile = fopen(tmpdestfile, "w+");
|
||||
if (!outfile)
|
||||
{
|
||||
error("Could not create file %s!", tmpdestfile);
|
||||
@@ -929,7 +870,7 @@ void ArticleDownloader::CompleteFileParts()
|
||||
FILE* infile;
|
||||
const char* fn = pa->GetResultFilename();
|
||||
|
||||
infile = fopen(fn, "rb");
|
||||
infile = fopen(fn, "r");
|
||||
if (infile)
|
||||
{
|
||||
int cnt = BUFFER_SIZE;
|
||||
@@ -1015,8 +956,6 @@ void ArticleDownloader::CompleteFileParts()
|
||||
{
|
||||
warn("Renaming broken file from %s to %s failed", ofn, brokenfn);
|
||||
}
|
||||
strncpy(ofn, brokenfn, 1024);
|
||||
ofn[1024-1] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1026,137 +965,13 @@ void ArticleDownloader::CompleteFileParts()
|
||||
if (g_pOptions->GetCreateBrokenLog())
|
||||
{
|
||||
char szBrokenLogName[1024];
|
||||
snprintf(szBrokenLogName, 1024, "%s%c_brokenlog.txt", szNZBDestDir, (int)PATH_SEPARATOR);
|
||||
snprintf(szBrokenLogName, 1024, "%s%c_brokenlog.txt", m_pFileInfo->GetNZBInfo()->GetDestDir(), (int)PATH_SEPARATOR);
|
||||
szBrokenLogName[1024-1] = '\0';
|
||||
FILE* file = fopen(szBrokenLogName, "ab");
|
||||
fprintf(file, "%s (%i/%i)%s", m_pFileInfo->GetFilename(), m_pFileInfo->GetArticles()->size() - iBrokenCount, m_pFileInfo->GetArticles()->size(), LINE_ENDING);
|
||||
FILE* file = fopen(szBrokenLogName, "a");
|
||||
fprintf(file, "%s (%i/%i)\n", m_pFileInfo->GetFilename(), m_pFileInfo->GetArticles()->size() - iBrokenCount, m_pFileInfo->GetArticles()->size());
|
||||
fclose(file);
|
||||
}
|
||||
}
|
||||
|
||||
// the locking is needed for accessing the memebers of NZBInfo
|
||||
g_pDownloadQueueHolder->LockQueue();
|
||||
m_pFileInfo->GetNZBInfo()->GetCompletedFiles()->push_back(strdup(ofn));
|
||||
if (strcmp(m_pFileInfo->GetNZBInfo()->GetDestDir(), szNZBDestDir))
|
||||
{
|
||||
// destination directory was changed during completion, need to move the file
|
||||
MoveCompletedFiles(m_pFileInfo->GetNZBInfo(), szNZBDestDir);
|
||||
}
|
||||
g_pDownloadQueueHolder->UnlockQueue();
|
||||
|
||||
SetStatus(adJoined);
|
||||
}
|
||||
|
||||
bool ArticleDownloader::MoveCompletedFiles(NZBInfo* pNZBInfo, const char* szOldDestDir)
|
||||
{
|
||||
if (pNZBInfo->GetCompletedFiles()->empty())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Ensure the DstDir is created
|
||||
if (!Util::ForceDirectories(pNZBInfo->GetDestDir()))
|
||||
{
|
||||
error("Could not create directory %s! Errcode: %i", pNZBInfo->GetDestDir(), errno);
|
||||
return false;
|
||||
}
|
||||
|
||||
// move already downloaded files to new destination
|
||||
for (NZBInfo::Files::iterator it = pNZBInfo->GetCompletedFiles()->begin(); it != pNZBInfo->GetCompletedFiles()->end(); it++)
|
||||
{
|
||||
char* szFileName = *it;
|
||||
char szNewFileName[1024];
|
||||
snprintf(szNewFileName, 1024, "%s%c%s", pNZBInfo->GetDestDir(), (int)PATH_SEPARATOR, Util::BaseFileName(szFileName));
|
||||
szNewFileName[1024-1] = '\0';
|
||||
|
||||
// check if file was not moved already
|
||||
if (strcmp(szFileName, szNewFileName))
|
||||
{
|
||||
// prevent overwriting of existing files
|
||||
int dupcount = 0;
|
||||
while (Util::FileExists(szNewFileName))
|
||||
{
|
||||
dupcount++;
|
||||
snprintf(szNewFileName, 1024, "%s%c%s_duplicate%d", pNZBInfo->GetDestDir(), (int)PATH_SEPARATOR, Util::BaseFileName(szFileName), dupcount);
|
||||
szNewFileName[1024-1] = '\0';
|
||||
}
|
||||
|
||||
detail("Moving file %s to %s", szFileName, szNewFileName);
|
||||
if (Util::MoveFile(szFileName, szNewFileName))
|
||||
{
|
||||
free(szFileName);
|
||||
*it = strdup(szNewFileName);
|
||||
}
|
||||
else
|
||||
{
|
||||
error("Could not move file %s to %s! Errcode: %i", szFileName, szNewFileName, errno);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// move brokenlog.txt
|
||||
if (g_pOptions->GetCreateBrokenLog())
|
||||
{
|
||||
char szOldBrokenLogName[1024];
|
||||
snprintf(szOldBrokenLogName, 1024, "%s%c_brokenlog.txt", szOldDestDir, (int)PATH_SEPARATOR);
|
||||
szOldBrokenLogName[1024-1] = '\0';
|
||||
if (Util::FileExists(szOldBrokenLogName))
|
||||
{
|
||||
char szBrokenLogName[1024];
|
||||
snprintf(szBrokenLogName, 1024, "%s%c_brokenlog.txt", pNZBInfo->GetDestDir(), (int)PATH_SEPARATOR);
|
||||
szBrokenLogName[1024-1] = '\0';
|
||||
|
||||
detail("Moving file %s to %s", szOldBrokenLogName, szBrokenLogName);
|
||||
if (Util::FileExists(szBrokenLogName))
|
||||
{
|
||||
// copy content to existing new file, then delete old file
|
||||
FILE* outfile;
|
||||
outfile = fopen(szBrokenLogName, "ab");
|
||||
if (outfile)
|
||||
{
|
||||
FILE* infile;
|
||||
infile = fopen(szOldBrokenLogName, "rb");
|
||||
if (infile)
|
||||
{
|
||||
static const int BUFFER_SIZE = 1024 * 50;
|
||||
int cnt = BUFFER_SIZE;
|
||||
char* buffer = (char*)malloc(BUFFER_SIZE);
|
||||
while (cnt == BUFFER_SIZE)
|
||||
{
|
||||
cnt = (int)fread(buffer, 1, BUFFER_SIZE, infile);
|
||||
fwrite(buffer, 1, cnt, outfile);
|
||||
}
|
||||
fclose(infile);
|
||||
free(buffer);
|
||||
remove(szOldBrokenLogName);
|
||||
}
|
||||
else
|
||||
{
|
||||
error("Could not open file %s", szOldBrokenLogName);
|
||||
}
|
||||
fclose(outfile);
|
||||
}
|
||||
else
|
||||
{
|
||||
error("Could not open file %s", szBrokenLogName);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// move to new destination
|
||||
if (!Util::MoveFile(szOldBrokenLogName, szBrokenLogName))
|
||||
{
|
||||
error("Could not move file %s to %s! Errcode: %i", szOldBrokenLogName, szBrokenLogName, errno);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// delete old directory (if empty)
|
||||
if (Util::DirEmpty(szOldDestDir))
|
||||
{
|
||||
rmdir(szOldDestDir);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007-2009 Andrei Prygounkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007 Andrei Prygounkov <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
|
||||
@@ -28,6 +28,9 @@
|
||||
#define ARTICLEDOWNLOADER_H
|
||||
|
||||
#include <time.h>
|
||||
#ifdef WIN32
|
||||
#include <sys/timeb.h>
|
||||
#endif
|
||||
|
||||
#include "Observer.h"
|
||||
#include "DownloadInfo.h"
|
||||
@@ -44,7 +47,6 @@ public:
|
||||
adRunning,
|
||||
adFinished,
|
||||
adFailed,
|
||||
adRetry,
|
||||
adDecodeError,
|
||||
adCrcError,
|
||||
adDecoding,
|
||||
@@ -101,7 +103,6 @@ public:
|
||||
void SetInfoName(const char* v);
|
||||
const char* GetInfoName() { return m_szInfoName; }
|
||||
void CompleteFileParts();
|
||||
static bool MoveCompletedFiles(NZBInfo* pNZBInfo, const char* szOldDestDir);
|
||||
void SetConnection(NNTPConnection* pConnection) { m_pConnection = pConnection; }
|
||||
|
||||
void LogDebugInfo();
|
||||
@@ -114,5 +115,5 @@ public:
|
||||
virtual float CalcCurrentDownloadSpeed() = 0;
|
||||
virtual void AddSpeedReading(int iBytes) = 0;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
406
BinRpc.cpp
406
BinRpc.cpp
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2005 Bo Cordes Petersen <placebodk@sourceforge.net>
|
||||
* Copyright (C) 2007-2010 Andrei Prygounkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2005 Bo Cordes Petersen <placebodk@sourceforge.net>
|
||||
* Copyright (C) 2007 Andrei Prygounkov <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
|
||||
@@ -59,8 +59,7 @@ extern void ExitProc();
|
||||
|
||||
const char* g_szMessageRequestNames[] =
|
||||
{ "N/A", "Download", "Pause/Unpause", "List", "Set download rate", "Dump debug",
|
||||
"Edit queue", "Log", "Quit", "Version", "Post-queue", "Write log", "Scan",
|
||||
"Pause/Unpause postprocessor", "History" };
|
||||
"Edit queue", "Log", "Quit", "Version", "Post-queue" };
|
||||
|
||||
const unsigned int g_iMessageRequestSizes[] =
|
||||
{ 0,
|
||||
@@ -74,9 +73,6 @@ const unsigned int g_iMessageRequestSizes[] =
|
||||
sizeof(SNZBShutdownRequest),
|
||||
sizeof(SNZBVersionRequest),
|
||||
sizeof(SNZBPostQueueRequest),
|
||||
sizeof(SNZBWriteLogRequest),
|
||||
sizeof(SNZBScanRequest),
|
||||
sizeof(SNZBHistoryRequest)
|
||||
};
|
||||
|
||||
//*****************************************************************
|
||||
@@ -112,10 +108,10 @@ void BinRpcProcessor::Execute()
|
||||
void BinRpcProcessor::Dispatch()
|
||||
{
|
||||
if (ntohl(m_MessageBase.m_iType) >= (int)eRemoteRequestDownload &&
|
||||
ntohl(m_MessageBase.m_iType) <= (int)eRemoteRequestHistory &&
|
||||
ntohl(m_MessageBase.m_iType) <= (int)eRemoteRequestPostQueue &&
|
||||
g_iMessageRequestSizes[ntohl(m_MessageBase.m_iType)] != ntohl(m_MessageBase.m_iStructSize))
|
||||
{
|
||||
error("Invalid size of request: expected %i Bytes, but received %i Bytes",
|
||||
error("Invalid size of request: needed %i Bytes, but received %i Bytes",
|
||||
g_iMessageRequestSizes[ntohl(m_MessageBase.m_iType)], ntohl(m_MessageBase.m_iStructSize));
|
||||
return;
|
||||
}
|
||||
@@ -125,56 +121,70 @@ void BinRpcProcessor::Dispatch()
|
||||
switch (ntohl(m_MessageBase.m_iType))
|
||||
{
|
||||
case eRemoteRequestDownload:
|
||||
command = new DownloadBinCommand();
|
||||
break;
|
||||
{
|
||||
command = new DownloadBinCommand();
|
||||
break;
|
||||
}
|
||||
|
||||
case eRemoteRequestList:
|
||||
command = new ListBinCommand();
|
||||
break;
|
||||
{
|
||||
command = new ListBinCommand();
|
||||
break;
|
||||
}
|
||||
|
||||
case eRemoteRequestLog:
|
||||
command = new LogBinCommand();
|
||||
break;
|
||||
{
|
||||
command = new LogBinCommand();
|
||||
break;
|
||||
}
|
||||
|
||||
case eRemoteRequestPauseUnpause:
|
||||
command = new PauseUnpauseBinCommand();
|
||||
break;
|
||||
{
|
||||
command = new PauseUnpauseBinCommand();
|
||||
break;
|
||||
}
|
||||
|
||||
case eRemoteRequestEditQueue:
|
||||
command = new EditQueueBinCommand();
|
||||
break;
|
||||
{
|
||||
command = new EditQueueBinCommand();
|
||||
break;
|
||||
}
|
||||
|
||||
case eRemoteRequestSetDownloadRate:
|
||||
command = new SetDownloadRateBinCommand();
|
||||
break;
|
||||
{
|
||||
command = new SetDownloadRateBinCommand();
|
||||
break;
|
||||
}
|
||||
|
||||
case eRemoteRequestDumpDebug:
|
||||
command = new DumpDebugBinCommand();
|
||||
break;
|
||||
{
|
||||
command = new DumpDebugBinCommand();
|
||||
break;
|
||||
}
|
||||
|
||||
case eRemoteRequestShutdown:
|
||||
command = new ShutdownBinCommand();
|
||||
break;
|
||||
{
|
||||
command = new ShutdownBinCommand();
|
||||
break;
|
||||
}
|
||||
|
||||
case eRemoteRequestVersion:
|
||||
command = new VersionBinCommand();
|
||||
break;
|
||||
{
|
||||
command = new VersionBinCommand();
|
||||
break;
|
||||
}
|
||||
|
||||
case eRemoteRequestPostQueue:
|
||||
command = new PostQueueBinCommand();
|
||||
break;
|
||||
{
|
||||
command = new PostQueueBinCommand();
|
||||
break;
|
||||
}
|
||||
|
||||
case eRemoteRequestWriteLog:
|
||||
command = new WriteLogBinCommand();
|
||||
break;
|
||||
|
||||
case eRemoteRequestScan:
|
||||
command = new ScanBinCommand();
|
||||
break;
|
||||
|
||||
case eRemoteRequestHistory:
|
||||
command = new HistoryBinCommand();
|
||||
break;
|
||||
{
|
||||
command = new WriteLogBinCommand();
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
error("Received unsupported request %i", ntohl(m_MessageBase.m_iType));
|
||||
@@ -233,25 +243,7 @@ void PauseUnpauseBinCommand::Execute()
|
||||
return;
|
||||
}
|
||||
|
||||
switch (ntohl(PauseUnpauseRequest.m_iAction))
|
||||
{
|
||||
case eRemotePauseUnpauseActionDownload:
|
||||
g_pOptions->SetPauseDownload(ntohl(PauseUnpauseRequest.m_bPause));
|
||||
break;
|
||||
|
||||
case eRemotePauseUnpauseActionDownload2:
|
||||
g_pOptions->SetPauseDownload2(ntohl(PauseUnpauseRequest.m_bPause));
|
||||
break;
|
||||
|
||||
case eRemotePauseUnpauseActionPostProcess:
|
||||
g_pOptions->SetPausePostProcess(ntohl(PauseUnpauseRequest.m_bPause));
|
||||
break;
|
||||
|
||||
case eRemotePauseUnpauseActionScan:
|
||||
g_pOptions->SetPauseScan(ntohl(PauseUnpauseRequest.m_bPause));
|
||||
break;
|
||||
}
|
||||
|
||||
g_pOptions->SetPause(ntohl(PauseUnpauseRequest.m_bPause));
|
||||
SendBoolResponse(true, "Pause-/Unpause-Command completed successfully");
|
||||
}
|
||||
|
||||
@@ -299,7 +291,7 @@ void VersionBinCommand::Execute()
|
||||
return;
|
||||
}
|
||||
|
||||
SendBoolResponse(true, Util::VersionRevision());
|
||||
SendBoolResponse(true, VERSION);
|
||||
}
|
||||
|
||||
void DownloadBinCommand::Execute()
|
||||
@@ -331,7 +323,7 @@ void DownloadBinCommand::Execute()
|
||||
|
||||
if (NeedBytes == 0)
|
||||
{
|
||||
NZBFile* pNZBFile = NZBFile::CreateFromBuffer(DownloadRequest.m_szFilename, DownloadRequest.m_szCategory, pRecvBuffer, ntohl(DownloadRequest.m_iTrailingDataLength));
|
||||
NZBFile* pNZBFile = NZBFile::CreateFromBuffer(DownloadRequest.m_szFilename, pRecvBuffer, ntohl(DownloadRequest.m_iTrailingDataLength));
|
||||
|
||||
if (pNZBFile)
|
||||
{
|
||||
@@ -368,7 +360,7 @@ void ListBinCommand::Execute()
|
||||
memset(&ListResponse, 0, sizeof(ListResponse));
|
||||
ListResponse.m_MessageBase.m_iSignature = htonl(NZBMESSAGE_SIGNATURE);
|
||||
ListResponse.m_MessageBase.m_iStructSize = htonl(sizeof(ListResponse));
|
||||
ListResponse.m_iEntrySize = htonl(sizeof(SNZBListResponseFileEntry));
|
||||
ListResponse.m_iEntrySize = htonl(sizeof(SNZBListResponseEntry));
|
||||
|
||||
char* buf = NULL;
|
||||
int bufsize = 0;
|
||||
@@ -378,125 +370,29 @@ void ListBinCommand::Execute()
|
||||
// Make a data structure and copy all the elements of the list into it
|
||||
DownloadQueue* pDownloadQueue = g_pQueueCoordinator->LockQueue();
|
||||
|
||||
// calculate required buffer size for nzbs
|
||||
int iNrNZBEntries = pDownloadQueue->GetNZBInfoList()->size();
|
||||
int iNrPPPEntries = 0;
|
||||
bufsize += iNrNZBEntries * sizeof(SNZBListResponseNZBEntry);
|
||||
for (NZBInfoList::iterator it = pDownloadQueue->GetNZBInfoList()->begin(); it != pDownloadQueue->GetNZBInfoList()->end(); it++)
|
||||
{
|
||||
NZBInfo* pNZBInfo = *it;
|
||||
bufsize += strlen(pNZBInfo->GetFilename()) + 1;
|
||||
bufsize += strlen(pNZBInfo->GetDestDir()) + 1;
|
||||
bufsize += strlen(pNZBInfo->GetCategory()) + 1;
|
||||
bufsize += strlen(pNZBInfo->GetQueuedFilename()) + 1;
|
||||
// align struct to 4-bytes, needed by ARM-processor (and may be others)
|
||||
bufsize += bufsize % 4 > 0 ? 4 - bufsize % 4 : 0;
|
||||
int NrEntries = pDownloadQueue->size();
|
||||
|
||||
// calculate required buffer size for pp-parameters
|
||||
for (NZBParameterList::iterator it = pNZBInfo->GetParameters()->begin(); it != pNZBInfo->GetParameters()->end(); it++)
|
||||
{
|
||||
NZBParameter* pNZBParameter = *it;
|
||||
bufsize += sizeof(SNZBListResponsePPPEntry);
|
||||
bufsize += strlen(pNZBParameter->GetName()) + 1;
|
||||
bufsize += strlen(pNZBParameter->GetValue()) + 1;
|
||||
// align struct to 4-bytes, needed by ARM-processor (and may be others)
|
||||
bufsize += bufsize % 4 > 0 ? 4 - bufsize % 4 : 0;
|
||||
iNrPPPEntries++;
|
||||
}
|
||||
}
|
||||
|
||||
// calculate required buffer size for files
|
||||
int iNrFileEntries = pDownloadQueue->GetFileQueue()->size();
|
||||
bufsize += iNrFileEntries * sizeof(SNZBListResponseFileEntry);
|
||||
for (FileQueue::iterator it = pDownloadQueue->GetFileQueue()->begin(); it != pDownloadQueue->GetFileQueue()->end(); it++)
|
||||
// calculate required buffer size
|
||||
bufsize = NrEntries * sizeof(SNZBListResponseEntry);
|
||||
for (DownloadQueue::iterator it = pDownloadQueue->begin(); it != pDownloadQueue->end(); it++)
|
||||
{
|
||||
FileInfo* pFileInfo = *it;
|
||||
bufsize += strlen(pFileInfo->GetNZBInfo()->GetFilename()) + 1;
|
||||
bufsize += strlen(pFileInfo->GetSubject()) + 1;
|
||||
bufsize += strlen(pFileInfo->GetFilename()) + 1;
|
||||
bufsize += strlen(pFileInfo->GetNZBInfo()->GetDestDir()) + 1;
|
||||
// align struct to 4-bytes, needed by ARM-processor (and may be others)
|
||||
bufsize += bufsize % 4 > 0 ? 4 - bufsize % 4 : 0;
|
||||
}
|
||||
|
||||
buf = (char*) malloc(bufsize);
|
||||
char* bufptr = buf;
|
||||
|
||||
// write nzb entries
|
||||
for (NZBInfoList::iterator it = pDownloadQueue->GetNZBInfoList()->begin(); it != pDownloadQueue->GetNZBInfoList()->end(); it++)
|
||||
{
|
||||
unsigned long iSizeHi, iSizeLo;
|
||||
NZBInfo* pNZBInfo = *it;
|
||||
SNZBListResponseNZBEntry* pListAnswer = (SNZBListResponseNZBEntry*) bufptr;
|
||||
Util::SplitInt64(pNZBInfo->GetSize(), &iSizeHi, &iSizeLo);
|
||||
pListAnswer->m_iSizeLo = htonl(iSizeLo);
|
||||
pListAnswer->m_iSizeHi = htonl(iSizeHi);
|
||||
pListAnswer->m_iFilenameLen = htonl(strlen(pNZBInfo->GetFilename()) + 1);
|
||||
pListAnswer->m_iDestDirLen = htonl(strlen(pNZBInfo->GetDestDir()) + 1);
|
||||
pListAnswer->m_iCategoryLen = htonl(strlen(pNZBInfo->GetCategory()) + 1);
|
||||
pListAnswer->m_iQueuedFilenameLen = htonl(strlen(pNZBInfo->GetQueuedFilename()) + 1);
|
||||
bufptr += sizeof(SNZBListResponseNZBEntry);
|
||||
strcpy(bufptr, pNZBInfo->GetFilename());
|
||||
bufptr += ntohl(pListAnswer->m_iFilenameLen);
|
||||
strcpy(bufptr, pNZBInfo->GetDestDir());
|
||||
bufptr += ntohl(pListAnswer->m_iDestDirLen);
|
||||
strcpy(bufptr, pNZBInfo->GetCategory());
|
||||
bufptr += ntohl(pListAnswer->m_iCategoryLen);
|
||||
strcpy(bufptr, pNZBInfo->GetQueuedFilename());
|
||||
bufptr += ntohl(pListAnswer->m_iQueuedFilenameLen);
|
||||
// align struct to 4-bytes, needed by ARM-processor (and may be others)
|
||||
if ((size_t)bufptr % 4 > 0)
|
||||
{
|
||||
pListAnswer->m_iQueuedFilenameLen = htonl(ntohl(pListAnswer->m_iQueuedFilenameLen) + 4 - (size_t)bufptr % 4);
|
||||
memset(bufptr, 0, 4 - (size_t)bufptr % 4); //suppress valgrind warning "uninitialized data"
|
||||
bufptr += 4 - (size_t)bufptr % 4;
|
||||
}
|
||||
}
|
||||
|
||||
// write ppp entries
|
||||
int iNZBIndex = 1;
|
||||
for (NZBInfoList::iterator it = pDownloadQueue->GetNZBInfoList()->begin(); it != pDownloadQueue->GetNZBInfoList()->end(); it++, iNZBIndex++)
|
||||
{
|
||||
NZBInfo* pNZBInfo = *it;
|
||||
for (NZBParameterList::iterator it = pNZBInfo->GetParameters()->begin(); it != pNZBInfo->GetParameters()->end(); it++)
|
||||
{
|
||||
NZBParameter* pNZBParameter = *it;
|
||||
SNZBListResponsePPPEntry* pListAnswer = (SNZBListResponsePPPEntry*) bufptr;
|
||||
pListAnswer->m_iNZBIndex = htonl(iNZBIndex);
|
||||
pListAnswer->m_iNameLen = htonl(strlen(pNZBParameter->GetName()) + 1);
|
||||
pListAnswer->m_iValueLen = htonl(strlen(pNZBParameter->GetValue()) + 1);
|
||||
bufptr += sizeof(SNZBListResponsePPPEntry);
|
||||
strcpy(bufptr, pNZBParameter->GetName());
|
||||
bufptr += ntohl(pListAnswer->m_iNameLen);
|
||||
strcpy(bufptr, pNZBParameter->GetValue());
|
||||
bufptr += ntohl(pListAnswer->m_iValueLen);
|
||||
// align struct to 4-bytes, needed by ARM-processor (and may be others)
|
||||
if ((size_t)bufptr % 4 > 0)
|
||||
{
|
||||
pListAnswer->m_iValueLen = htonl(ntohl(pListAnswer->m_iValueLen) + 4 - (size_t)bufptr % 4);
|
||||
memset(bufptr, 0, 4 - (size_t)bufptr % 4); //suppress valgrind warning "uninitialized data"
|
||||
bufptr += 4 - (size_t)bufptr % 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// write file entries
|
||||
for (FileQueue::iterator it = pDownloadQueue->GetFileQueue()->begin(); it != pDownloadQueue->GetFileQueue()->end(); it++)
|
||||
for (DownloadQueue::iterator it = pDownloadQueue->begin(); it != pDownloadQueue->end(); it++)
|
||||
{
|
||||
unsigned long iSizeHi, iSizeLo;
|
||||
FileInfo* pFileInfo = *it;
|
||||
SNZBListResponseFileEntry* pListAnswer = (SNZBListResponseFileEntry*) bufptr;
|
||||
SNZBListResponseEntry* pListAnswer = (SNZBListResponseEntry*) bufptr;
|
||||
pListAnswer->m_iID = htonl(pFileInfo->GetID());
|
||||
|
||||
int iNZBIndex = 0;
|
||||
for (unsigned int i = 0; i < pDownloadQueue->GetNZBInfoList()->size(); i++)
|
||||
{
|
||||
iNZBIndex++;
|
||||
if (pDownloadQueue->GetNZBInfoList()->at(i) == pFileInfo->GetNZBInfo())
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
pListAnswer->m_iNZBIndex = htonl(iNZBIndex);
|
||||
|
||||
Util::SplitInt64(pFileInfo->GetSize(), &iSizeHi, &iSizeLo);
|
||||
pListAnswer->m_iFileSizeLo = htonl(iSizeLo);
|
||||
pListAnswer->m_iFileSizeHi = htonl(iSizeHi);
|
||||
@@ -505,27 +401,30 @@ void ListBinCommand::Execute()
|
||||
pListAnswer->m_iRemainingSizeHi = htonl(iSizeHi);
|
||||
pListAnswer->m_bFilenameConfirmed = htonl(pFileInfo->GetFilenameConfirmed());
|
||||
pListAnswer->m_bPaused = htonl(pFileInfo->GetPaused());
|
||||
pListAnswer->m_iNZBFilenameLen = htonl(strlen(pFileInfo->GetNZBInfo()->GetFilename()) + 1);
|
||||
pListAnswer->m_iSubjectLen = htonl(strlen(pFileInfo->GetSubject()) + 1);
|
||||
pListAnswer->m_iFilenameLen = htonl(strlen(pFileInfo->GetFilename()) + 1);
|
||||
bufptr += sizeof(SNZBListResponseFileEntry);
|
||||
pListAnswer->m_iDestDirLen = htonl(strlen(pFileInfo->GetNZBInfo()->GetDestDir()) + 1);
|
||||
bufptr += sizeof(SNZBListResponseEntry);
|
||||
strcpy(bufptr, pFileInfo->GetNZBInfo()->GetFilename());
|
||||
bufptr += ntohl(pListAnswer->m_iNZBFilenameLen);
|
||||
strcpy(bufptr, pFileInfo->GetSubject());
|
||||
bufptr += ntohl(pListAnswer->m_iSubjectLen);
|
||||
strcpy(bufptr, pFileInfo->GetFilename());
|
||||
bufptr += ntohl(pListAnswer->m_iFilenameLen);
|
||||
strcpy(bufptr, pFileInfo->GetNZBInfo()->GetDestDir());
|
||||
bufptr += ntohl(pListAnswer->m_iDestDirLen);
|
||||
// align struct to 4-bytes, needed by ARM-processor (and may be others)
|
||||
if ((size_t)bufptr % 4 > 0)
|
||||
{
|
||||
pListAnswer->m_iFilenameLen = htonl(ntohl(pListAnswer->m_iFilenameLen) + 4 - (size_t)bufptr % 4);
|
||||
memset(bufptr, 0, 4 - (size_t)bufptr % 4); //suppress valgrind warning "uninitialized data"
|
||||
pListAnswer->m_iDestDirLen = htonl(ntohl(pListAnswer->m_iDestDirLen) + 4 - (size_t)bufptr % 4);
|
||||
bufptr += 4 - (size_t)bufptr % 4;
|
||||
}
|
||||
}
|
||||
|
||||
g_pQueueCoordinator->UnlockQueue();
|
||||
|
||||
ListResponse.m_iNrTrailingNZBEntries = htonl(iNrNZBEntries);
|
||||
ListResponse.m_iNrTrailingPPPEntries = htonl(iNrPPPEntries);
|
||||
ListResponse.m_iNrTrailingFileEntries = htonl(iNrFileEntries);
|
||||
ListResponse.m_iNrTrailingEntries = htonl(NrEntries);
|
||||
ListResponse.m_iTrailingDataLength = htonl(bufsize);
|
||||
}
|
||||
|
||||
@@ -537,14 +436,11 @@ void ListBinCommand::Execute()
|
||||
ListResponse.m_iRemainingSizeHi = htonl(iSizeHi);
|
||||
ListResponse.m_iRemainingSizeLo = htonl(iSizeLo);
|
||||
ListResponse.m_iDownloadLimit = htonl((int)(g_pOptions->GetDownloadRate() * 1024));
|
||||
ListResponse.m_bDownloadPaused = htonl(g_pOptions->GetPauseDownload());
|
||||
ListResponse.m_bDownload2Paused = htonl(g_pOptions->GetPauseDownload2());
|
||||
ListResponse.m_bPostPaused = htonl(g_pOptions->GetPausePostProcess());
|
||||
ListResponse.m_bScanPaused = htonl(g_pOptions->GetPauseScan());
|
||||
ListResponse.m_bServerPaused = htonl(g_pOptions->GetPause());
|
||||
ListResponse.m_iThreadCount = htonl(Thread::GetThreadCount() - 1); // not counting itself
|
||||
PostQueue* pPostQueue = g_pQueueCoordinator->LockQueue()->GetPostQueue();
|
||||
PostQueue* pPostQueue = g_pPrePostProcessor->LockPostQueue();
|
||||
ListResponse.m_iPostJobCount = htonl(pPostQueue->size());
|
||||
g_pQueueCoordinator->UnlockQueue();
|
||||
g_pPrePostProcessor->UnlockPostQueue();
|
||||
|
||||
int iUpTimeSec, iDnTimeSec;
|
||||
long long iAllBytes;
|
||||
@@ -552,7 +448,7 @@ void ListBinCommand::Execute()
|
||||
g_pQueueCoordinator->CalcStat(&iUpTimeSec, &iDnTimeSec, &iAllBytes, &bStandBy);
|
||||
ListResponse.m_iUpTimeSec = htonl(iUpTimeSec);
|
||||
ListResponse.m_iDownloadTimeSec = htonl(iDnTimeSec);
|
||||
ListResponse.m_bDownloadStandBy = htonl(bStandBy);
|
||||
ListResponse.m_bServerStandBy = htonl(bStandBy);
|
||||
Util::SplitInt64(iAllBytes, &iSizeHi, &iSizeLo);
|
||||
ListResponse.m_iDownloadedBytesHi = htonl(iSizeHi);
|
||||
ListResponse.m_iDownloadedBytesLo = htonl(iSizeLo);
|
||||
@@ -635,7 +531,6 @@ void LogBinCommand::Execute()
|
||||
if ((size_t)bufptr % 4 > 0)
|
||||
{
|
||||
pLogAnswer->m_iTextLen = htonl(ntohl(pLogAnswer->m_iTextLen) + 4 - (size_t)bufptr % 4);
|
||||
memset(bufptr, 0, 4 - (size_t)bufptr % 4); //suppress valgrind warning "uninitialized data"
|
||||
bufptr += 4 - (size_t)bufptr % 4;
|
||||
}
|
||||
}
|
||||
@@ -672,11 +567,10 @@ void EditQueueBinCommand::Execute()
|
||||
int iNrEntries = ntohl(EditQueueRequest.m_iNrTrailingEntries);
|
||||
int iAction = ntohl(EditQueueRequest.m_iAction);
|
||||
int iOffset = ntohl(EditQueueRequest.m_iOffset);
|
||||
int iTextLen = ntohl(EditQueueRequest.m_iTextLen);
|
||||
bool bSmartOrder = ntohl(EditQueueRequest.m_bSmartOrder);
|
||||
unsigned int iBufLength = ntohl(EditQueueRequest.m_iTrailingDataLength);
|
||||
|
||||
if (iNrEntries * sizeof(int32_t) + iTextLen != iBufLength)
|
||||
if (iNrEntries * sizeof(int32_t) != iBufLength)
|
||||
{
|
||||
error("Invalid struct size");
|
||||
return;
|
||||
@@ -688,12 +582,10 @@ void EditQueueBinCommand::Execute()
|
||||
return;
|
||||
}
|
||||
|
||||
char* pBuf = (char*)malloc(iBufLength);
|
||||
char* szText = NULL;
|
||||
int32_t* pIDs = NULL;
|
||||
int32_t* pIDs = (int32_t*)malloc(iBufLength);
|
||||
|
||||
// Read from the socket until nothing remains
|
||||
char* pBufPtr = pBuf;
|
||||
char* pBufPtr = (char*)pIDs;
|
||||
int NeedBytes = iBufLength;
|
||||
int iResult = 0;
|
||||
while (NeedBytes > 0)
|
||||
@@ -708,31 +600,17 @@ void EditQueueBinCommand::Execute()
|
||||
pBufPtr += iResult;
|
||||
NeedBytes -= iResult;
|
||||
}
|
||||
bool bOK = NeedBytes == 0;
|
||||
|
||||
if (bOK)
|
||||
{
|
||||
szText = iTextLen > 0 ? pBuf : NULL;
|
||||
pIDs = (int32_t*)(pBuf + iTextLen);
|
||||
}
|
||||
|
||||
IDList cIDList;
|
||||
QueueEditor::IDList cIDList;
|
||||
cIDList.reserve(iNrEntries);
|
||||
for (int i = 0; i < iNrEntries; i++)
|
||||
{
|
||||
cIDList.push_back(ntohl(pIDs[i]));
|
||||
}
|
||||
|
||||
if (iAction < eRemoteEditActionPostMoveOffset)
|
||||
{
|
||||
bOK = g_pQueueCoordinator->GetQueueEditor()->EditList(&cIDList, bSmartOrder, (QueueEditor::EEditAction)iAction, iOffset, szText);
|
||||
}
|
||||
else
|
||||
{
|
||||
bOK = g_pPrePostProcessor->QueueEditList(&cIDList, (PrePostProcessor::EEditAction)iAction, iOffset);
|
||||
}
|
||||
free(pIDs);
|
||||
|
||||
free(pBuf);
|
||||
bool bOK = g_pQueueCoordinator->GetQueueEditor()->EditList(&cIDList, bSmartOrder, (QueueEditor::EEditAction)iAction, iOffset);
|
||||
|
||||
if (bOK)
|
||||
{
|
||||
@@ -762,7 +640,7 @@ void PostQueueBinCommand::Execute()
|
||||
int bufsize = 0;
|
||||
|
||||
// Make a data structure and copy all the elements of the list into it
|
||||
PostQueue* pPostQueue = g_pQueueCoordinator->LockQueue()->GetPostQueue();
|
||||
PostQueue* pPostQueue = g_pPrePostProcessor->LockPostQueue();
|
||||
|
||||
int NrEntries = pPostQueue->size();
|
||||
|
||||
@@ -771,10 +649,10 @@ void PostQueueBinCommand::Execute()
|
||||
for (PostQueue::iterator it = pPostQueue->begin(); it != pPostQueue->end(); it++)
|
||||
{
|
||||
PostInfo* pPostInfo = *it;
|
||||
bufsize += strlen(pPostInfo->GetNZBInfo()->GetFilename()) + 1;
|
||||
bufsize += strlen(pPostInfo->GetNZBFilename()) + 1;
|
||||
bufsize += strlen(pPostInfo->GetParFilename()) + 1;
|
||||
bufsize += strlen(pPostInfo->GetInfoName()) + 1;
|
||||
bufsize += strlen(pPostInfo->GetNZBInfo()->GetDestDir()) + 1;
|
||||
bufsize += strlen(pPostInfo->GetDestDir()) + 1;
|
||||
bufsize += strlen(pPostInfo->GetProgressLabel()) + 1;
|
||||
// align struct to 4-bytes, needed by ARM-processor (and may be others)
|
||||
bufsize += bufsize % 4 > 0 ? 4 - bufsize % 4 : 0;
|
||||
@@ -794,19 +672,19 @@ void PostQueueBinCommand::Execute()
|
||||
pPostQueueAnswer->m_iFileProgress = htonl(pPostInfo->GetFileProgress());
|
||||
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_iNZBFilenameLen = htonl(strlen(pPostInfo->GetNZBFilename()) + 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_iDestDirLen = htonl(strlen(pPostInfo->GetDestDir()) + 1);
|
||||
pPostQueueAnswer->m_iProgressLabelLen = htonl(strlen(pPostInfo->GetProgressLabel()) + 1);
|
||||
bufptr += sizeof(SNZBPostQueueResponseEntry);
|
||||
strcpy(bufptr, pPostInfo->GetNZBInfo()->GetFilename());
|
||||
strcpy(bufptr, pPostInfo->GetNZBFilename());
|
||||
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());
|
||||
strcpy(bufptr, pPostInfo->GetDestDir());
|
||||
bufptr += ntohl(pPostQueueAnswer->m_iDestDirLen);
|
||||
strcpy(bufptr, pPostInfo->GetProgressLabel());
|
||||
bufptr += ntohl(pPostQueueAnswer->m_iProgressLabelLen);
|
||||
@@ -814,12 +692,11 @@ void PostQueueBinCommand::Execute()
|
||||
if ((size_t)bufptr % 4 > 0)
|
||||
{
|
||||
pPostQueueAnswer->m_iProgressLabelLen = htonl(ntohl(pPostQueueAnswer->m_iProgressLabelLen) + 4 - (size_t)bufptr % 4);
|
||||
memset(bufptr, 0, 4 - (size_t)bufptr % 4); //suppress valgrind warning "uninitialized data"
|
||||
bufptr += 4 - (size_t)bufptr % 4;
|
||||
}
|
||||
}
|
||||
|
||||
g_pQueueCoordinator->UnlockQueue();
|
||||
g_pPrePostProcessor->UnlockPostQueue();
|
||||
|
||||
PostQueueResponse.m_iNrTrailingEntries = htonl(NrEntries);
|
||||
PostQueueResponse.m_iTrailingDataLength = htonl(bufsize);
|
||||
@@ -833,7 +710,10 @@ void PostQueueBinCommand::Execute()
|
||||
send(m_iSocket, buf, bufsize, 0);
|
||||
}
|
||||
|
||||
free(buf);
|
||||
if (buf)
|
||||
{
|
||||
free(buf);
|
||||
}
|
||||
}
|
||||
|
||||
void WriteLogBinCommand::Execute()
|
||||
@@ -892,105 +772,3 @@ void WriteLogBinCommand::Execute()
|
||||
|
||||
free(pRecvBuffer);
|
||||
}
|
||||
|
||||
void ScanBinCommand::Execute()
|
||||
{
|
||||
SNZBScanRequest ScanRequest;
|
||||
if (!ReceiveRequest(&ScanRequest, sizeof(ScanRequest)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
g_pPrePostProcessor->ScanNZBDir();
|
||||
SendBoolResponse(true, "Scan-Command scheduled successfully");
|
||||
}
|
||||
|
||||
void HistoryBinCommand::Execute()
|
||||
{
|
||||
SNZBHistoryRequest HistoryRequest;
|
||||
if (!ReceiveRequest(&HistoryRequest, sizeof(HistoryRequest)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SNZBHistoryResponse HistoryResponse;
|
||||
memset(&HistoryResponse, 0, sizeof(HistoryResponse));
|
||||
HistoryResponse.m_MessageBase.m_iSignature = htonl(NZBMESSAGE_SIGNATURE);
|
||||
HistoryResponse.m_MessageBase.m_iStructSize = htonl(sizeof(HistoryResponse));
|
||||
HistoryResponse.m_iEntrySize = htonl(sizeof(SNZBHistoryResponseEntry));
|
||||
|
||||
char* buf = NULL;
|
||||
int bufsize = 0;
|
||||
|
||||
// Make a data structure and copy all the elements of the list into it
|
||||
DownloadQueue* pDownloadQueue = g_pQueueCoordinator->LockQueue();
|
||||
|
||||
// calculate required buffer size for nzbs
|
||||
int iNrNZBEntries = pDownloadQueue->GetHistoryList()->size();
|
||||
bufsize += iNrNZBEntries * sizeof(SNZBHistoryResponseEntry);
|
||||
for (HistoryList::iterator it = pDownloadQueue->GetHistoryList()->begin(); it != pDownloadQueue->GetHistoryList()->end(); it++)
|
||||
{
|
||||
NZBInfo* pNZBInfo = *it;
|
||||
bufsize += strlen(pNZBInfo->GetFilename()) + 1;
|
||||
bufsize += strlen(pNZBInfo->GetDestDir()) + 1;
|
||||
bufsize += strlen(pNZBInfo->GetCategory()) + 1;
|
||||
bufsize += strlen(pNZBInfo->GetQueuedFilename()) + 1;
|
||||
// align struct to 4-bytes, needed by ARM-processor (and may be others)
|
||||
bufsize += bufsize % 4 > 0 ? 4 - bufsize % 4 : 0;
|
||||
}
|
||||
|
||||
buf = (char*) malloc(bufsize);
|
||||
char* bufptr = buf;
|
||||
|
||||
// write nzb entries
|
||||
for (NZBInfoList::iterator it = pDownloadQueue->GetHistoryList()->begin(); it != pDownloadQueue->GetHistoryList()->end(); it++)
|
||||
{
|
||||
unsigned long iSizeHi, iSizeLo;
|
||||
NZBInfo* pNZBInfo = *it;
|
||||
SNZBHistoryResponseEntry* pListAnswer = (SNZBHistoryResponseEntry*) bufptr;
|
||||
Util::SplitInt64(pNZBInfo->GetSize(), &iSizeHi, &iSizeLo);
|
||||
pListAnswer->m_iID = htonl(pNZBInfo->GetID());
|
||||
pListAnswer->m_tTime = htonl((int)pNZBInfo->GetHistoryTime());
|
||||
pListAnswer->m_iSizeLo = htonl(iSizeLo);
|
||||
pListAnswer->m_iSizeHi = htonl(iSizeHi);
|
||||
pListAnswer->m_iFileCount = htonl(pNZBInfo->GetFileCount());
|
||||
pListAnswer->m_iParStatus = htonl(pNZBInfo->GetParStatus());
|
||||
pListAnswer->m_iScriptStatus = htonl(pNZBInfo->GetScriptStatus());
|
||||
pListAnswer->m_iFilenameLen = htonl(strlen(pNZBInfo->GetFilename()) + 1);
|
||||
pListAnswer->m_iDestDirLen = htonl(strlen(pNZBInfo->GetDestDir()) + 1);
|
||||
pListAnswer->m_iCategoryLen = htonl(strlen(pNZBInfo->GetCategory()) + 1);
|
||||
pListAnswer->m_iQueuedFilenameLen = htonl(strlen(pNZBInfo->GetQueuedFilename()) + 1);
|
||||
bufptr += sizeof(SNZBHistoryResponseEntry);
|
||||
strcpy(bufptr, pNZBInfo->GetFilename());
|
||||
bufptr += ntohl(pListAnswer->m_iFilenameLen);
|
||||
strcpy(bufptr, pNZBInfo->GetDestDir());
|
||||
bufptr += ntohl(pListAnswer->m_iDestDirLen);
|
||||
strcpy(bufptr, pNZBInfo->GetCategory());
|
||||
bufptr += ntohl(pListAnswer->m_iCategoryLen);
|
||||
strcpy(bufptr, pNZBInfo->GetQueuedFilename());
|
||||
bufptr += ntohl(pListAnswer->m_iQueuedFilenameLen);
|
||||
// align struct to 4-bytes, needed by ARM-processor (and may be others)
|
||||
if ((size_t)bufptr % 4 > 0)
|
||||
{
|
||||
pListAnswer->m_iQueuedFilenameLen = htonl(ntohl(pListAnswer->m_iQueuedFilenameLen) + 4 - (size_t)bufptr % 4);
|
||||
memset(bufptr, 0, 4 - (size_t)bufptr % 4); //suppress valgrind warning "uninitialized data"
|
||||
bufptr += 4 - (size_t)bufptr % 4;
|
||||
}
|
||||
}
|
||||
|
||||
g_pQueueCoordinator->UnlockQueue();
|
||||
|
||||
HistoryResponse.m_iNrTrailingEntries = htonl(iNrNZBEntries);
|
||||
HistoryResponse.m_iTrailingDataLength = htonl(bufsize);
|
||||
|
||||
// Send the request answer
|
||||
send(m_iSocket, (char*) &HistoryResponse, sizeof(HistoryResponse), 0);
|
||||
|
||||
// Send the data
|
||||
if (bufsize > 0)
|
||||
{
|
||||
send(m_iSocket, buf, bufsize, 0);
|
||||
}
|
||||
|
||||
free(buf);
|
||||
}
|
||||
|
||||
16
BinRpc.h
16
BinRpc.h
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2005 Bo Cordes Petersen <placebodk@sourceforge.net>
|
||||
* Copyright (C) 2007-2009 Andrei Prygounkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2005 Bo Cordes Petersen <placebodk@sourceforge.net>
|
||||
* Copyright (C) 2007 Andrei Prygounkov <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
|
||||
@@ -128,16 +128,4 @@ public:
|
||||
virtual void Execute();
|
||||
};
|
||||
|
||||
class ScanBinCommand: public BinCommand
|
||||
{
|
||||
public:
|
||||
virtual void Execute();
|
||||
};
|
||||
|
||||
class HistoryBinCommand: public BinCommand
|
||||
{
|
||||
public:
|
||||
virtual void Execute();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
975
ChangeLog
975
ChangeLog
@@ -1,620 +1,355 @@
|
||||
nzbget-0.7.0:
|
||||
- added history: new option <KeepHistory>, new remote subcommand <H> for
|
||||
commands <L> (list history entries) and <E> (delete history entries,
|
||||
return history item, postprocess history item), new RPC-command <History>
|
||||
and subcommands <HistoryDelete>, <HistoryReturn>, <HistoryProcess> for
|
||||
command <EditQueue>;
|
||||
- added support for JSON-P (extension of JSON-RPC);
|
||||
- changed the result code returning status <ERROR> for postprocessing script
|
||||
from <1> to <94> (needed to show the proper script status in history);
|
||||
- improved the detection of new files in incoming nzb directory: now the
|
||||
scanner does not rely on system datum, but tracks the changing of file
|
||||
sizes during a last few (<NzbDirFileAge>) seconds instead;
|
||||
- improvements in example postprocessing script: 1) if download contains
|
||||
only par2-files the script do not delete them during cleanup;
|
||||
2) if download contains only nzb-files the script moves them to incoming
|
||||
nzb-directory for further download;
|
||||
- improved formatting of groups and added time info in curses output mode;
|
||||
- added second pause register, which is independent of main pause-state and
|
||||
therfore is intended for usage from external scripts;
|
||||
that allows to pause download without interfering with options
|
||||
<ParPauseQueue> and <PostPauseQueue> and scheduler tasks <PauseDownload>
|
||||
and <UnpauseDownload> - they all work with first (default) pause register;
|
||||
new subcommand <D2> for commands <--pause/-P> and <--unpause/-U>;
|
||||
new RPC-command <pausedownload2> and <resumedownload2>;
|
||||
existing RPC-commands <pause> und <resume> renamed to <pausedownload> and
|
||||
<resumedownload>;
|
||||
new field <Download2Paused> in result struct for RPC-command <status>;
|
||||
existing fields <ServerPaused> and <ParJobCount> renamed to
|
||||
<DownloadPaused> and <PostJobCount>;
|
||||
old RPC-commands and fields still exist for compatibility;
|
||||
the status output of command <--list/-L> indicates the state of second
|
||||
pause register;
|
||||
key <P> in curses-frontend can unpause second pause-register;
|
||||
- nzbprocess-script (option <NZBProcess>) can now set category and
|
||||
post-processing parameters for nzb-file;
|
||||
- redesigned server pool and par-checker to avoid using of semaphores
|
||||
(which are very platform specific);
|
||||
- added subcommand <S> to remote commands <--pause/-P> and <--unpause/-U> to
|
||||
pause/unpause the scanning of incoming nzb-directory;
|
||||
- added commands <PauseScan> and <UnpauseScan> for scheduler option
|
||||
<TaskX.Command>;
|
||||
- added remote commands <PauseScan> and <ResumeScan> for XML-/JSON-RPC;
|
||||
- command <pause post-processing> now not only pauses the post-processing
|
||||
queue but also pauses the current post-processing job (par-job or
|
||||
script-job);
|
||||
however the script-job can be paused only after the next line printed to
|
||||
screen;
|
||||
- improved error reporting while parsing nzb-files;
|
||||
- added field <NZBID> to NZBInfo; the field is now returned by XML-/JSON-RPC
|
||||
methods <listfiles>, <listgroups> and <postqueue>;
|
||||
- improvements in configure script;
|
||||
- added support for platforms without IPv6 (they do not have <getaddrinfo>);
|
||||
- debug-messages generated on early stages during initializing are now
|
||||
printed to screen/log-file;
|
||||
- messages about obsolete options are now printed to screen/log-file;
|
||||
- imporved example postprocessing script: added support for external
|
||||
configuration file, postprocessing parameters and configuration via
|
||||
web-interface;
|
||||
- option <TaskX.Process> now can contain parameters which must be passed
|
||||
to the script;
|
||||
- added pausing/resuming for post-processor queue;
|
||||
added new modifier <O> to remote commands <--pause/-P> and <--unpause/-U>;
|
||||
added new commands <postpause> and <postresume> to XML-/JSON-RPC;
|
||||
extended output of remote command <--list/-L> to indicate paused state
|
||||
of post-processor queue; extended command <status> of XML-/JSON-RPC
|
||||
with field <PostPause>;
|
||||
- changed the command line syntax for requesting of post-processor queue
|
||||
from <-O> to <-L O> for consistency with other post-queue related
|
||||
commands (<-P O>, <-U O> and <-E O>);
|
||||
- improved example post-processing script: added support for delayed
|
||||
par-check (try unrar first, par-repair if unrar failed);
|
||||
- added modifier <O> to command <-E/--edit> for editing of
|
||||
post-processor-queue;
|
||||
following subcommands are supported: <+/-offset>, <T>, <B>, <D>;
|
||||
subcommand <D> supports deletion of queued post-jobs and active job as well;
|
||||
deletion of active job means the cancelling of par-check/repair or
|
||||
terminating of post-processing-script (including child processes of the
|
||||
script);
|
||||
updated remote-server to support new edit-subcommands in XML/JSON-RPC;
|
||||
- extended the syntax of option <TaskX.Time> in two ways:
|
||||
1) it now accepts multiple comma-separated values;
|
||||
2) an asterix as hours-part means <every hour>;
|
||||
- added svn revision number to version string (commands <-v> and <-V>,
|
||||
startup log entry);
|
||||
svn revision is automatically read from svn-repository on each build;
|
||||
- added estimated remaining time and better distinguishing of server state
|
||||
in command <--list/-L>;
|
||||
- added new return code (93) for post-processing script to indicate
|
||||
successful processing; that results in cleaning up of download queue
|
||||
if option <ParCleanupQueue> is active;
|
||||
- added readonly options <AppBin>, <ConfigFile> and <Version> for usage
|
||||
in processing scripts (options are available as environment variables
|
||||
<NZBOP_APPBIN>, <NZBOP_CONFIGFILE> and <NZBOP_VERSION>);
|
||||
- renamed ParStatus constant <FAILED> to <FAILURE> for a consistence with
|
||||
ScriptStatus constant <FAILURE>, that also affects the results of
|
||||
RPC-command <history>;
|
||||
- added a new return code <95/POSTPROCESS_NONE> for post-processing scripts
|
||||
for cases when pp-script skips all post-processing work (typically upon
|
||||
a user's request via a pp-parameter);
|
||||
modified the example post-processing script to return the new code
|
||||
instead of a error code when a pp-parameter <PostProcess> was set to <no>;
|
||||
- added field <PostTime> to result of RPC-Command <listfiles> and fields
|
||||
<MinPostTime> and <MaxPostTime> for command <listgroups>;
|
||||
- in <curses> and <colored> output-modes the download speed is now printed
|
||||
with one decimal digit when the speed is lower than 10 KB/s;
|
||||
- improvement in example post-processing script: added check for existence
|
||||
of <unrar> and command <wc>;
|
||||
- added shell batch file for windows (nzbget-shell.bat);
|
||||
thanks to orbisvicis (orbisvicis@users.sourceforge.net) for the script;
|
||||
- added debian style init script (nzbgetd);
|
||||
thanks to orbisvicis (orbisvicis@users.sourceforge.net) for the script;
|
||||
- added the returning of a proper HTTP error code if the authorization was
|
||||
failed on RPC-calls;
|
||||
thanks to jdembski (jdembski@users.sourceforge.net) for the patch;
|
||||
- changed the sleep-time during the throttling of bandwidth from 200ms to
|
||||
10ms in order to achieve better uniformity;
|
||||
- modified example postprocessing script to not use the command <dirname>,
|
||||
which is not always available;
|
||||
thanks to Ger Teunis for the patch;
|
||||
- improved example post-processing script: added the check for existence
|
||||
of destination directory to return a proper ERROR-code (important for
|
||||
reprocessing of history items);
|
||||
- by saving the queue to disk now using relative paths for the list of
|
||||
compeled files to reduce the file's size;
|
||||
- eliminated few compiler warnings on GCC;
|
||||
- fixed: when option <DaemonUserName> was specified and nzbget was
|
||||
started as root, the lockfile was not removed;
|
||||
- fixed: nothing was downloaded when the option <Retries> was set to <0>;
|
||||
- fixed: base64 decoding function used by RPC-method <append> sometimes
|
||||
failed, in particular when called from Ruby-language;
|
||||
- fixed: JSON-RPC-commands failed, if parameters were placed before method
|
||||
name in the request;
|
||||
- fixed: RPC-method <append> did not work properly on Posix systems
|
||||
(it worked only on Windows);
|
||||
- fixed compilation error when using native curses library on OpenSolaris;
|
||||
- fixed linking error on OpenSolaris when using GnuTLS;
|
||||
- fixed: option <ContinuePartial> did not work;
|
||||
- fixed: seg. fault in service mode on program start (Windows only);
|
||||
- fixed: environment block was not passed correctly to child process,
|
||||
what could result in seg faults (windows only);
|
||||
- fixed: returning the postprocessing exit code <92 - par-check all
|
||||
collections> when there were no par-files results in endless calling
|
||||
of postprocessing script;
|
||||
- fixed compatibility issues with OS/2.
|
||||
|
||||
nzbget-0.6.0:
|
||||
- added scheduler; new options <TaskX.Time>, <TaskX.WeekDays>,
|
||||
<TaskX.Command>, <TaskX.DownloadRate> and <TaskX.Process>;
|
||||
- added support for postprocess-parameters; new subcommand <O> of remote
|
||||
command <E> to add/modify pp-parameter for group (nzb-file); new
|
||||
XML-/JSON-RPC-subcommand <GroupSetParameter> of method <editqueue> for
|
||||
the same purpose; updated example configuration file and example
|
||||
postprocess-script to indicate new method of passing arguments via
|
||||
environment variables;
|
||||
- added subcommands <F>, <G> and <S> to command line switch <-L/--list>,
|
||||
which prints list of files, groups or only status info respectively;
|
||||
extended binary communication protocol to transfer nzb-infos in addition
|
||||
to file-infos;
|
||||
- added new subcommand <M> to edit-command <E> for merging of two (or more)
|
||||
groups (useful after adding pars from a separate nzb-file);
|
||||
- added option <MergeNzb> to automatically merge nzb-files with the same
|
||||
filename (useful by adding pars from a different source);
|
||||
- added script-processing of files in incoming directory to allow automatic
|
||||
unpacking and queueing of compressed nzb-files; new option <NzbProcess>;
|
||||
- added the printing of post-process-parameters for groups in command
|
||||
<--list G>;
|
||||
- added the printing of nzbget version into the log-file on start;
|
||||
- added option <DeleteCleanupDisk> to automatically delete already downloaded
|
||||
files from disk if nzb-file was deleted from queue (the download was
|
||||
cancelled);
|
||||
- added option <ParTimeLimit> to define the max time allowed for par-repair;
|
||||
- added command <--scan/-S> to execute the scan of nzb-directory on remote
|
||||
server;
|
||||
- changed the method to pass arguments to postprocess/nzbprocess: now using
|
||||
environment variables (old method is still supported for compatibility with
|
||||
existing scripts);
|
||||
- added the passing of nzbget-options to postprocess/nzbprocess scripts as
|
||||
environment variables;
|
||||
- extended the communication between nzbget and post-process-script:
|
||||
collections are now detected even if parcheck is disabled;
|
||||
- added support for delayed par-check/repair: post-process-script can request
|
||||
par-check/repair using special exit codes to repair current collection or
|
||||
all collections;
|
||||
- implemented the normalizing of option names and values in option list; the
|
||||
command <-p> also prints normalized names and values now; that makes the
|
||||
parsing of output of command <-p> for external scripts easier;
|
||||
- replaced option <PostLogKind> with new option <ProcessLogKind> which is now
|
||||
used by all scripts (PostProcess, NzbProcess, TaskX.Process);
|
||||
- improved entering to paused state on connection errors (do not retry failed
|
||||
downloads if pause was activated);
|
||||
- improved error reporting on decoding failures;
|
||||
- improved compatibility of yenc-decoder;
|
||||
- improved the speed of deleting of groups from download queue (by avoiding
|
||||
the saving of queue after the deleting of each individual file);
|
||||
- updated configure-script for better compatibility with FreeBSD;
|
||||
- cleaning up of download queue (option <ParCleanupQueue>) and deletion of
|
||||
source nzb-file (option <NzbCleanupDisk>) after par-repair now works also
|
||||
if par-repair was cancelled (option <ParTimeLimit>); since required
|
||||
par-files were already downloaded the repair in an external tool is
|
||||
possible;
|
||||
- added workaround to avoid hangs in child processes (by starting of
|
||||
postprocess or nzbprocess), observed on uClibC based systems;
|
||||
- fixed: TLS/SSL didn't work in standalone mode;
|
||||
- fixed compatibility issues with Mac OS X;
|
||||
- fixed: not all necessary par2-files were unpaused on first request for
|
||||
par-blocks (although harmless, because additional files were unpaused
|
||||
later anyway);
|
||||
- fixed small memory leak appeared if process-script could not be started;
|
||||
- fixed: configure-script could not detect the right syntax for function
|
||||
<ctime_r> on OpenSolaris.
|
||||
- fixed: files downloaded with disabled decoder (option decode=no) sometimes
|
||||
were malformed and could not be decoded;
|
||||
- fixed: empty string parameters did not always work in XML-RPC.
|
||||
|
||||
nzbget-0.5.1:
|
||||
- improved the check of server responses to prevent unnecessary retrying
|
||||
if the article does not exist on server;
|
||||
- fixed: seg.fault in standalone mode if used without specifying the
|
||||
category (e.g. without switch <-K>);
|
||||
- fixed: download speed indicator could report not-null values in
|
||||
standby-mode (when paused);
|
||||
- fixed: parameter <category> in JSON/XML-RPC was not properly decoded by
|
||||
server, making the setting of a nested category (containing slash or
|
||||
backslash character) via nzbgetweb not possible;
|
||||
|
||||
nzbget-0.5.0:
|
||||
- added TLS/SSL-support for encrypted communication with news-servers;
|
||||
- added IPv6-support for communication with news-servers as well as for
|
||||
communication between nzbget-server and nzbget-client;
|
||||
- added support for categories to organize downloaded files;
|
||||
- new option <AppendCategoryDir> to create the subdirectory for each category;
|
||||
- new switch <-K> for usage with switch <-A> to define a category during
|
||||
the adding a file to download queue;
|
||||
- new command <K> in switch <-E> to change the category of nzb-file in
|
||||
download queue; the already downloaded files are automatically moved to new
|
||||
directory if the option <AppendCategoryDir> is active;
|
||||
- new parameter <Category> in XML-/JSON-RPC-command <editqueue> to allow the
|
||||
changing of category via those protocols;
|
||||
- new parameter in a call to post-process-script with category name;
|
||||
- scanning of subdirectories inside incoming nzb-directory to automatically
|
||||
assign category names; nested categories are supported;
|
||||
- added option <ServerX.JoinGroup> to connect to servers, that do not accept
|
||||
<GROUP>-command;
|
||||
- added example post-process script for unraring of downloaded files
|
||||
(POSIX only);
|
||||
- added options <ParPauseQueue> and <PostPauseQueue> useful on slow CPUs;
|
||||
- added option <NzbCleanupDisk> to delete source nzb-file after successful
|
||||
download and parcheck;
|
||||
- switch <-P> can now be used together with switches <-s> and <-D> to start
|
||||
server/daemon in paused state;
|
||||
- changed the type of messages logged in a case of connection errors from
|
||||
<DEBUG> to <ERROR> to provide better error reporting;
|
||||
- now using OS-specific line-endings in log-file and brokenlog-file: LF on
|
||||
Posix and CRLF on Windows;
|
||||
- added detection of adjusting of system clock to correct uptime/download
|
||||
time (for NAS-devices, that do not have internal clock and set time from
|
||||
internet after booting, while nzbget may be already running);
|
||||
- added the printing of stack on segmentation faults (if configured with
|
||||
<--enable-debug>, POSIX only);
|
||||
- added option <DumpCore> for better debugging on Linux in a case of abnormal
|
||||
program termination;
|
||||
- fixed: configure-script could not automatically find libsigc++ on 64-bit
|
||||
systems;
|
||||
- few other small fixes;
|
||||
|
||||
nzbget-0.4.1:
|
||||
- to avoid accidental deletion of file in curses-frontend the key <D>
|
||||
now must be pressed in uppercase;
|
||||
- options <username> and <password> in news-server's configuration are now
|
||||
optional;
|
||||
- added the server's name to the detail-log-message, displayed on the start
|
||||
of article's download;
|
||||
- added the option <AllowReProcess> to help to post-process-scripts, which
|
||||
make par-check/-repair on it's own;
|
||||
- improved download-speed-meter: it uses now a little bit less cpu and
|
||||
calculates the speed for the last 30 seconds (instead of 5 seconds),
|
||||
providing better accuracy; Thanks to ydrol <ydrol@users.sourceforge.net>
|
||||
for the patch;
|
||||
- reduced CPU-usage in curses-outputmode; Thanks to ydrol for the patch
|
||||
<ydrol@users.sourceforge.net>;
|
||||
- fixed: line-endings in windows-style (CR-LF) in config-file were not
|
||||
read properly;
|
||||
- fixed: trailing spaces in nzb-filenames (before the file's extension)
|
||||
caused errors on windows. Now they will be trimmed;
|
||||
- fixed: XML-RPC and JSON-RPC did not work on Big-Endian-CPUs (ARM, PPC, etc),
|
||||
preventing the using of web-interface;
|
||||
- fixed: umask-option did not allow to enable write-permissions for <group>
|
||||
and <others>;
|
||||
- fixed: in curses-outputmode the remote-client showed on first screen-update
|
||||
only one item of queue;
|
||||
- fixed: edit-commands with negative offset did not work via XML-RPC
|
||||
(but worked via JSON-RPC);
|
||||
- fixed incompatibility issues with gcc 4.3; Thanks to Paul Bredbury
|
||||
<brebs@users.sourceforge.net> for the patch;
|
||||
- fixed: segmentation fault if a file listed in nzb-file does not have any
|
||||
segments (articles);
|
||||
|
||||
nzbget-0.4.0:
|
||||
- added the support for XML-RPC and JSON-RPC to easier control the server
|
||||
from other applications;
|
||||
- added web-interface - it is available for download from NZBGet-project's
|
||||
home page as a separate package "web-interface";
|
||||
- added the automatic cleaning up of the download queue (deletion of unneeded
|
||||
paused par-files) after successful par-check/repair - new
|
||||
option <ParCleanupQueue>;
|
||||
- added option <DetailTarget> to allow to filter the (not so important)
|
||||
log-messages from articles' downloads (they have now the type <detail>
|
||||
instead of <info>);
|
||||
- added the gathering of progress-information during par-check; it is
|
||||
available via XML-RPC or JSON-RPC; it is also showed in web-interface;
|
||||
- improvements in internal decoder: added support for yEnc-files without
|
||||
ypart-statement (sometimes used for small files); added support for
|
||||
UU-format;
|
||||
- removed support for uulib-decoder (it did not work well anyway);
|
||||
- replaced the option <decoder (yenc, uulib, none)> with the option
|
||||
<decode (yes, no)>;
|
||||
- added detection of errors <server busy> and <remote server not available>
|
||||
(special case for NNTPCache-server) to consider them as connect-errors
|
||||
(and therefore not count as retries);
|
||||
- added check for incomplete articles (also mostly for NNTPCache-server) to
|
||||
differ such errors from CrcErrors (better error reporting);
|
||||
- improved error-reporting on moving of completed files from tmp- to
|
||||
dst-directory and added code to move files across drives if renaming fails;
|
||||
- improved handling of nzb-files with multiple collections in par-checker;
|
||||
- improved the parchecker: added the detection and processing of files
|
||||
splitted after parring;
|
||||
- added the queueing of post-process-scripts and waiting for script's
|
||||
completion before starting of a next job in postprocessor (par-job or
|
||||
script) to provide more balanced cpu utilization;
|
||||
- added the redirecting of post-process-script's output to log; new option
|
||||
<PostLogKind> to specify the default message-kind for unformatted
|
||||
log-messages;
|
||||
- added the returning of script-output by command <postqueue> via XML-RPC
|
||||
and JSON-RPC; the script-output is also showed in web-interface;
|
||||
- added the saving and restoring of the post-processor-queue (if server was
|
||||
stopped before all items were processed); new option <ReloadPostQueue>;
|
||||
- added new parameter to postprocess-script to indicate if any of par-jobs
|
||||
for the same nzb-file failed;
|
||||
- added remote command (switch O/--post) to request the post-processor-queue
|
||||
from server;
|
||||
- added remote command (switch -W/--write) to write messages to server's log;
|
||||
- added option <DiskSpace> to automatically pause the download on low disk
|
||||
space;
|
||||
- fixed few incompatibility-issues with unslung-platform on nslu2 (ARM);
|
||||
- fixed: articles with trailing text after binary data caused the decode
|
||||
failures and the reporting of CRC-errors;
|
||||
- fixed: dupecheck could cause seg.faults when all articles for a file failed;
|
||||
- fixed: by dupe-checking of files contained in nzb-file the files with the
|
||||
same size were ignored (not deleted from queue);
|
||||
- updated libpar2-patch for msvc to fix a segfault in libpar2 (windows only);
|
||||
- fixed: by registering the service on windows the fullpath to nzbget.exe
|
||||
was not always added to service's exename, making the registered service
|
||||
unusable;
|
||||
- fixed: the pausing of a group could cause the start of post-processing for
|
||||
that group;
|
||||
- fixed: too many info-messages <Need more N blocks> could be printed during
|
||||
par-check (appeared on posix only);
|
||||
|
||||
nzbget-0.3.1:
|
||||
- Greatly reduced the memory consumption by keeping articles' info on disk
|
||||
until the file download starts;
|
||||
- Implemented decode-on-the-fly-technique to reduce disk-io; downloaded
|
||||
and decoded data can also be saved directly to the destination file
|
||||
(without any intermediate files at all); this eliminates the necessity
|
||||
of joining of articles later (option "DirectWrite");
|
||||
- Improved communication with news-servers: connections are now keeped open
|
||||
until all files are downloaded (or server paused); this eliminates the
|
||||
need for establishing of connections and authorizations for each
|
||||
article and improves overal download speed;
|
||||
- Significantly better download speed is now possible on fast connection;
|
||||
it was limited by delays on starting of new articles' downloads;
|
||||
the synchronisation mechanism was reworked to fix this issue;
|
||||
- Download speed meter is much more accurate, especially on fast connections;
|
||||
this also means better speed throttling;
|
||||
- Speed optimisations in internal decoder (up to 25% faster);
|
||||
- CRC-calculation can be bypassed to increase performance on slow CPUs
|
||||
(option "CrcCheck");
|
||||
- Improved parsing of artcile's subject for better extracting of filename
|
||||
part from it and implemented a fallback-option if the parsing was incorrect;
|
||||
- Improved dupe check for files from the same nzb-request to detect reposted
|
||||
files and download only the best from them (if option "DupeCheck" is on);
|
||||
- Articles with incorrect CRC can be treated as "possibly recoverable errors"
|
||||
and relaunched for download (option "RetryOnCrcError"), it is useful if
|
||||
multiple servers are available;
|
||||
- Improved error-check for downloaded articles (crc-check and check for
|
||||
received message-id) decreases the number of broken files;
|
||||
- Extensions in curses-outputmode: added group-view-mode (key "G") to show
|
||||
items in download queue as groups, where one group represents all files
|
||||
from the same nzb-file; the editing of queue works also in group-mode
|
||||
(for all files in this group): pause/unpause/delete/move of groups;
|
||||
- Other extensions in curses-outputmode: key "T" toggles timestamps in log;
|
||||
added output of statistical data: uptime, download-time, average session
|
||||
download speed;
|
||||
- Edit-command accepts more than one ID or range of IDs.
|
||||
E.g: "nzbget -E P 2,6-10,33-39"; The switch "-I" is not used anymore;
|
||||
- Move-actions in Edit-command affect files in a smart order to guarantee
|
||||
that the relative order of files in queue is not changed after the moving;
|
||||
- Extended syntax of edit-command to edit groups (pause/unpause/delete/move
|
||||
of groups). E.g: "nzbget -E G P 2";
|
||||
- Added option "DaemonUserName" to set the user that the daemon (POSIX only)
|
||||
normally runs at. This allows nzbget daemon to be launched in rc.local
|
||||
(at boot), and download items as a specific user id; Thanks to Thierry
|
||||
MERLE <merlum@users.sourceforge.net> for the patch;
|
||||
- Added option "UMask" to specify permissions for newly created files and dirs
|
||||
(POSIX only);
|
||||
- Communication protocol used between server and client was revised to define
|
||||
the byte order for transferred data. This allows hosts with different
|
||||
endianness to communicate with each other;
|
||||
- Added options "CursesNzbName", "CursesGroup" and "CursesTime" to define
|
||||
initial state of curses-outputmode;
|
||||
- Added option "UpdateInterval" to adjust update interval for Frontend-output
|
||||
(useful in remote-mode to reduce network usage);
|
||||
- Added option "WriteBufferSize" to reduce disk-io (but it could slightly
|
||||
increase memory usage and therefore disabled by default);
|
||||
- List-command prints additional statistical info: uptime, download-time,
|
||||
total amount of downloaded data and average session download speed;
|
||||
- The creation of necessary directories on program's start was extended
|
||||
with automatic creation of all parent directories or error reporting
|
||||
if it was not possible;
|
||||
- Printed messages are now translated to oem-codepage to correctly print
|
||||
filenames with non-english characters (windows only);
|
||||
- Added remote-command "-V (--serverversion)" to print the server's version;
|
||||
- Added option "ThreadLimit" to prevent program from crash if it wants to
|
||||
create too many threads (sometimes could occur in special cases);
|
||||
- Added options "NzbDirInterval" and "NzbDirFileAge" to adjust interval and
|
||||
delay by monitoring of incoming-directory for new nzb-files;
|
||||
- Fixed error on parsing of nzb-files containing percent and other special
|
||||
characters in their names (bug appeared on windows only);
|
||||
- Reformated sample configuration file and changed default optionnames
|
||||
from lowercase to MixedCase for better readability;
|
||||
- Few bugs (seg faults) were fixed.
|
||||
|
||||
nzbget-0.3.0:
|
||||
- The download queue now contains newsgroup-files to be downloaded instead of
|
||||
nzb-jobs. By adding a new job, the nzb-file is immediately parsed and each
|
||||
newsgroup-file is added to download queue. Each file can therefore be
|
||||
managed separately (paused, deleted or moved);
|
||||
- Current queue state is saved after every change (file is completed or the
|
||||
queue is changed - entries paused, deleted or moved). The state is saved on
|
||||
disk using internal format, which allows fast loading on next program start
|
||||
(no need to parse xml-files again);
|
||||
- The remaining download-size is updated after every article is completed to
|
||||
indicate the correct remaining size and time for total files in queue;
|
||||
- Downloaded articles, which are saved in temp-directory, can be reused on
|
||||
next program start, if the file was not completed (option "continuepartial"
|
||||
in config-file);
|
||||
- Along with uulib the program has internal decoder for yEnc-format. This
|
||||
decoder was necessary, because uulib is so slow, that it prevents using of
|
||||
the program on not so powerful systems like linux-routers (MIPSEL CPU 200
|
||||
MHz). The new decoder is very fast. It is controlled over option "decoder"
|
||||
in config-file;
|
||||
- The decoder can be completely disabled. In this case all downloaded articles
|
||||
are saved in unaltered form and can be joined with an external program;
|
||||
UUDeview is one of them;
|
||||
- If download of article fails, the program attempts to download it again so
|
||||
many times, what the option "retries" in config-file says. This works even
|
||||
if no servers with level higher than "0" defined. After each retry the next
|
||||
server-level is used, if there are no more levels, the program switches to
|
||||
level "0" again. The pause between retries can be set with config-option
|
||||
"retryinterval";
|
||||
- If despite of a stated connection-timeout (it can be changed via
|
||||
config-option "connectiontimeout") connection hangs, the program tries to
|
||||
cancel the connection (after "terminatetimeout" seconds). If it doesn't
|
||||
work the download thread is killed and the article will be redownloaded in
|
||||
a new thread. This ensures, that there are no long-time hanging connections
|
||||
and all articles are downloaded, when a time to rejoin file comes;
|
||||
- Automatic par-checking and repairing. Only reuired par-files are downloaded.
|
||||
The program uses libpar2 and does not require any external tools. The big
|
||||
advantage of library is, that it allows to continue par-check after new
|
||||
par-blocks were downloaded. This were not possible with external
|
||||
par2cmdline-tool;
|
||||
- There is a daemon-mode now (command-line switch "-D" (--daemon)). In this
|
||||
mode a lock-file (default location "/tmp/nzbget.lock", can be changed via
|
||||
option "lockfile") contains PID of daemon;
|
||||
- The format of configuration-file was changed from xml to more common
|
||||
text-format. It allows also using of variables like
|
||||
"tempdir=${MAINDIR}/tmp";
|
||||
- Any option of config-file can be overwritten via command-line switch
|
||||
"-o" (--option). This includes also the definition of servers.
|
||||
This means that the program can now be started without a configuration-file
|
||||
at all (all required options must be passed via command-line);
|
||||
- The command-line switches were revised. The dedicated switches to change
|
||||
options in config-file were eliminated, since any option can now be changed
|
||||
via switch "-o" (--option);
|
||||
- If the name of configuration-file was not passed via command-line the
|
||||
program search it in following locations: "~/.nzbget", "/etc/nzbget.conf",
|
||||
"/usr/etc/nzbget.conf", "/usr/local/etc/nzbget.conf",
|
||||
"/opt/etc/nzbget.conf";
|
||||
- The new command-line switch "-n" (--noconfigfile) prevents the loading of
|
||||
a config-file. All required config-options must be passed via command-line
|
||||
(switch "-o" (--option));
|
||||
- To start the program in server mode either "-s" (--server) or
|
||||
"-D" (--daemon) switch must be used. If the program started without any
|
||||
parameters it prints help-screen. There is no a dedicated switch to start
|
||||
in a standalone mode. If switches "-s" and "-D" are omitted and none of
|
||||
client-request-switches used the standalone mode is default. This usage
|
||||
of switches is more common to programs like "wget". To add a file to
|
||||
server's download queue use switch "-A" (--append) and a name of nzb-file
|
||||
as last command-line parameter;
|
||||
- There is a new switch "-Q" (--quit) to gracefully stop server. BTW the
|
||||
SIGKIL-signal is now handled appropriately, so "killall nzbget" is also OK,
|
||||
where "killall -9 nzbget" terminates server immediately (helpful if it
|
||||
hangs, but it shouldn't);
|
||||
- With new switch "-T" (--top) the file will be added to the top of download
|
||||
queue. Use it with switch "-A" (--append);
|
||||
- The download queue can be edited via switch "-E" (--edit). It is possible
|
||||
to pause, unpause, delete and move files in queue. The IDs of file(s)
|
||||
to be affected are passed via switch "-I" (fileid), either one ID or a
|
||||
range in a form "IDForm-IDTo". This also means, that every file in queue
|
||||
have ID now;
|
||||
- The switch "-L" (--list) prints IDs of files consequently. It prints also
|
||||
name, size, percentage of completing and state (paused or not) of each file.
|
||||
Plus summary info: number of files, total remaining size and size of
|
||||
paused files, server state (paused or running), number of threads on
|
||||
server, current speed limit;
|
||||
- With new switch "-G" (--log) the last N lines printed to server's
|
||||
screen-log, can be printed on client. The max number of lines which can
|
||||
be returned from servers depends on option "logbuffersize";
|
||||
- The redesigned Frontends (known as outputmodes "loggable", "colored" and
|
||||
"curses") can connect to (remote) server and behave as if you were running
|
||||
server-instance of program itself (command-line switch "-C" (--connect)).
|
||||
The log-output updates constantly and even all control-functions in
|
||||
ncurses-mode works: pause/unpause server, set download rate limit, edit of
|
||||
queue (pause/unpause, delete, move entries). The number of connected
|
||||
clients is not limited. The "outputmode" on a client can be set
|
||||
independently from server. The client-mode is especially useful if the
|
||||
server runs as a daemon;
|
||||
- The writing to log-file can be disabled via option "createlog".
|
||||
The location of log-file controls the option "log-file";
|
||||
- Switch "-p" (--printconfig) prints the name of configuration file being
|
||||
used and all option/value-pairs, taking into account all used
|
||||
"-o" (--option) - switches;
|
||||
- The communication protocol between server and client was optimized to
|
||||
minimize the size of transferred data. Instead of fixing the size for
|
||||
Filenames in data-structures to 512 bytes only in fact used data
|
||||
are transferred;
|
||||
- Extensions in ncurses-outputmode: scrolling in queue-list works better,
|
||||
navigation in queue with keys Up, Down, PgUp, PgDn, Home, End.
|
||||
Keys to move entries are "U" (move up), "N" (move down), "T" (move to top),
|
||||
"B" (move to bottom). "P" to pause/unpause file. The size, percentage
|
||||
of completing and state (paused or not) for every file is printed.
|
||||
The header of queue shows number of total files, number of unpaused
|
||||
files and size for all and unpaused files. Better using of screen estate
|
||||
space <20> no more empty lines and separate header for status (total seven
|
||||
lines gain). The messages are printed on several lines (if they not fill
|
||||
in one line) without trimming now;
|
||||
- configure.ac-file updated to work with recent versions of autoconf/automake.
|
||||
There are new configure-options now: "--disable-uulib" to compile the
|
||||
program without uulib; "--disable-ncurses" to disable ncurses-support
|
||||
(eliminates necessity of ncurses-libs), useful on embedded systems with
|
||||
little resources; "--disable-parcheck" to compile without par-check;
|
||||
- The algorithm for parsing of nzb-files now uses XMLReader instead of
|
||||
DOM-Parser to minimize memory usage (no mor needs to build complete DOM-tree
|
||||
in memory). Thanks to Thierry MERLE <merlum@users.sourceforge.net> for
|
||||
the patch;
|
||||
- The log-file contains now thread-ID for all entry-types and additionally
|
||||
for debug-entries: filename, line number and function's name of source
|
||||
code, where the message was printed. Debug-messages can be disabled in
|
||||
config-file (option "debugtarget") like other messages;
|
||||
- The program is now compatible with windows. Project file for MS Visual
|
||||
C++ 2005 is included. Use "nzbget -install" and "nzbget -remove" to
|
||||
install/remove NZBGet-Service. Servers and clients can run on diferrent
|
||||
operating systems;
|
||||
- Improved compatibility with POSIX systems; Tested on:
|
||||
- Linux Debian 3.1 on x86;
|
||||
- Linux BusyBox with uClibc on MIPSEL;
|
||||
- PC-BSD 1.4 (based on FreeBSD 6.2) on x86;
|
||||
- Solaris 10 on x86;
|
||||
- Many memory-leaks and thread issues were fixed;
|
||||
- The program was thoroughly worked over. Almost every line of code was
|
||||
revised.
|
||||
|
||||
nzbget-0.2.3
|
||||
- Fixed problem with losing connection to newsserver after too long idle time
|
||||
- Added functionality for dumping lots of debug info
|
||||
|
||||
nzbget-0.2.2
|
||||
- Added Florian Penzkofers fix for FreeBSD, exchanging base functionality in
|
||||
SingleServerPool.cpp with a more elegant solution
|
||||
- Added functionality for forcing answer to reloading queue upon startup of
|
||||
server
|
||||
+ use -y option to force from command-line
|
||||
+ use "reloadqueue" option in nzbget.cfg to control behavior
|
||||
- Added nzbget.cfg options to control where info, warnings and errors get
|
||||
directed to (either screen, log or both)
|
||||
- Added option "createbrokenfilelog" in nzbget.cfg
|
||||
|
||||
nzbget-0.2.1
|
||||
- Changed and extended the TCP client/server interface
|
||||
- Added timeout on sockets which prevents certain types of nzbget hanging
|
||||
- Added Kristian Hermansen's patch for renaming broken files
|
||||
|
||||
nzbget-0.2.0
|
||||
- Moved 0.1.2-alt4 to a official release as 0.2.0
|
||||
- Small fixes
|
||||
|
||||
nzbget-0.1.2-alt4
|
||||
- implemented tcp/ip communication between client & server (removing the
|
||||
rather defunct System V IPC)
|
||||
- added queue editing functionality in server-mode
|
||||
|
||||
nzbget-0.1.2-alt1
|
||||
- added new ncurses frontend
|
||||
- added server/client-mode (using System V IPC)
|
||||
- added functionality for queueing download requests
|
||||
|
||||
nzbget-0.1.2
|
||||
- performance-improvements
|
||||
- commandline-options
|
||||
- fixes
|
||||
|
||||
nzbget-0.1.1
|
||||
- new output
|
||||
- fixes
|
||||
|
||||
nzbget-0.1.0a
|
||||
- compiling-fixes
|
||||
|
||||
nzbget-0.1.0
|
||||
- initial release
|
||||
nzbget-0.4.1:
|
||||
- to avoid accidental deletion of file in curses-frontend the key <D>
|
||||
not now must be pressed in uppercase;
|
||||
- options <username> and <password> in news-server's configuration are now
|
||||
optional;
|
||||
- added the server's name to the detail-log-message, displayed on the start
|
||||
of article's download;
|
||||
- added the option <AllowReProcess> to help to post-process-scripts, which
|
||||
make par-check/-repair on it's own;
|
||||
- improved download-speed-meter: it useses now a ölittle bit less cpu and
|
||||
calculates the speed for the last 30 seconds (instead of 5 seconds),
|
||||
providing better accuracy; Thanks to ydrol <ydrol@users.sourceforge.net>
|
||||
for the patch;
|
||||
- reduced CPU-usage in curses-outputmode; Thanks to ydrol for the patch
|
||||
<ydrol@users.sourceforge.net>;
|
||||
- fixed: line-endings in windows-style (CR-LF) in config-file were not
|
||||
read properly;
|
||||
- fixed: trailing spaces in nzb-filenames (before the file's extension)
|
||||
caused errors on windows. Now they will be trimmed;
|
||||
- fixed: XML-RPC and JSON-RPC did not work on Big-Endian-CPUs (ARM, PPC, etc),
|
||||
preventing the using of web-interface;
|
||||
- fixed: umask-option did not allow to enable write-permissions for <group>
|
||||
and <others>;
|
||||
- fixed: in curses-outputmode the remote-client showed on first screen-update
|
||||
only one item of queue;
|
||||
- fixed: edit-commands with negative offset did not work via XML-RPC
|
||||
(but worked via JSON-RPC);
|
||||
- fixed incompatibility issues with gcc 4.3; Thanks to Paul Bredbury
|
||||
<brebs@users.sourceforge.net> for the patch;
|
||||
- fixed: segmentation fault if a file listed in nzb-file does not have any
|
||||
segments (articles);
|
||||
|
||||
nzbget-0.4.0:
|
||||
- added the support for XML-RPC and JSON-RPC to easier control the server
|
||||
from other applications;
|
||||
- added web-interface - it is available for download from NZBGet-project's
|
||||
home page as a separate package "web-interface";
|
||||
- added the automatic cleaning up of the download queue (deletion of unneeded
|
||||
paused par-files) after successful par-check/repair - new
|
||||
option <ParCleanupQueue>;
|
||||
- added option <DetailTarget> to allow to filter the (not so important)
|
||||
log-messages from articles' downloads (they have now the type <detail>
|
||||
instead of <info>);
|
||||
- added the gathering of progress-information during par-check; it is
|
||||
available via XML-RPC or JSON-RPC; it is also showed in web-interface;
|
||||
- improvements in internal decoder: added support for yEnc-files without
|
||||
ypart-statement (sometimes used for small files); added support for
|
||||
UU-format;
|
||||
- removed support for uulib-decoder (it did not work well anyway);
|
||||
- replaced the option <decoder (yenc, uulib, none)> with the option
|
||||
<decode (yes, no)>;
|
||||
- added detection of errors <server busy> and <remote server not available>
|
||||
(special case for NNTPCache-server) to consider them as connect-errors
|
||||
(and therefore not count as retries);
|
||||
- added check for incomplete articles (also mostly for NNTPCache-server) to
|
||||
differ such errors from CrcErrors (better error reporting);
|
||||
- improved error-reporting on moving of completed files from tmp- to
|
||||
dst-directory and added code to move files across drives if renaming fails;
|
||||
- improved handling of nzb-files with multiple collections in par-checker;
|
||||
- improved the parchecker: added the detection and processing of files
|
||||
splitted after parring;
|
||||
- added the queueing of post-process-scripts and waiting for script's
|
||||
completion before starting of a next job in postprocessor (par-job or
|
||||
script) to provide more balanced cpu utilization;
|
||||
- added the redirecting of post-process-script's output to log; new option
|
||||
<PostLogKind> to specify the default message-kind for unformatted
|
||||
log-messages;
|
||||
- added the returning of script-output by command <postqueue> via XML-RPC
|
||||
and JSON-RPC; the script-output is also showed in web-interface;
|
||||
- added the saving and restoring of the post-processor-queue (if server was
|
||||
stopped before all items were processed); new option <ReloadPostQueue>;
|
||||
- added new parameter to postprocess-script to indicate if any of par-jobs
|
||||
for the same nzb-file failed;
|
||||
- added remote command (switch O/--post) to request the post-processor-queue
|
||||
from server;
|
||||
- added remote command (switch -W/--write) to write messages to server's log;
|
||||
- added option <DiskSpace> to automatically pause the download on low disk
|
||||
space;
|
||||
- fixed few incompatibility-issues with unslung-platform on nslu2 (ARM);
|
||||
- fixed: articles with trailing text after binary data caused the decode
|
||||
failures and the reporting of CRC-errors;
|
||||
- fixed: dupecheck could cause seg.faults when all articles for a file failed;
|
||||
- fixed: by dupe-checking of files contained in nzb-file the files with the
|
||||
same size were ignored (not deleted from queue);
|
||||
- updated libpar2-patch for msvc to fix a segfault in libpar2 (windows only);
|
||||
- fixed: by registering the service on windows the fullpath to nzbget.exe
|
||||
was not always added to service's exename, making the registered service
|
||||
unusable;
|
||||
- fixed: the pausing of a group could cause the start of post-processing for
|
||||
that group;
|
||||
- fixed: too many info-messages <Need more N blocks> could be printed during
|
||||
par-check (appeared on posix only);
|
||||
|
||||
nzbget-0.3.1:
|
||||
- Greatly reduced the memory consumption by keeping articles' info on disk
|
||||
until the file download starts;
|
||||
- Implemented decode-on-the-fly-technique to reduce disk-io; downloaded
|
||||
and decoded data can also be saved directly to the destination file
|
||||
(without any intermediate files at all); this eliminates the necessity
|
||||
of joining of articles later (option "DirectWrite");
|
||||
- Improved communication with news-servers: connections are now keeped open
|
||||
until all files are downloaded (or server paused); this eliminates the
|
||||
need for establishing of connections and authorizations for each
|
||||
article and improves overal download speed;
|
||||
- Significantly better download speed is now possible on fast connection;
|
||||
it was limited by delays on starting of new articles' downloads;
|
||||
the synchronisation mechanism was reworked to fix this issue;
|
||||
- Download speed meter is much more accurate, especially on fast connections;
|
||||
this also means better speed throttling;
|
||||
- Speed optimisations in internal decoder (up to 25% faster);
|
||||
- CRC-calculation can be bypassed to increase performance on slow CPUs
|
||||
(option "CrcCheck");
|
||||
- Improved parsing of artcile's subject for better extracting of filename
|
||||
part from it and implemented a fallback-option if the parsing was incorrect;
|
||||
- Improved dupe check for files from the same nzb-request to detect reposted
|
||||
files and download only the best from them (if option "DupeCheck" is on);
|
||||
- Articles with incorrect CRC can be treated as "possibly recoverable errors"
|
||||
and relaunched for download (option "RetryOnCrcError"), it is useful if
|
||||
multiple servers are available;
|
||||
- Improved error-check for downloaded articles (crc-check and check for
|
||||
received message-id) decreases the number of broken files;
|
||||
- Extensions in curses-outputmode: added group-view-mode (key "G") to show
|
||||
items in download queue as groups, where one group represents all files
|
||||
from the same nzb-file; the editing of queue works also in group-mode
|
||||
(for all files in this group): pause/unpause/delete/move of groups;
|
||||
- Other extensions in curses-outputmode: key "T" toggles timestamps in log;
|
||||
added output of statistical data: uptime, download-time, average session
|
||||
download speed;
|
||||
- Edit-command accepts more than one ID or range of IDs.
|
||||
E.g: "nzbget -E P 2,6-10,33-39"; The switch "-I" is not used anymore;
|
||||
- Move-actions in Edit-command affect files in a smart order to guarantee
|
||||
that the relative order of files in queue is not changed after the moving;
|
||||
- Extended syntax of edit-command to edit groups (pause/unpause/delete/move
|
||||
of groups). E.g: "nzbget -E G P 2";
|
||||
- Added option "DaemonUserName" to set the user that the daemon (POSIX only)
|
||||
normally runs at. This allows nzbget daemon to be launched in rc.local
|
||||
(at boot), and download items as a specific user id; Thanks to Thierry
|
||||
MERLE <merlum@users.sourceforge.net> for the patch;
|
||||
- Added option "UMask" to specify permissions for newly created files and dirs
|
||||
(POSIX only);
|
||||
- Communication protocol used between server and client was revised to define
|
||||
the byte order for transferred data. This allows hosts with different
|
||||
endianness to communicate with each other;
|
||||
- Added options "CursesNzbName", "CursesGroup" and "CursesTime" to define
|
||||
initial state of curses-outputmode;
|
||||
- Added option "UpdateInterval" to adjust update interval for Frontend-output
|
||||
(useful in remote-mode to reduce network usage);
|
||||
- Added option "WriteBufferSize" to reduce disk-io (but it could slightly
|
||||
increase memory usage and therefore disabled by default);
|
||||
- List-command prints additional statistical info: uptime, download-time,
|
||||
total amount of downloaded data and average session download speed;
|
||||
- The creation of necessary directories on program's start was extended
|
||||
with automatic creation of all parent directories or error reporting
|
||||
if it was not possible;
|
||||
- Printed messages are now translated to oem-codepage to correctly print
|
||||
filenames with non-english characters (windows only);
|
||||
- Added remote-command "-V (--serverversion)" to print the server's version;
|
||||
- Added option "ThreadLimit" to prevent program from crash if it wants to
|
||||
create too many threads (sometimes could occur in special cases);
|
||||
- Added options "NzbDirInterval" and "NzbDirFileAge" to adjust interval and
|
||||
delay by monitoring of incoming-directory for new nzb-files;
|
||||
- Fixed error on parsing of nzb-files containing percent and other special
|
||||
characters in their names (bug appeared on windows only);
|
||||
- Reformated sample configuration file and changed default optionnames
|
||||
from lowercase to MixedCase for better readability;
|
||||
- Few bugs (seg faults) were fixed.
|
||||
|
||||
nzbget-0.3.0:
|
||||
- The download queue now contains newsgroup-files to be downloaded instead of
|
||||
nzb-jobs. By adding a new job, the nzb-file is immediately parsed and each
|
||||
newsgroup-file is added to download queue. Each file can therefore be
|
||||
managed separately (paused, deleted or moved);
|
||||
- Current queue state is saved after every change (file is completed or the
|
||||
queue is changed - entries paused, deleted or moved). The state is saved on
|
||||
disk using internal format, which allows fast loading on next program start
|
||||
(no need to parse xml-files again);
|
||||
- The remaining download-size is updated after every article is completed to
|
||||
indicate the correct remaining size and time for total files in queue;
|
||||
- Downloaded articles, which are saved in temp-directory, can be reused on
|
||||
next program start, if the file was not completed (option "continuepartial"
|
||||
in config-file);
|
||||
- Along with uulib the program has internal decoder for yEnc-format. This
|
||||
decoder was necessary, because uulib is so slow, that it prevents using of
|
||||
the program on not so powerful systems like linux-routers (MIPSEL CPU 200
|
||||
MHz). The new decoder is very fast. It is controlled over option "decoder"
|
||||
in config-file;
|
||||
- The decoder can be completely disabled. In this case all downloaded articles
|
||||
are saved in unaltered form and can be joined with an external program;
|
||||
UUDeview is one of them;
|
||||
- If download of article fails, the program attempts to download it again so
|
||||
many times, what the option "retries" in config-file says. This works even
|
||||
if no servers with level higher than "0" defined. After each retry the next
|
||||
server-level is used, if there are no more levels, the program switches to
|
||||
level "0" again. The pause between retries can be set with config-option
|
||||
"retryinterval";
|
||||
- If despite of a stated connection-timeout (it can be changed via
|
||||
config-option "connectiontimeout") connection hangs, the program tries to
|
||||
cancel the connection (after "terminatetimeout" seconds). If it doesn't
|
||||
work the download thread is killed and the article will be redownloaded in
|
||||
a new thread. This ensures, that there are no long-time hanging connections
|
||||
and all articles are downloaded, when a time to rejoin file comes;
|
||||
- Automatic par-checking and repairing. Only reuired par-files are downloaded.
|
||||
The program uses libpar2 and does not require any external tools. The big
|
||||
advantage of library is, that it allows to continue par-check after new
|
||||
par-blocks were downloaded. This were not possible with external
|
||||
par2cmdline-tool;
|
||||
- There is a daemon-mode now (command-line switch "-D" (--daemon)). In this
|
||||
mode a lock-file (default location "/tmp/nzbget.lock", can be changed via
|
||||
option "lockfile") contains PID of daemon;
|
||||
- The format of configuration-file was changed from xml to more common
|
||||
text-format. It allows also using of variables like
|
||||
"tempdir=${MAINDIR}/tmp";
|
||||
- Any option of config-file can be overwritten via command-line switch
|
||||
"-o" (--option). This includes also the definition of servers.
|
||||
This means that the program can now be started without a configuration-file
|
||||
at all (all required options must be passed via command-line);
|
||||
- The command-line switches were revised. The dedicated switches to change
|
||||
options in config-file were eliminated, since any option can now be changed
|
||||
via switch "-o" (--option);
|
||||
- If the name of configuration-file was not passed via command-line the
|
||||
program search it in following locations: "~/.nzbget", "/etc/nzbget.conf",
|
||||
"/usr/etc/nzbget.conf", "/usr/local/etc/nzbget.conf",
|
||||
"/opt/etc/nzbget.conf";
|
||||
- The new command-line switch "-n" (--noconfigfile) prevents the loading of
|
||||
a config-file. All required config-options must be passed via command-line
|
||||
(switch "-o" (--option));
|
||||
- To start the program in server mode either "-s" (--server) or
|
||||
"-D" (--daemon) switch must be used. If the program started without any
|
||||
parameters it prints help-screen. There is no a dedicated switch to start
|
||||
in a standalone mode. If switches "-s" and "-D" are omitted and none of
|
||||
client-request-switches used the standalone mode is default. This usage
|
||||
of switches is more common to programs like "wget". To add a file to
|
||||
server's download queue use switch "-A" (--append) and a name of nzb-file
|
||||
as last command-line parameter;
|
||||
- There is a new switch "-Q" (--quit) to gracefully stop server. BTW the
|
||||
SIGKIL-signal is now handled appropriately, so "killall nzbget" is also OK,
|
||||
where "killall -9 nzbget" terminates server immediately (helpful if it
|
||||
hangs, but it shouldn't);
|
||||
- With new switch "-T" (--top) the file will be added to the top of download
|
||||
queue. Use it with switch "-A" (--append);
|
||||
- The download queue can be edited via switch "-E" (--edit). It is possible
|
||||
to pause, unpause, delete and move files in queue. The IDs of file(s)
|
||||
to be affected are passed via switch "-I" (fileid), either one ID or a
|
||||
range in a form "IDForm-IDTo". This also means, that every file in queue
|
||||
have ID now;
|
||||
- The switch "-L" (--list) prints IDs of files consequently. It prints also
|
||||
name, size, percentage of completing and state (paused or not) of each file.
|
||||
Plus summary info: number of files, total remaining size and size of
|
||||
paused files, server state (paused or running), number of threads on
|
||||
server, current speed limit;
|
||||
- With new switch "-G" (--log) the last N lines printed to server's
|
||||
screen-log, can be printed on client. The max number of lines which can
|
||||
be returned from servers depends on option "logbuffersize";
|
||||
- The redesigned Frontends (known as outputmodes "loggable", "colored" and
|
||||
"curses") can connect to (remote) server and behave as if you were running
|
||||
server-instance of program itself (command-line switch "-C" (--connect)).
|
||||
The log-output updates constantly and even all control-functions in
|
||||
ncurses-mode works: pause/unpause server, set download rate limit, edit of
|
||||
queue (pause/unpause, delete, move entries). The number of connected
|
||||
clients is not limited. The "outputmode" on a client can be set
|
||||
independently from server. The client-mode is especially useful if the
|
||||
server runs as a daemon;
|
||||
- The writing to log-file can be disabled via option "createlog".
|
||||
The location of log-file controls the option "log-file";
|
||||
- Switch "-p" (--printconfig) prints the name of configuration file being
|
||||
used and all option/value-pairs, taking into account all used
|
||||
"-o" (--option) - switches;
|
||||
- The communication protocol between server and client was optimized to
|
||||
minimize the size of transferred data. Instead of fixing the size for
|
||||
Filenames in data-structures to 512 bytes only in fact used data
|
||||
are transferred;
|
||||
- Extensions in ncurses-outputmode: scrolling in queue-list works better,
|
||||
navigation in queue with keys Up, Down, PgUp, PgDn, Home, End.
|
||||
Keys to move entries are "U" (move up), "N" (move down), "T" (move to top),
|
||||
"B" (move to bottom). "P" to pause/unpause file. The size, percentage
|
||||
of completing and state (paused or not) for every file is printed.
|
||||
The header of queue shows number of total files, number of unpaused
|
||||
files and size for all and unpaused files. Better using of screen estate
|
||||
space <20> no more empty lines and separate header for status (total seven
|
||||
lines gain). The messages are printed on several lines (if they not fill
|
||||
in one line) without trimming now;
|
||||
- configure.ac-file updated to work with recent versions of autoconf/automake.
|
||||
There are new configure-options now: "--disable-uulib" to compile the
|
||||
program without uulib; "--disable-ncurses" to disable ncurses-support
|
||||
(eliminates necessity of ncurses-libs), useful on embedded systems with
|
||||
little resources; "--disable-parcheck" to compile without par-check;
|
||||
- The algorithm for parsing of nzb-files now uses XMLReader instead of
|
||||
DOM-Parser to minimize memory usage (no mor needs to build complete DOM-tree
|
||||
in memory). Thanks to Thierry MERLE <merlum@users.sourceforge.net> for
|
||||
the patch;
|
||||
- The log-file contains now thread-ID for all entry-types and additionally
|
||||
for debug-entries: filename, line number and function's name of source
|
||||
code, where the message was printed. Debug-messages can be disabled in
|
||||
config-file (option "debugtarget") like other messages;
|
||||
- The program is now compatible with windows. Project file for MS Visual
|
||||
C++ 2005 is included. Use "nzbget -install" and "nzbget -remove" to
|
||||
install/remove NZBGet-Service. Servers and clients can run on diferrent
|
||||
operating systems;
|
||||
- Improved compatibility with POSIX systems; Tested on:
|
||||
- Linux Debian 3.1 on x86;
|
||||
- Linux BusyBox with uClibc on MIPSEL;
|
||||
- PC-BSD 1.4 (based on FreeBSD 6.2) on x86;
|
||||
- Solaris 10 on x86;
|
||||
- Many memory-leaks and thread issues were fixed;
|
||||
- The program was thoroughly worked over. Almost every line of code was
|
||||
revised.
|
||||
|
||||
nzbget-0.2.3
|
||||
- Fixed problem with losing connection to newsserver after too long idle time
|
||||
- Added functionality for dumping lots of debug info
|
||||
|
||||
nzbget-0.2.2
|
||||
- Added Florian Penzkofers fix for FreeBSD, exchanging base functionality in
|
||||
SingleServerPool.cpp with a more elegant solution
|
||||
- Added functionality for forcing answer to reloading queue upon startup of
|
||||
server
|
||||
+ use -y option to force from command-line
|
||||
+ use "reloadqueue" option in nzbget.cfg to control behavior
|
||||
- Added nzbget.cfg options to control where info, warnings and errors get
|
||||
directed to (either screen, log or both)
|
||||
- Added option "createbrokenfilelog" in nzbget.cfg
|
||||
|
||||
nzbget-0.2.1
|
||||
- Changed and extended the TCP client/server interface
|
||||
- Added timeout on sockets which prevents certain types of nzbget hanging
|
||||
- Added Kristian Hermansen's patch for renaming broken files
|
||||
|
||||
nzbget-0.2.0
|
||||
- Moved 0.1.2-alt4 to a official release as 0.2.0
|
||||
- Small fixes
|
||||
|
||||
nzbget-0.1.2-alt4
|
||||
- implemented tcp/ip communication between client & server (removing the
|
||||
rather defunct System V IPC)
|
||||
- added queue editing functionality in server-mode
|
||||
|
||||
nzbget-0.1.2-alt1
|
||||
- added new ncurses frontend
|
||||
- added server/client-mode (using System V IPC)
|
||||
- added functionality for queueing download requests
|
||||
|
||||
nzbget-0.1.2
|
||||
- performance-improvements
|
||||
- commandline-options
|
||||
- fixes
|
||||
|
||||
nzbget-0.1.1
|
||||
- new output
|
||||
- fixes
|
||||
|
||||
nzbget-0.1.0a
|
||||
- compiling-fixes
|
||||
|
||||
nzbget-0.1.0
|
||||
- initial release
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file if part of nzbget
|
||||
*
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007-2010 Andrei Prygounkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007 Andrei Prygounkov <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
|
||||
@@ -76,7 +76,7 @@ void ColoredFrontend::PrintStatus()
|
||||
timeString[0] = '\0';
|
||||
float fCurrentDownloadSpeed = m_bStandBy ? 0 : m_fCurrentDownloadSpeed;
|
||||
|
||||
if (fCurrentDownloadSpeed > 0.0 && !(m_bPauseDownload || m_bPauseDownload2))
|
||||
if (fCurrentDownloadSpeed > 0.0 && !m_bPause)
|
||||
{
|
||||
long long remain_sec = m_lRemainingSize / ((long long)(fCurrentDownloadSpeed * 1024));
|
||||
int h = (int)(remain_sec / 3600);
|
||||
@@ -88,7 +88,7 @@ void ColoredFrontend::PrintStatus()
|
||||
char szDownloadLimit[128];
|
||||
if (m_fDownloadLimit > 0.0f)
|
||||
{
|
||||
sprintf(szDownloadLimit, ", Limit %.0f KB/s", m_fDownloadLimit);
|
||||
sprintf(szDownloadLimit, ", Limit %.0f KB/S", m_fDownloadLimit);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -112,11 +112,9 @@ void ColoredFrontend::PrintStatus()
|
||||
const char* szControlSeq = "\033[K";
|
||||
#endif
|
||||
|
||||
snprintf(tmp, 1024, " %d threads, %.*f KB/s, %.2f MB remaining%s%s%s%s%s\n",
|
||||
m_iThreadCount, (fCurrentDownloadSpeed >= 10 ? 0 : 1), fCurrentDownloadSpeed,
|
||||
(float)(Util::Int64ToFloat(m_lRemainingSize) / 1024.0 / 1024.0), timeString, szPostStatus,
|
||||
m_bPauseDownload || m_bPauseDownload2 ? (m_bStandBy ? ", Paused" : ", Pausing") : "",
|
||||
szDownloadLimit, szControlSeq);
|
||||
snprintf(tmp, 1024, " %d threads, %.0f KB/s, %.2f MB remaining%s%s%s%s%s\n",
|
||||
m_iThreadCount, fCurrentDownloadSpeed, (float)(Util::Int64ToFloat(m_lRemainingSize) / 1024.0 / 1024.0),
|
||||
timeString, szPostStatus, m_bPause ? (m_bStandBy ? ", Paused" : ", Pausing") : "", szDownloadLimit, szControlSeq);
|
||||
tmp[1024-1] = '\0';
|
||||
printf("%s", tmp);
|
||||
m_bNeedGoBack = true;
|
||||
|
||||
521
Connection.cpp
521
Connection.cpp
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
* This file if part of nzbget
|
||||
*
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007-2009 Andrei Prygounkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007 Andrei Prygounkov <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,24 +29,17 @@
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
// SKIP_DEFAULT_WINDOWS_HEADERS prevents the including of <windows.h>, which includes "winsock.h",
|
||||
// but we need "winsock2.h" here (they conflicts with each other)
|
||||
#define SKIP_DEFAULT_WINDOWS_HEADERS
|
||||
#include "win32.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <cstdio>
|
||||
#ifdef WIN32
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#else
|
||||
#ifndef WIN32
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
@@ -54,21 +47,12 @@
|
||||
#include "nzbget.h"
|
||||
#include "Connection.h"
|
||||
#include "Log.h"
|
||||
#include "TLS.h"
|
||||
|
||||
static const int CONNECTION_READBUFFER_SIZE = 1024;
|
||||
#ifndef DISABLE_TLS
|
||||
bool Connection::bTLSLibInitialized = false;
|
||||
#endif
|
||||
#ifndef HAVE_GETADDRINFO
|
||||
#ifndef HAVE_GETHOSTBYNAME_R
|
||||
Mutex* Connection::m_pMutexGetHostByName = NULL;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void Connection::Init(bool bTLS)
|
||||
void Connection::Init()
|
||||
{
|
||||
debug("Initializing global connection data");
|
||||
debug("Intiializing global connection data");
|
||||
|
||||
#ifdef WIN32
|
||||
WSADATA wsaData;
|
||||
@@ -85,30 +69,6 @@ void Connection::Init(bool bTLS)
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef DISABLE_TLS
|
||||
if (bTLS)
|
||||
{
|
||||
debug("Initializing TLS library");
|
||||
char* szErrStr;
|
||||
int iRes = tls_lib_init(&szErrStr);
|
||||
bTLSLibInitialized = iRes == TLS_EOK;
|
||||
if (!bTLSLibInitialized)
|
||||
{
|
||||
error("Could not initialize TLS library: %s", szErrStr ? szErrStr : "unknown error");
|
||||
if (szErrStr)
|
||||
{
|
||||
free(szErrStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_GETADDRINFO
|
||||
#ifndef HAVE_GETHOSTBYNAME_R
|
||||
m_pMutexGetHostByName = new Mutex();
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void Connection::Final()
|
||||
@@ -118,22 +78,9 @@ void Connection::Final()
|
||||
#ifdef WIN32
|
||||
WSACleanup();
|
||||
#endif
|
||||
|
||||
#ifndef DISABLE_TLS
|
||||
if (bTLSLibInitialized)
|
||||
{
|
||||
debug("Finalizing TLS library");
|
||||
tls_lib_deinit();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_GETADDRINFO
|
||||
#ifndef HAVE_GETHOSTBYNAME_R
|
||||
delete m_pMutexGetHostByName;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
Connection::Connection(NetAddress* pNetAddress)
|
||||
{
|
||||
debug("Creating Connection");
|
||||
@@ -146,10 +93,6 @@ Connection::Connection(NetAddress* pNetAddress)
|
||||
m_bSuppressErrors = true;
|
||||
m_szReadBuf = (char*)malloc(CONNECTION_READBUFFER_SIZE + 1);
|
||||
m_bAutoClose = true;
|
||||
#ifndef DISABLE_TLS
|
||||
m_pTLS = NULL;
|
||||
m_bTLSError = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
Connection::Connection(SOCKET iSocket, bool bAutoClose)
|
||||
@@ -164,9 +107,6 @@ Connection::Connection(SOCKET iSocket, bool bAutoClose)
|
||||
m_bSuppressErrors = true;
|
||||
m_szReadBuf = (char*)malloc(CONNECTION_READBUFFER_SIZE + 1);
|
||||
m_bAutoClose = bAutoClose;
|
||||
#ifndef DISABLE_TLS
|
||||
m_pTLS = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
Connection::~Connection()
|
||||
@@ -178,45 +118,39 @@ Connection::~Connection()
|
||||
Disconnect();
|
||||
}
|
||||
free(m_szReadBuf);
|
||||
#ifndef DISABLE_TLS
|
||||
if (m_pTLS)
|
||||
{
|
||||
free(m_pTLS);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Connection::Connect()
|
||||
int Connection::Connect()
|
||||
{
|
||||
debug("Connecting");
|
||||
|
||||
if (m_eStatus == csConnected)
|
||||
return true;
|
||||
return 0;
|
||||
|
||||
bool bRes = DoConnect();
|
||||
int iRes = DoConnect();
|
||||
|
||||
if (bRes)
|
||||
if (iRes >= 0)
|
||||
m_eStatus = csConnected;
|
||||
else
|
||||
Connection::DoDisconnect();
|
||||
|
||||
return bRes;
|
||||
return iRes;
|
||||
}
|
||||
|
||||
bool Connection::Disconnect()
|
||||
int Connection::Disconnect()
|
||||
{
|
||||
debug("Disconnecting");
|
||||
|
||||
if (m_eStatus == csDisconnected)
|
||||
return true;
|
||||
return 0;
|
||||
|
||||
bool bRes = DoDisconnect();
|
||||
int iRes = DoDisconnect();
|
||||
|
||||
m_eStatus = csDisconnected;
|
||||
m_iSocket = INVALID_SOCKET;
|
||||
m_iBufAvail = 0;
|
||||
|
||||
return bRes;
|
||||
return iRes;
|
||||
}
|
||||
|
||||
int Connection::Bind()
|
||||
@@ -302,7 +236,7 @@ int Connection::Recv(char* pBuffer, int iSize)
|
||||
|
||||
if (iReceived < 0)
|
||||
{
|
||||
ReportError("Could not receive data on socket", NULL, true, 0);
|
||||
ReportError("Could not receive data on socket", NULL, 0);
|
||||
}
|
||||
|
||||
return iReceived;
|
||||
@@ -334,7 +268,7 @@ bool Connection::RecvAll(char * pBuffer, int iSize)
|
||||
// Did the recv succeed?
|
||||
if (iReceived <= 0)
|
||||
{
|
||||
ReportError("Could not receive data on socket", NULL, true, 0);
|
||||
ReportError("Could not receive data on socket", NULL, 0);
|
||||
return false;
|
||||
}
|
||||
pBufPtr += iReceived;
|
||||
@@ -343,81 +277,35 @@ bool Connection::RecvAll(char * pBuffer, int iSize)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Connection::DoConnect()
|
||||
int Connection::DoConnect()
|
||||
{
|
||||
debug("Do connecting");
|
||||
|
||||
m_iSocket = INVALID_SOCKET;
|
||||
|
||||
#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,
|
||||
|
||||
sprintf(iPortStr, "%d", m_pNetAddress->GetPort());
|
||||
|
||||
int res = getaddrinfo(m_pNetAddress->GetHost(), iPortStr, &addr_hints, &addr_list);
|
||||
if (res != 0)
|
||||
{
|
||||
ReportError("Could not resolve hostname %s", m_pNetAddress->GetHost(), true, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
res = connect(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));
|
||||
memset(&sSocketAddress, '\0', sizeof(sSocketAddress));
|
||||
sSocketAddress.sin_family = AF_INET;
|
||||
sSocketAddress.sin_port = htons(m_pNetAddress->GetPort());
|
||||
sSocketAddress.sin_addr.s_addr = ResolveHostAddr(m_pNetAddress->GetHost());
|
||||
if (sSocketAddress.sin_addr.s_addr == (unsigned int)-1)
|
||||
{
|
||||
return false;
|
||||
return -1;
|
||||
}
|
||||
|
||||
m_iSocket = socket(PF_INET, SOCK_STREAM, 0);
|
||||
|
||||
if (m_iSocket == INVALID_SOCKET)
|
||||
{
|
||||
ReportError("Socket creation failed for %s", m_pNetAddress->GetHost(), true, 0);
|
||||
return false;
|
||||
ReportError("Socket creation failed for %s!", m_pNetAddress->GetHost(), 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int res = connect(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)
|
||||
if (res < 0)
|
||||
{
|
||||
ReportError("Connection to %s failed", m_pNetAddress->GetHost(), true, 0);
|
||||
return false;
|
||||
}
|
||||
ReportError("Connection to %s failed!", m_pNetAddress->GetHost(), 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
int MSecVal = m_iTimeout * 1000;
|
||||
@@ -430,30 +318,65 @@ bool Connection::DoConnect()
|
||||
#endif
|
||||
if (err != 0)
|
||||
{
|
||||
ReportError("setsockopt failed", NULL, true, 0);
|
||||
ReportError("setsockopt failed", NULL, 0);
|
||||
}
|
||||
|
||||
return true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Connection::DoDisconnect()
|
||||
unsigned int Connection::ResolveHostAddr(const char* szHost)
|
||||
{
|
||||
unsigned int uaddr = inet_addr(szHost);
|
||||
if (uaddr == (unsigned int)-1)
|
||||
{
|
||||
struct hostent* hinfo;
|
||||
bool err = false;
|
||||
int h_errnop = 0;
|
||||
#ifdef WIN32
|
||||
hinfo = gethostbyname(szHost);
|
||||
err = hinfo == NULL;
|
||||
h_errnop = WSAGetLastError();
|
||||
#else
|
||||
struct hostent hinfobuf;
|
||||
static const int strbuflen = 1024;
|
||||
char* strbuf = (char*)malloc(strbuflen);
|
||||
#ifdef HAVE_GETHOSTBYNAME_R_6
|
||||
err = gethostbyname_r(szHost, &hinfobuf, strbuf, strbuflen, &hinfo, &h_errnop);
|
||||
err = err || (hinfo == NULL); // error on null hinfo (means 'no entry')
|
||||
#else
|
||||
hinfo = gethostbyname_r(szHost, &hinfobuf, strbuf, strbuflen, &h_errnop);
|
||||
err = hinfo == NULL;
|
||||
#endif
|
||||
#endif
|
||||
if (err)
|
||||
{
|
||||
ReportError("Could not resolve hostname %s", szHost, h_errnop);
|
||||
#ifndef WIN32
|
||||
free(strbuf);
|
||||
#endif
|
||||
return (unsigned int)-1;
|
||||
}
|
||||
|
||||
memcpy(&uaddr, hinfo->h_addr_list[0], sizeof(uaddr));
|
||||
#ifndef WIN32
|
||||
free(strbuf);
|
||||
#endif
|
||||
}
|
||||
return uaddr;
|
||||
}
|
||||
|
||||
int Connection::DoDisconnect()
|
||||
{
|
||||
debug("Do disconnecting");
|
||||
|
||||
if (m_iSocket != INVALID_SOCKET)
|
||||
if (m_iSocket > 0)
|
||||
{
|
||||
closesocket(m_iSocket);
|
||||
m_iSocket = INVALID_SOCKET;
|
||||
#ifndef DISABLE_TLS
|
||||
if (m_pTLS)
|
||||
{
|
||||
CloseTLS();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
m_eStatus = csDisconnected;
|
||||
return true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Connection::DoWriteLine(const char* pBuffer)
|
||||
@@ -477,7 +400,7 @@ char* Connection::DoReadLine(char* pBuffer, int iSize, int* pBytesRead)
|
||||
iBufAvail = recv(m_iSocket, m_szReadBuf, CONNECTION_READBUFFER_SIZE, 0);
|
||||
if (iBufAvail < 0)
|
||||
{
|
||||
ReportError("Could not receive data on socket", NULL, true, 0);
|
||||
ReportError("Could not receive data on socket", NULL, 0);
|
||||
break;
|
||||
}
|
||||
else if (iBufAvail == 0)
|
||||
@@ -537,50 +460,15 @@ 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_pNetAddress->GetPort());
|
||||
|
||||
int res = getaddrinfo(m_pNetAddress->GetHost(), iPortStr, &addr_hints, &addr_list);
|
||||
if (res != 0)
|
||||
m_iSocket = socket(PF_INET, SOCK_STREAM, 0);
|
||||
if (m_iSocket == INVALID_SOCKET)
|
||||
{
|
||||
error( "Could not resolve hostname %s", m_pNetAddress->GetHost() );
|
||||
ReportError("Socket creation failed for %s!", m_pNetAddress->GetHost(), 0);
|
||||
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));
|
||||
memset(&sSocketAddress, '\0', sizeof(sSocketAddress));
|
||||
sSocketAddress.sin_family = AF_INET;
|
||||
if (!m_pNetAddress->GetHost() || strlen(m_pNetAddress->GetHost()) == 0)
|
||||
{
|
||||
@@ -595,35 +483,18 @@ int Connection::DoBind()
|
||||
}
|
||||
}
|
||||
sSocketAddress.sin_port = htons(m_pNetAddress->GetPort());
|
||||
|
||||
m_iSocket = socket(PF_INET, SOCK_STREAM, 0);
|
||||
if (m_iSocket == INVALID_SOCKET)
|
||||
{
|
||||
ReportError("Socket creation failed for %s", m_pNetAddress->GetHost(), 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)
|
||||
if (bind(m_iSocket, (struct sockaddr *) &sSocketAddress, sizeof(sSocketAddress)) < 0)
|
||||
{
|
||||
// Connection failed
|
||||
closesocket(m_iSocket);
|
||||
m_iSocket = INVALID_SOCKET;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (m_iSocket == INVALID_SOCKET)
|
||||
{
|
||||
ReportError("Binding socket failed for %s", m_pNetAddress->GetHost(), true, 0);
|
||||
ReportError("Binding socket failed for %s", m_pNetAddress->GetHost(), 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (listen(m_iSocket, 10) < 0)
|
||||
{
|
||||
ReportError("Listen on socket failed for %s", m_pNetAddress->GetHost(), true, 0);
|
||||
ReportError("Listen on socket failed for %s", m_pNetAddress->GetHost(), 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -632,11 +503,16 @@ int Connection::DoBind()
|
||||
|
||||
SOCKET Connection::DoAccept()
|
||||
{
|
||||
SOCKET iSocket = accept(GetSocket(), NULL, NULL);
|
||||
struct sockaddr_in ClientAddress;
|
||||
socklen_t SockLen;
|
||||
|
||||
SockLen = sizeof(ClientAddress);
|
||||
|
||||
SOCKET iSocket = accept(GetSocket(), (struct sockaddr *) & ClientAddress, &SockLen);
|
||||
|
||||
if (iSocket == INVALID_SOCKET && m_eStatus != csCancelled)
|
||||
{
|
||||
ReportError("Could not accept connection", NULL, true, 0);
|
||||
ReportError("Could not accept connection", NULL, 0);
|
||||
}
|
||||
|
||||
return iSocket;
|
||||
@@ -651,220 +527,43 @@ void Connection::Cancel()
|
||||
int r = shutdown(m_iSocket, SHUT_RDWR);
|
||||
if (r == -1)
|
||||
{
|
||||
ReportError("Could not shutdown connection", NULL, true, 0);
|
||||
ReportError("Could not shutdown connection", NULL, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Connection::ReportError(const char* szMsgPrefix, const char* szMsgArg, bool PrintErrCode, int herrno)
|
||||
void Connection::ReportError(const char* szMsgPrefix, const char* szMsgArg, int ErrCode)
|
||||
{
|
||||
#ifndef DISABLE_TLS
|
||||
if (m_bTLSError)
|
||||
if (ErrCode == 0)
|
||||
{
|
||||
// TLS-Error was already reported
|
||||
m_bTLSError = false;
|
||||
return;
|
||||
}
|
||||
#ifdef WIN32
|
||||
ErrCode = WSAGetLastError();
|
||||
#else
|
||||
ErrCode = errno;
|
||||
#endif
|
||||
}
|
||||
|
||||
char szErrPrefix[1024];
|
||||
snprintf(szErrPrefix, 1024, szMsgPrefix, szMsgArg);
|
||||
szErrPrefix[1024-1] = '\0';
|
||||
|
||||
if (PrintErrCode)
|
||||
{
|
||||
#ifdef WIN32
|
||||
int ErrCode = WSAGetLastError();
|
||||
if (m_bSuppressErrors)
|
||||
{
|
||||
debug("%s: ErrNo %i", szErrPrefix, ErrCode);
|
||||
}
|
||||
else
|
||||
{
|
||||
error("%s: ErrNo %i", szErrPrefix, ErrCode);
|
||||
}
|
||||
if (m_bSuppressErrors)
|
||||
{
|
||||
debug("%s: ErrNo %i", szErrPrefix, ErrCode);
|
||||
}
|
||||
else
|
||||
{
|
||||
error("%s: ErrNo %i", szErrPrefix, ErrCode);
|
||||
}
|
||||
#else
|
||||
const char *szErrMsg = NULL;
|
||||
int ErrCode = herrno;
|
||||
if (herrno == 0)
|
||||
{
|
||||
ErrCode = errno;
|
||||
szErrMsg = strerror(ErrCode);
|
||||
}
|
||||
else
|
||||
{
|
||||
szErrMsg = hstrerror(ErrCode);
|
||||
}
|
||||
|
||||
if (m_bSuppressErrors)
|
||||
{
|
||||
debug("%s: ErrNo %i, %s", szErrPrefix, ErrCode, szErrMsg);
|
||||
}
|
||||
else
|
||||
{
|
||||
error("%s: ErrNo %i, %s", szErrPrefix, ErrCode, szErrMsg);
|
||||
}
|
||||
#endif
|
||||
const char* szErrMsg = hstrerror(ErrCode);
|
||||
if (m_bSuppressErrors)
|
||||
{
|
||||
debug("%s: ErrNo %i, %s", szErrPrefix, ErrCode, szErrMsg);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_bSuppressErrors)
|
||||
{
|
||||
debug(szErrPrefix);
|
||||
}
|
||||
else
|
||||
{
|
||||
error(szErrPrefix);
|
||||
}
|
||||
error("%s: ErrNo %i, %s", szErrPrefix, ErrCode, szErrMsg);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef DISABLE_TLS
|
||||
bool Connection::CheckTLSResult(int iResultCode, char* szErrStr, const char* szErrMsgPrefix)
|
||||
{
|
||||
bool bOK = iResultCode == TLS_EOK;
|
||||
if (!bOK)
|
||||
{
|
||||
ReportError(szErrMsgPrefix, szErrStr ? szErrStr : "unknown error", false, 0);
|
||||
if (szErrStr)
|
||||
{
|
||||
free(szErrStr);
|
||||
}
|
||||
}
|
||||
return bOK;
|
||||
}
|
||||
|
||||
bool Connection::StartTLS()
|
||||
{
|
||||
debug("Starting TLS");
|
||||
|
||||
if (m_pTLS)
|
||||
{
|
||||
free(m_pTLS);
|
||||
}
|
||||
|
||||
m_pTLS = malloc(sizeof(tls_t));
|
||||
tls_t* pTLS = (tls_t*)m_pTLS;
|
||||
memset(pTLS, 0, sizeof(tls_t));
|
||||
tls_clear(pTLS);
|
||||
|
||||
char* szErrStr;
|
||||
int iRes;
|
||||
|
||||
iRes = tls_init(pTLS, NULL, NULL, NULL, 0, &szErrStr);
|
||||
if (!CheckTLSResult(iRes, szErrStr, "Could not initialize TLS-object: %s"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
debug("tls_start...");
|
||||
iRes = tls_start(pTLS, (int)m_iSocket, NULL, 1, NULL, &szErrStr);
|
||||
debug("tls_start...%i", iRes);
|
||||
if (!CheckTLSResult(iRes, szErrStr, "Could not establish secure connection: %s"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Connection::CloseTLS()
|
||||
{
|
||||
tls_close((tls_t*)m_pTLS);
|
||||
free(m_pTLS);
|
||||
m_pTLS = NULL;
|
||||
}
|
||||
|
||||
int Connection::recv(SOCKET s, char* buf, int len, int flags)
|
||||
{
|
||||
size_t iReceived = 0;
|
||||
|
||||
if (m_pTLS)
|
||||
{
|
||||
m_bTLSError = false;
|
||||
char* szErrStr;
|
||||
int iRes = tls_getbuf((tls_t*)m_pTLS, buf, len, &iReceived, &szErrStr);
|
||||
if (!CheckTLSResult(iRes, szErrStr, "Could not read from TLS-socket: %s"))
|
||||
{
|
||||
m_bTLSError = true;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
iReceived = ::recv(s, buf, len, flags);
|
||||
}
|
||||
return iReceived;
|
||||
}
|
||||
|
||||
int Connection::send(SOCKET s, const char* buf, int len, int flags)
|
||||
{
|
||||
if (m_pTLS)
|
||||
{
|
||||
m_bTLSError = false;
|
||||
char* szErrStr;
|
||||
int iRes = tls_putbuf((tls_t*)m_pTLS, buf, len, &szErrStr);
|
||||
if (!CheckTLSResult(iRes, szErrStr, "Could not send to TLS-socket: %s"))
|
||||
{
|
||||
m_bTLSError = true;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
int iRet = ::send(s, buf, len, flags);
|
||||
return iRet;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_GETADDRINFO
|
||||
unsigned int Connection::ResolveHostAddr(const char* szHost)
|
||||
{
|
||||
unsigned int uaddr = inet_addr(szHost);
|
||||
if (uaddr == (unsigned int)-1)
|
||||
{
|
||||
struct hostent* hinfo;
|
||||
bool err = false;
|
||||
int h_errnop = 0;
|
||||
#ifdef HAVE_GETHOSTBYNAME_R
|
||||
struct hostent hinfobuf;
|
||||
char strbuf[1024];
|
||||
#ifdef HAVE_GETHOSTBYNAME_R_6
|
||||
err = gethostbyname_r(szHost, &hinfobuf, strbuf, sizeof(strbuf), &hinfo, &h_errnop);
|
||||
err = err || (hinfo == NULL); // error on null hinfo (means 'no entry')
|
||||
#endif
|
||||
#ifdef HAVE_GETHOSTBYNAME_R_5
|
||||
hinfo = gethostbyname_r(szHost, &hinfobuf, strbuf, sizeof(strbuf), &h_errnop);
|
||||
err = hinfo == NULL;
|
||||
#endif
|
||||
#ifdef HAVE_GETHOSTBYNAME_R_3
|
||||
//NOTE: gethostbyname_r with three parameters were not tested
|
||||
struct hostent_data hinfo_data;
|
||||
hinfo = gethostbyname_r((char*)szHost, (struct hostent*)hinfobuf, &hinfo_data);
|
||||
err = hinfo == NULL;
|
||||
#endif
|
||||
#else
|
||||
m_pMutexGetHostByName->Lock();
|
||||
hinfo = gethostbyname(szHost);
|
||||
err = hinfo == NULL;
|
||||
#endif
|
||||
if (err)
|
||||
{
|
||||
#ifndef HAVE_GETHOSTBYNAME_R
|
||||
m_pMutexGetHostByName->Unlock();
|
||||
#endif
|
||||
ReportError("Could not resolve hostname %s", szHost, true, h_errnop);
|
||||
return (unsigned int)-1;
|
||||
}
|
||||
|
||||
memcpy(&uaddr, hinfo->h_addr_list[0], sizeof(uaddr));
|
||||
|
||||
#ifndef HAVE_GETHOSTBYNAME_R
|
||||
m_pMutexGetHostByName->Unlock();
|
||||
#endif
|
||||
}
|
||||
return uaddr;
|
||||
}
|
||||
#endif
|
||||
|
||||
46
Connection.h
46
Connection.h
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
* This file if part of nzbget
|
||||
*
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007-2009 Andrei Prygounkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007 Andrei Prygounkov <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
|
||||
@@ -28,11 +28,6 @@
|
||||
#define CONNECTION_H
|
||||
|
||||
#include "NetAddress.h"
|
||||
#ifndef HAVE_GETADDRINFO
|
||||
#ifndef HAVE_GETHOSTBYNAME_R
|
||||
#include "Thread.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
class Connection
|
||||
{
|
||||
@@ -55,42 +50,24 @@ protected:
|
||||
int m_iTimeout;
|
||||
bool m_bSuppressErrors;
|
||||
bool m_bAutoClose;
|
||||
#ifndef DISABLE_TLS
|
||||
void* m_pTLS;
|
||||
static bool bTLSLibInitialized;
|
||||
bool m_bTLSError;
|
||||
#endif
|
||||
#ifndef HAVE_GETADDRINFO
|
||||
#ifndef HAVE_GETHOSTBYNAME_R
|
||||
static Mutex* m_pMutexGetHostByName;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void ReportError(const char* szMsgPrefix, const char* szMsgArg, bool PrintErrCode, int herrno);
|
||||
virtual bool DoConnect();
|
||||
virtual bool DoDisconnect();
|
||||
unsigned int ResolveHostAddr(const char* szHost);
|
||||
void ReportError(const char* szMsgPrefix, const char* szMsgArg, int ErrCode);
|
||||
virtual int DoConnect();
|
||||
virtual int 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
|
||||
#ifndef DISABLE_TLS
|
||||
bool CheckTLSResult(int iResultCode, char* szErrStr, const char* szErrMsgPrefix);
|
||||
int recv(SOCKET s, char* buf, int len, int flags);
|
||||
int send(SOCKET s, const char* buf, int len, int flags);
|
||||
void CloseTLS();
|
||||
#endif
|
||||
|
||||
public:
|
||||
Connection(NetAddress* pNetAddress);
|
||||
Connection(SOCKET iSocket, bool bAutoClose);
|
||||
virtual ~Connection();
|
||||
static void Init(bool bTLS);
|
||||
static void Init();
|
||||
static void Final();
|
||||
bool Connect();
|
||||
bool Disconnect();
|
||||
int Connect();
|
||||
int Disconnect();
|
||||
int Bind();
|
||||
int Send(const char* pBuffer, int iSize);
|
||||
int Recv(char* pBuffer, int iSize);
|
||||
@@ -105,9 +82,6 @@ public:
|
||||
EStatus GetStatus() { return m_eStatus; }
|
||||
void SetSuppressErrors(bool bSuppressErrors) { m_bSuppressErrors = bSuppressErrors; }
|
||||
bool GetSuppressErrors() { return m_bSuppressErrors; }
|
||||
#ifndef DISABLE_TLS
|
||||
bool StartTLS();
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -141,7 +141,7 @@ void YDecoder::Clear()
|
||||
m_lExpectedCRC = 0;
|
||||
m_lCalculatedCRC = 0xFFFFFFFF;
|
||||
m_iBegin = 0;
|
||||
m_iEnd = 0xFFFFFFFF;
|
||||
m_iEnd = 0;
|
||||
m_iSize = 0;
|
||||
m_iEndSize = 0;
|
||||
m_bAutoSeek = false;
|
||||
@@ -319,7 +319,7 @@ bool YDecoder::Write(char* buffer, int len, FILE* outfile)
|
||||
{
|
||||
if (m_bNeedSetPos)
|
||||
{
|
||||
if (m_iBegin == 0 || m_iEnd == 0xFFFFFFFF || !outfile)
|
||||
if (m_iBegin == 0 || m_iEnd == 0 || !outfile)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007-2008 Andrei Prygounkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007 Andrei Prygounkov <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,6 +27,8 @@
|
||||
#ifndef DECODER_H
|
||||
#define DECODER_H
|
||||
|
||||
#include "Thread.h"
|
||||
|
||||
class Decoder
|
||||
{
|
||||
public:
|
||||
|
||||
736
DiskState.cpp
736
DiskState.cpp
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2007-2009 Andrei Prygounkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2007 Andrei Prygounkov <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 <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "nzbget.h"
|
||||
#include "DiskState.h"
|
||||
@@ -45,22 +44,10 @@
|
||||
|
||||
extern Options* g_pOptions;
|
||||
|
||||
static const char* FORMATVERSION_SIGNATURE = "nzbget diskstate file version ";
|
||||
|
||||
/* Parse signature and return format version number
|
||||
*/
|
||||
int DiskState::ParseFormatVersion(const char* szFormatSignature)
|
||||
{
|
||||
if (strncmp(szFormatSignature, FORMATVERSION_SIGNATURE, strlen(FORMATVERSION_SIGNATURE)))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return atoi(szFormatSignature + strlen(FORMATVERSION_SIGNATURE));
|
||||
}
|
||||
static const char* FORMATVERSION_SIGNATURE = "nzbget diskstate file version 3\n";
|
||||
|
||||
/* Save Download Queue to Disk.
|
||||
* The Disk State consists of file "queue", which contains the order of files,
|
||||
* The Disk State consists of file "queue", which contains the order of files
|
||||
* and of one diskstate-file for each file in download queue.
|
||||
* This function saves file "queue" and files with NZB-info. It does not
|
||||
* save file-infos.
|
||||
@@ -69,11 +56,35 @@ bool DiskState::SaveDownloadQueue(DownloadQueue* pDownloadQueue)
|
||||
{
|
||||
debug("Saving queue to disk");
|
||||
|
||||
// prepare list of nzb-infos
|
||||
|
||||
typedef std::deque<NZBInfo*> NZBList;
|
||||
NZBList cNZBList;
|
||||
|
||||
for (DownloadQueue::iterator it = pDownloadQueue->begin(); it != pDownloadQueue->end(); it++)
|
||||
{
|
||||
FileInfo* pFileInfo = *it;
|
||||
bool inlist = false;
|
||||
for (NZBList::iterator it = cNZBList.begin(); it != cNZBList.end(); it++)
|
||||
{
|
||||
NZBInfo* pNZBInfo = *it;
|
||||
if (pNZBInfo == pFileInfo->GetNZBInfo())
|
||||
{
|
||||
inlist = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!inlist)
|
||||
{
|
||||
cNZBList.push_back(pFileInfo->GetNZBInfo());
|
||||
}
|
||||
}
|
||||
|
||||
char fileName[1024];
|
||||
snprintf(fileName, 1024, "%s%s", g_pOptions->GetQueueDir(), "queue");
|
||||
fileName[1024-1] = '\0';
|
||||
|
||||
FILE* outfile = fopen(fileName, "wb");
|
||||
FILE* outfile = fopen(fileName, "w");
|
||||
|
||||
if (!outfile)
|
||||
{
|
||||
@@ -82,28 +93,45 @@ bool DiskState::SaveDownloadQueue(DownloadQueue* pDownloadQueue)
|
||||
return false;
|
||||
}
|
||||
|
||||
fprintf(outfile, "%s%i\n", FORMATVERSION_SIGNATURE, 12);
|
||||
fprintf(outfile, FORMATVERSION_SIGNATURE);
|
||||
|
||||
// save nzb-infos
|
||||
SaveNZBList(pDownloadQueue, outfile);
|
||||
fprintf(outfile, "%i\n", cNZBList.size());
|
||||
for (NZBList::iterator it = cNZBList.begin(); it != cNZBList.end(); it++)
|
||||
{
|
||||
NZBInfo* pNZBInfo = *it;
|
||||
fprintf(outfile, "%s\n", pNZBInfo->GetFilename());
|
||||
fprintf(outfile, "%s\n", pNZBInfo->GetDestDir());
|
||||
fprintf(outfile, "%i\n", pNZBInfo->GetFileCount());
|
||||
unsigned long High, Low;
|
||||
Util::SplitInt64(pNZBInfo->GetSize(), &High, &Low);
|
||||
fprintf(outfile, "%lu,%lu\n", High, Low);
|
||||
}
|
||||
|
||||
// save file-infos
|
||||
SaveFileQueue(pDownloadQueue, pDownloadQueue->GetFileQueue(), outfile);
|
||||
|
||||
// save post-queue
|
||||
SavePostQueue(pDownloadQueue, outfile);
|
||||
|
||||
// save history
|
||||
SaveHistory(pDownloadQueue, outfile);
|
||||
|
||||
// save parked file-infos
|
||||
SaveFileQueue(pDownloadQueue, pDownloadQueue->GetParkedFiles(), outfile);
|
||||
fprintf(outfile, "%i\n", pDownloadQueue->size());
|
||||
for (DownloadQueue::iterator it = pDownloadQueue->begin(); it != pDownloadQueue->end(); it++)
|
||||
{
|
||||
FileInfo* pFileInfo = *it;
|
||||
if (!pFileInfo->GetDeleted())
|
||||
{
|
||||
// find index of nzb-info
|
||||
int iNZBIndex = 0;
|
||||
for (unsigned int i = 0; i < cNZBList.size(); i++)
|
||||
{
|
||||
iNZBIndex++;
|
||||
if (cNZBList[i] == pFileInfo->GetNZBInfo())
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(outfile, "%i,%i,%i\n", pFileInfo->GetID(), iNZBIndex, (int)pFileInfo->GetPaused());
|
||||
}
|
||||
}
|
||||
fclose(outfile);
|
||||
|
||||
if (pDownloadQueue->GetFileQueue()->empty() &&
|
||||
pDownloadQueue->GetPostQueue()->empty() &&
|
||||
pDownloadQueue->GetHistoryList()->empty())
|
||||
if (pDownloadQueue->empty())
|
||||
{
|
||||
remove(fileName);
|
||||
}
|
||||
@@ -115,13 +143,14 @@ bool DiskState::LoadDownloadQueue(DownloadQueue* pDownloadQueue)
|
||||
{
|
||||
debug("Loading queue from disk");
|
||||
|
||||
bool bOK = false;
|
||||
typedef std::deque<NZBInfo*> NZBList;
|
||||
NZBList cNZBList;
|
||||
|
||||
char fileName[1024];
|
||||
snprintf(fileName, 1024, "%s%s", g_pOptions->GetQueueDir(), "queue");
|
||||
fileName[1024-1] = '\0';
|
||||
|
||||
FILE* infile = fopen(fileName, "rb");
|
||||
FILE* infile = fopen(fileName, "r");
|
||||
|
||||
if (!infile)
|
||||
{
|
||||
@@ -131,128 +160,22 @@ bool DiskState::LoadDownloadQueue(DownloadQueue* pDownloadQueue)
|
||||
|
||||
char FileSignatur[128];
|
||||
fgets(FileSignatur, sizeof(FileSignatur), infile);
|
||||
int iFormatVersion = ParseFormatVersion(FileSignatur);
|
||||
if (iFormatVersion < 3 || iFormatVersion > 12)
|
||||
if (strcmp(FileSignatur, FORMATVERSION_SIGNATURE))
|
||||
{
|
||||
error("Could not load diskstate due to file version mismatch");
|
||||
error("Could not load diskstate due file version mismatch");
|
||||
fclose(infile);
|
||||
return false;
|
||||
}
|
||||
|
||||
// load nzb-infos
|
||||
if (!LoadNZBList(pDownloadQueue, infile, iFormatVersion)) goto error;
|
||||
|
||||
// load file-infos
|
||||
if (!LoadFileQueue(pDownloadQueue, pDownloadQueue->GetFileQueue(), infile, iFormatVersion)) goto error;
|
||||
|
||||
if (iFormatVersion >= 7)
|
||||
{
|
||||
// load post-queue
|
||||
if (!LoadPostQueue(pDownloadQueue, infile)) goto error;
|
||||
}
|
||||
else if (iFormatVersion < 7 && g_pOptions->GetReloadPostQueue())
|
||||
{
|
||||
// load post-queue created with older version of program
|
||||
LoadOldPostQueue(pDownloadQueue);
|
||||
}
|
||||
|
||||
if (iFormatVersion >= 9)
|
||||
{
|
||||
// load history
|
||||
if (!LoadHistory(pDownloadQueue, infile)) goto error;
|
||||
|
||||
// load parked file-infos
|
||||
if (!LoadFileQueue(pDownloadQueue, pDownloadQueue->GetParkedFiles(), infile, iFormatVersion)) goto error;
|
||||
}
|
||||
|
||||
bOK = true;
|
||||
|
||||
error:
|
||||
|
||||
fclose(infile);
|
||||
if (!bOK)
|
||||
{
|
||||
error("Error reading diskstate for file %s", fileName);
|
||||
}
|
||||
|
||||
pDownloadQueue->GetNZBInfoList()->ReleaseAll();
|
||||
|
||||
return bOK;
|
||||
}
|
||||
|
||||
void DiskState::SaveNZBList(DownloadQueue* pDownloadQueue, FILE* outfile)
|
||||
{
|
||||
debug("Saving nzb list to disk");
|
||||
|
||||
fprintf(outfile, "%i\n", pDownloadQueue->GetNZBInfoList()->size());
|
||||
for (NZBInfoList::iterator it = pDownloadQueue->GetNZBInfoList()->begin(); it != pDownloadQueue->GetNZBInfoList()->end(); it++)
|
||||
{
|
||||
NZBInfo* pNZBInfo = *it;
|
||||
fprintf(outfile, "%s\n", pNZBInfo->GetFilename());
|
||||
fprintf(outfile, "%s\n", pNZBInfo->GetDestDir());
|
||||
fprintf(outfile, "%s\n", pNZBInfo->GetQueuedFilename());
|
||||
fprintf(outfile, "%s\n", pNZBInfo->GetCategory());
|
||||
fprintf(outfile, "%i\n", pNZBInfo->GetPostProcess() ? 1 : 0);
|
||||
fprintf(outfile, "%i\n", (int)pNZBInfo->GetParStatus());
|
||||
fprintf(outfile, "%i\n", (int)pNZBInfo->GetScriptStatus());
|
||||
fprintf(outfile, "%i\n", pNZBInfo->GetFileCount());
|
||||
fprintf(outfile, "%i\n", pNZBInfo->GetParkedFileCount());
|
||||
|
||||
unsigned long High, Low;
|
||||
Util::SplitInt64(pNZBInfo->GetSize(), &High, &Low);
|
||||
fprintf(outfile, "%lu,%lu\n", High, Low);
|
||||
|
||||
char DestDirSlash[1024];
|
||||
snprintf(DestDirSlash, 1023, "%s%c", pNZBInfo->GetDestDir(), PATH_SEPARATOR);
|
||||
int iDestDirLen = strlen(DestDirSlash);
|
||||
|
||||
fprintf(outfile, "%i\n", pNZBInfo->GetCompletedFiles()->size());
|
||||
for (NZBInfo::Files::iterator it = pNZBInfo->GetCompletedFiles()->begin(); it != pNZBInfo->GetCompletedFiles()->end(); it++)
|
||||
{
|
||||
char* szFilename = *it;
|
||||
// do not save full path to reduce the size of queue-file
|
||||
if (!strncmp(DestDirSlash, szFilename, iDestDirLen))
|
||||
{
|
||||
fprintf(outfile, "%s\n", szFilename + iDestDirLen);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(outfile, "%s\n", szFilename);
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(outfile, "%i\n", pNZBInfo->GetParameters()->size());
|
||||
for (NZBParameterList::iterator it = pNZBInfo->GetParameters()->begin(); it != pNZBInfo->GetParameters()->end(); it++)
|
||||
{
|
||||
NZBParameter* pParameter = *it;
|
||||
fprintf(outfile, "%s=%s\n", pParameter->GetName(), pParameter->GetValue());
|
||||
}
|
||||
|
||||
NZBInfo::Messages* pMessages = pNZBInfo->LockMessages();
|
||||
fprintf(outfile, "%i\n", pMessages->size());
|
||||
for (NZBInfo::Messages::iterator it = pMessages->begin(); it != pMessages->end(); it++)
|
||||
{
|
||||
Message* pMessage = *it;
|
||||
fprintf(outfile, "%i,%i,%s\n", pMessage->GetKind(), (int)pMessage->GetTime(), pMessage->GetText());
|
||||
}
|
||||
pNZBInfo->UnlockMessages();
|
||||
}
|
||||
}
|
||||
|
||||
bool DiskState::LoadNZBList(DownloadQueue* pDownloadQueue, FILE* infile, int iFormatVersion)
|
||||
{
|
||||
debug("Loading nzb list from disk");
|
||||
|
||||
int size;
|
||||
char buf[10240];
|
||||
char buf[1024];
|
||||
|
||||
// load nzb-infos
|
||||
if (fscanf(infile, "%i\n", &size) != 1) goto error;
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
NZBInfo* pNZBInfo = new NZBInfo();
|
||||
pNZBInfo->AddReference();
|
||||
pDownloadQueue->GetNZBInfoList()->Add(pNZBInfo);
|
||||
cNZBList.push_back(pNZBInfo);
|
||||
|
||||
if (!fgets(buf, sizeof(buf), infile)) goto error;
|
||||
if (buf[0] != 0) buf[strlen(buf)-1] = 0; // remove traling '\n'
|
||||
@@ -262,156 +185,22 @@ bool DiskState::LoadNZBList(DownloadQueue* pDownloadQueue, FILE* infile, int iFo
|
||||
if (buf[0] != 0) buf[strlen(buf)-1] = 0; // remove traling '\n'
|
||||
pNZBInfo->SetDestDir(buf);
|
||||
|
||||
if (iFormatVersion >= 5)
|
||||
{
|
||||
if (!fgets(buf, sizeof(buf), infile)) goto error;
|
||||
if (buf[0] != 0) buf[strlen(buf)-1] = 0; // remove traling '\n'
|
||||
pNZBInfo->SetQueuedFilename(buf);
|
||||
}
|
||||
|
||||
if (iFormatVersion >= 4)
|
||||
{
|
||||
if (!fgets(buf, sizeof(buf), infile)) goto error;
|
||||
if (buf[0] != 0) buf[strlen(buf)-1] = 0; // remove traling '\n'
|
||||
pNZBInfo->SetCategory(buf);
|
||||
|
||||
int iPostProcess;
|
||||
if (fscanf(infile, "%i\n", &iPostProcess) != 1) goto error;
|
||||
pNZBInfo->SetPostProcess(iPostProcess == 1);
|
||||
}
|
||||
|
||||
if (iFormatVersion >= 8)
|
||||
{
|
||||
int iParStatus;
|
||||
if (fscanf(infile, "%i\n", &iParStatus) != 1) goto error;
|
||||
pNZBInfo->SetParStatus((NZBInfo::EParStatus)iParStatus);
|
||||
}
|
||||
|
||||
if (iFormatVersion >= 9)
|
||||
{
|
||||
int iScriptStatus;
|
||||
if (fscanf(infile, "%i\n", &iScriptStatus) != 1) goto error;
|
||||
pNZBInfo->SetScriptStatus((NZBInfo::EScriptStatus)iScriptStatus);
|
||||
}
|
||||
|
||||
int iFileCount;
|
||||
if (fscanf(infile, "%i\n", &iFileCount) != 1) goto error;
|
||||
pNZBInfo->SetFileCount(iFileCount);
|
||||
|
||||
if (iFormatVersion >= 10)
|
||||
{
|
||||
if (fscanf(infile, "%i\n", &iFileCount) != 1) goto error;
|
||||
pNZBInfo->SetParkedFileCount(iFileCount);
|
||||
}
|
||||
|
||||
unsigned long High, Low;
|
||||
if (fscanf(infile, "%lu,%lu\n", &High, &Low) != 2) goto error;
|
||||
pNZBInfo->SetSize(Util::JoinInt64(High, Low));
|
||||
|
||||
if (iFormatVersion >= 4)
|
||||
{
|
||||
int iFileCount;
|
||||
if (fscanf(infile, "%i\n", &iFileCount) != 1) goto error;
|
||||
for (int i = 0; i < iFileCount; i++)
|
||||
{
|
||||
if (!fgets(buf, sizeof(buf), infile)) goto error;
|
||||
if (buf[0] != 0) buf[strlen(buf)-1] = 0; // remove traling '\n'
|
||||
|
||||
// restore full file name.
|
||||
char* szFileName = buf;
|
||||
char FullFileName[1024];
|
||||
if (!strchr(buf, PATH_SEPARATOR))
|
||||
{
|
||||
snprintf(FullFileName, 1023, "%s%c%s", pNZBInfo->GetDestDir(), PATH_SEPARATOR, buf);
|
||||
szFileName = FullFileName;
|
||||
}
|
||||
|
||||
pNZBInfo->GetCompletedFiles()->push_back(strdup(szFileName));
|
||||
}
|
||||
}
|
||||
|
||||
if (iFormatVersion >= 6)
|
||||
{
|
||||
int iParameterCount;
|
||||
if (fscanf(infile, "%i\n", &iParameterCount) != 1) goto error;
|
||||
for (int i = 0; i < iParameterCount; i++)
|
||||
{
|
||||
if (!fgets(buf, sizeof(buf), infile)) goto error;
|
||||
if (buf[0] != 0) buf[strlen(buf)-1] = 0; // remove traling '\n'
|
||||
|
||||
char* szValue = strchr(buf, '=');
|
||||
if (szValue)
|
||||
{
|
||||
*szValue = '\0';
|
||||
szValue++;
|
||||
pNZBInfo->SetParameter(buf, szValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (iFormatVersion >= 11)
|
||||
{
|
||||
int iLogCount;
|
||||
if (fscanf(infile, "%i\n", &iLogCount) != 1) goto error;
|
||||
for (int i = 0; i < iLogCount; i++)
|
||||
{
|
||||
if (!fgets(buf, sizeof(buf), infile)) goto error;
|
||||
if (buf[0] != 0) buf[strlen(buf)-1] = 0; // remove traling '\n'
|
||||
|
||||
int iKind, iTime;
|
||||
sscanf(buf, "%i,%i", &iKind, &iTime);
|
||||
char* szText = strchr(buf + 2, ',');
|
||||
if (szText) {
|
||||
szText++;
|
||||
}
|
||||
pNZBInfo->AppendMessage((Message::EKind)iKind, (time_t)iTime, szText);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
error:
|
||||
error("Error reading nzb list from disk");
|
||||
return false;
|
||||
}
|
||||
|
||||
void DiskState::SaveFileQueue(DownloadQueue* pDownloadQueue, FileQueue* pFileQueue, FILE* outfile)
|
||||
{
|
||||
debug("Saving file queue to disk");
|
||||
|
||||
// save file-infos
|
||||
fprintf(outfile, "%i\n", pFileQueue->size());
|
||||
for (FileQueue::iterator it = pFileQueue->begin(); it != pFileQueue->end(); it++)
|
||||
{
|
||||
FileInfo* pFileInfo = *it;
|
||||
if (!pFileInfo->GetDeleted())
|
||||
{
|
||||
int iNZBIndex = FindNZBInfoIndex(pDownloadQueue, pFileInfo->GetNZBInfo());
|
||||
fprintf(outfile, "%i,%i,%i,%i\n", pFileInfo->GetID(), iNZBIndex, (int)pFileInfo->GetPaused(), (int)pFileInfo->GetTime());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool DiskState::LoadFileQueue(DownloadQueue* pDownloadQueue, FileQueue* pFileQueue, FILE* infile, int iFormatVersion)
|
||||
{
|
||||
debug("Loading file queue from disk");
|
||||
|
||||
int size;
|
||||
// load file-infos
|
||||
if (fscanf(infile, "%i\n", &size) != 1) goto error;
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
unsigned int id, iNZBIndex, paused, iTime;
|
||||
if (iFormatVersion >= 12)
|
||||
{
|
||||
if (fscanf(infile, "%i,%i,%i,%i\n", &id, &iNZBIndex, &paused, &iTime) != 4) goto error;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fscanf(infile, "%i,%i,%i\n", &id, &iNZBIndex, &paused) != 3) goto error;
|
||||
iTime = 0;
|
||||
}
|
||||
if (iNZBIndex < 0 || iNZBIndex > pDownloadQueue->GetNZBInfoList()->size()) goto error;
|
||||
unsigned int id, iNZBIndex, paused;
|
||||
if (fscanf(infile, "%i,%i,%i\n", &id, &iNZBIndex, &paused) != 3) goto error;
|
||||
if (iNZBIndex < 0 || iNZBIndex > cNZBList.size()) goto error;
|
||||
|
||||
char fileName[1024];
|
||||
snprintf(fileName, 1024, "%s%i", g_pOptions->GetQueueDir(), id);
|
||||
@@ -422,9 +211,8 @@ bool DiskState::LoadFileQueue(DownloadQueue* pDownloadQueue, FileQueue* pFileQue
|
||||
{
|
||||
pFileInfo->SetID(id);
|
||||
pFileInfo->SetPaused(paused);
|
||||
pFileInfo->SetTime(iTime);
|
||||
pFileInfo->SetNZBInfo(pDownloadQueue->GetNZBInfoList()->at(iNZBIndex - 1));
|
||||
pFileQueue->push_back(pFileInfo);
|
||||
pFileInfo->SetNZBInfo(cNZBList[iNZBIndex - 1]);
|
||||
pDownloadQueue->push_back(pFileInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -433,10 +221,12 @@ bool DiskState::LoadFileQueue(DownloadQueue* pDownloadQueue, FileQueue* pFileQue
|
||||
}
|
||||
}
|
||||
|
||||
fclose(infile);
|
||||
return true;
|
||||
|
||||
error:
|
||||
error("Error reading file queue from disk");
|
||||
fclose(infile);
|
||||
error("Error reading diskstate for file %s", fileName);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -452,7 +242,7 @@ bool DiskState::SaveFileInfo(FileInfo* pFileInfo, const char* szFilename)
|
||||
{
|
||||
debug("Saving FileInfo to disk");
|
||||
|
||||
FILE* outfile = fopen(szFilename, "wb");
|
||||
FILE* outfile = fopen(szFilename, "w");
|
||||
|
||||
if (!outfile)
|
||||
{
|
||||
@@ -497,7 +287,7 @@ bool DiskState::LoadFileInfo(FileInfo* pFileInfo, const char * szFilename, bool
|
||||
{
|
||||
debug("Loading FileInfo from disk");
|
||||
|
||||
FILE* infile = fopen(szFilename, "rb");
|
||||
FILE* infile = fopen(szFilename, "r");
|
||||
|
||||
if (!infile)
|
||||
{
|
||||
@@ -561,86 +351,57 @@ error:
|
||||
return false;
|
||||
}
|
||||
|
||||
void DiskState::SavePostQueue(DownloadQueue* pDownloadQueue, FILE* outfile)
|
||||
bool DiskState::SavePostQueue(PostQueue* pPostQueue, bool bCompleted)
|
||||
{
|
||||
debug("Saving post-queue to disk");
|
||||
|
||||
fprintf(outfile, "%i\n", pDownloadQueue->GetPostQueue()->size());
|
||||
for (PostQueue::iterator it = pDownloadQueue->GetPostQueue()->begin(); it != pDownloadQueue->GetPostQueue()->end(); it++)
|
||||
char fileName[1024];
|
||||
snprintf(fileName, 1024, "%s%s", g_pOptions->GetQueueDir(), bCompleted ? "postc" : "postq");
|
||||
fileName[1024-1] = '\0';
|
||||
|
||||
FILE* outfile = fopen(fileName, "w");
|
||||
|
||||
if (!outfile)
|
||||
{
|
||||
error("Could not create file %s", fileName);
|
||||
perror(fileName);
|
||||
return false;
|
||||
}
|
||||
|
||||
fprintf(outfile, FORMATVERSION_SIGNATURE);
|
||||
|
||||
fprintf(outfile, "%i\n", pPostQueue->size());
|
||||
for (PostQueue::iterator it = pPostQueue->begin(); it != pPostQueue->end(); it++)
|
||||
{
|
||||
PostInfo* pPostInfo = *it;
|
||||
int iNZBIndex = FindNZBInfoIndex(pDownloadQueue, pPostInfo->GetNZBInfo());
|
||||
fprintf(outfile, "%i,%i,%i,%i\n", iNZBIndex, (int)pPostInfo->GetParCheck(),
|
||||
(int)pPostInfo->GetParStatus(), (int)pPostInfo->GetStage());
|
||||
fprintf(outfile, "%s\n", pPostInfo->GetInfoName());
|
||||
fprintf(outfile, "%s\n", pPostInfo->GetNZBFilename());
|
||||
fprintf(outfile, "%s\n", pPostInfo->GetDestDir());
|
||||
fprintf(outfile, "%s\n", pPostInfo->GetParFilename());
|
||||
fprintf(outfile, "%s\n", pPostInfo->GetInfoName());
|
||||
fprintf(outfile, "%i\n", (int)pPostInfo->GetParCheck());
|
||||
fprintf(outfile, "%i\n", (int)pPostInfo->GetParStatus());
|
||||
fprintf(outfile, "%i\n", (int)pPostInfo->GetParFailed());
|
||||
fprintf(outfile, "%i\n", (int)pPostInfo->GetStage());
|
||||
}
|
||||
}
|
||||
fclose(outfile);
|
||||
|
||||
bool DiskState::LoadPostQueue(DownloadQueue* pDownloadQueue, FILE* infile)
|
||||
{
|
||||
debug("Loading post-queue from disk");
|
||||
|
||||
bool bSkipPostQueue = !g_pOptions->GetReloadPostQueue();
|
||||
int size;
|
||||
char buf[10240];
|
||||
|
||||
// load file-infos
|
||||
if (fscanf(infile, "%i\n", &size) != 1) goto error;
|
||||
for (int i = 0; i < size; i++)
|
||||
if (pPostQueue->empty())
|
||||
{
|
||||
PostInfo* pPostInfo = NULL;
|
||||
unsigned int iNZBIndex, iParCheck, iParStatus, iStage;
|
||||
if (fscanf(infile, "%i,%i,%i,%i\n", &iNZBIndex, &iParCheck, &iParStatus, &iStage) != 4) goto error;
|
||||
|
||||
if (!bSkipPostQueue)
|
||||
{
|
||||
pPostInfo = new PostInfo();
|
||||
pPostInfo->SetNZBInfo(pDownloadQueue->GetNZBInfoList()->at(iNZBIndex - 1));
|
||||
pPostInfo->SetParCheck(iParCheck);
|
||||
pPostInfo->SetParStatus((PostInfo::EParStatus)iParStatus);
|
||||
pPostInfo->SetStage((PostInfo::EStage)iStage);
|
||||
}
|
||||
|
||||
if (!fgets(buf, sizeof(buf), infile)) goto error;
|
||||
if (buf[0] != 0) buf[strlen(buf)-1] = 0; // remove traling '\n'
|
||||
if (!bSkipPostQueue) pPostInfo->SetInfoName(buf);
|
||||
|
||||
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)
|
||||
{
|
||||
pDownloadQueue->GetPostQueue()->push_back(pPostInfo);
|
||||
}
|
||||
remove(fileName);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
error:
|
||||
error("Error reading diskstate for post-processor queue");
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Loads post-queue created with older versions of nzbget.
|
||||
* Returns true if successful, false if not
|
||||
*/
|
||||
bool DiskState::LoadOldPostQueue(DownloadQueue* pDownloadQueue)
|
||||
bool DiskState::LoadPostQueue(PostQueue* pPostQueue, bool bCompleted)
|
||||
{
|
||||
debug("Loading post-queue from disk");
|
||||
|
||||
char fileName[1024];
|
||||
snprintf(fileName, 1024, "%s%s", g_pOptions->GetQueueDir(), "postq");
|
||||
snprintf(fileName, 1024, "%s%s", g_pOptions->GetQueueDir(), bCompleted ? "postc" : "postq");
|
||||
fileName[1024-1] = '\0';
|
||||
|
||||
if (!Util::FileExists(fileName))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
FILE* infile = fopen(fileName, "rb");
|
||||
FILE* infile = fopen(fileName, "r");
|
||||
|
||||
if (!infile)
|
||||
{
|
||||
@@ -650,16 +411,15 @@ bool DiskState::LoadOldPostQueue(DownloadQueue* pDownloadQueue)
|
||||
|
||||
char FileSignatur[128];
|
||||
fgets(FileSignatur, sizeof(FileSignatur), infile);
|
||||
int iFormatVersion = ParseFormatVersion(FileSignatur);
|
||||
if (iFormatVersion < 3 || iFormatVersion > 7)
|
||||
if (strcmp(FileSignatur, FORMATVERSION_SIGNATURE))
|
||||
{
|
||||
error("Could not load diskstate due to file version mismatch");
|
||||
error("Could not load diskstate due file version mismatch");
|
||||
fclose(infile);
|
||||
return false;
|
||||
}
|
||||
|
||||
int size;
|
||||
char buf[10240];
|
||||
char buf[1024];
|
||||
int iIntValue;
|
||||
|
||||
// load file-infos
|
||||
@@ -670,36 +430,11 @@ bool DiskState::LoadOldPostQueue(DownloadQueue* pDownloadQueue)
|
||||
|
||||
if (!fgets(buf, sizeof(buf), infile)) goto error;
|
||||
if (buf[0] != 0) buf[strlen(buf)-1] = 0; // remove traling '\n'
|
||||
|
||||
// find NZBInfo based on NZBFilename
|
||||
NZBInfo* pNZBInfo = NULL;
|
||||
for (NZBInfoList::iterator it = pDownloadQueue->GetNZBInfoList()->begin(); it != pDownloadQueue->GetNZBInfoList()->end(); it++)
|
||||
{
|
||||
NZBInfo* pNZBInfo2 = *it;
|
||||
if (!strcmp(pNZBInfo2->GetFilename(), buf))
|
||||
{
|
||||
pNZBInfo = pNZBInfo2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool bNewNZBInfo = !pNZBInfo;
|
||||
if (bNewNZBInfo)
|
||||
{
|
||||
pNZBInfo = new NZBInfo();
|
||||
pNZBInfo->AddReference();
|
||||
pDownloadQueue->GetNZBInfoList()->Add(pNZBInfo);
|
||||
pNZBInfo->SetFilename(buf);
|
||||
}
|
||||
|
||||
pPostInfo->SetNZBInfo(pNZBInfo);
|
||||
pPostInfo->SetNZBFilename(buf);
|
||||
|
||||
if (!fgets(buf, sizeof(buf), infile)) goto error;
|
||||
if (buf[0] != 0) buf[strlen(buf)-1] = 0; // remove traling '\n'
|
||||
if (bNewNZBInfo)
|
||||
{
|
||||
pNZBInfo->SetDestDir(buf);
|
||||
}
|
||||
pPostInfo->SetDestDir(buf);
|
||||
|
||||
if (!fgets(buf, sizeof(buf), infile)) goto error;
|
||||
if (buf[0] != 0) buf[strlen(buf)-1] = 0; // remove traling '\n'
|
||||
@@ -709,78 +444,19 @@ bool DiskState::LoadOldPostQueue(DownloadQueue* pDownloadQueue)
|
||||
if (buf[0] != 0) buf[strlen(buf)-1] = 0; // remove traling '\n'
|
||||
pPostInfo->SetInfoName(buf);
|
||||
|
||||
if (iFormatVersion >= 4)
|
||||
{
|
||||
if (!fgets(buf, sizeof(buf), infile)) goto error;
|
||||
if (buf[0] != 0) buf[strlen(buf)-1] = 0; // remove traling '\n'
|
||||
if (bNewNZBInfo)
|
||||
{
|
||||
pNZBInfo->SetCategory(buf);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bNewNZBInfo)
|
||||
{
|
||||
pNZBInfo->SetCategory("");
|
||||
}
|
||||
}
|
||||
|
||||
if (iFormatVersion >= 5)
|
||||
{
|
||||
if (!fgets(buf, sizeof(buf), infile)) goto error;
|
||||
if (buf[0] != 0) buf[strlen(buf)-1] = 0; // remove traling '\n'
|
||||
if (bNewNZBInfo)
|
||||
{
|
||||
pNZBInfo->SetQueuedFilename(buf);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bNewNZBInfo)
|
||||
{
|
||||
pNZBInfo->SetQueuedFilename("");
|
||||
}
|
||||
}
|
||||
|
||||
if (fscanf(infile, "%i\n", &iIntValue) != 1) goto error;
|
||||
pPostInfo->SetParCheck(iIntValue);
|
||||
|
||||
if (fscanf(infile, "%i\n", &iIntValue) != 1) goto error;
|
||||
pPostInfo->SetParStatus((PostInfo::EParStatus)iIntValue);
|
||||
pPostInfo->SetParStatus(iIntValue);
|
||||
|
||||
if (iFormatVersion < 7)
|
||||
{
|
||||
// skip old field ParFailed, not used anymore
|
||||
if (fscanf(infile, "%i\n", &iIntValue) != 1) goto error;
|
||||
}
|
||||
if (fscanf(infile, "%i\n", &iIntValue) != 1) goto error;
|
||||
pPostInfo->SetParFailed(iIntValue);
|
||||
|
||||
if (fscanf(infile, "%i\n", &iIntValue) != 1) goto error;
|
||||
pPostInfo->SetStage((PostInfo::EStage)iIntValue);
|
||||
|
||||
if (iFormatVersion >= 6)
|
||||
{
|
||||
int iParameterCount;
|
||||
if (fscanf(infile, "%i\n", &iParameterCount) != 1) goto error;
|
||||
for (int i = 0; i < iParameterCount; i++)
|
||||
{
|
||||
if (!fgets(buf, sizeof(buf), infile)) goto error;
|
||||
if (buf[0] != 0) buf[strlen(buf)-1] = 0; // remove traling '\n'
|
||||
|
||||
char* szValue = strchr(buf, '=');
|
||||
if (szValue)
|
||||
{
|
||||
*szValue = '\0';
|
||||
szValue++;
|
||||
if (bNewNZBInfo)
|
||||
{
|
||||
pNZBInfo->SetParameter(buf, szValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pDownloadQueue->GetPostQueue()->push_back(pPostInfo);
|
||||
pPostQueue->push_back(pPostInfo);
|
||||
}
|
||||
|
||||
fclose(infile);
|
||||
@@ -792,63 +468,6 @@ error:
|
||||
return false;
|
||||
}
|
||||
|
||||
void DiskState::SaveHistory(DownloadQueue* pDownloadQueue, FILE* outfile)
|
||||
{
|
||||
debug("Saving history to disk");
|
||||
|
||||
fprintf(outfile, "%i\n", pDownloadQueue->GetHistoryList()->size());
|
||||
for (HistoryList::iterator it = pDownloadQueue->GetHistoryList()->begin(); it != pDownloadQueue->GetHistoryList()->end(); it++)
|
||||
{
|
||||
NZBInfo* pNZBInfo = *it;
|
||||
int iNZBIndex = FindNZBInfoIndex(pDownloadQueue, pNZBInfo);
|
||||
fprintf(outfile, "%i\n", iNZBIndex);
|
||||
fprintf(outfile, "%i\n", (int)pNZBInfo->GetHistoryTime());
|
||||
}
|
||||
}
|
||||
|
||||
bool DiskState::LoadHistory(DownloadQueue* pDownloadQueue, FILE* infile)
|
||||
{
|
||||
debug("Loading history from disk");
|
||||
|
||||
int size;
|
||||
if (fscanf(infile, "%i\n", &size) != 1) goto error;
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
unsigned int iNZBIndex;
|
||||
if (fscanf(infile, "%i\n", &iNZBIndex) != 1) goto error;
|
||||
|
||||
NZBInfo* pNZBInfo = pDownloadQueue->GetNZBInfoList()->at(iNZBIndex - 1);
|
||||
|
||||
int iTime;
|
||||
if (fscanf(infile, "%i\n", &iTime) != 1) goto error;
|
||||
pNZBInfo->SetHistoryTime((time_t)iTime);
|
||||
|
||||
pNZBInfo->AddReference();
|
||||
pDownloadQueue->GetHistoryList()->push_back(pNZBInfo);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
error:
|
||||
error("Error reading diskstate for post-processor queue");
|
||||
return false;
|
||||
}
|
||||
|
||||
int DiskState::FindNZBInfoIndex(DownloadQueue* pDownloadQueue, NZBInfo* pNZBInfo)
|
||||
{
|
||||
// find index of nzb-info
|
||||
int iNZBIndex = 0;
|
||||
for (unsigned int i = 0; i < pDownloadQueue->GetNZBInfoList()->size(); i++)
|
||||
{
|
||||
iNZBIndex++;
|
||||
if (pDownloadQueue->GetNZBInfoList()->at(i) == pNZBInfo)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return iNZBIndex;
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete all files from Queue.
|
||||
* Returns true if successful, false if not
|
||||
@@ -861,7 +480,7 @@ bool DiskState::DiscardDownloadQueue()
|
||||
snprintf(fileName, 1024, "%s%s", g_pOptions->GetQueueDir(), "queue");
|
||||
fileName[1024-1] = '\0';
|
||||
|
||||
FILE* infile = fopen(fileName, "rb");
|
||||
FILE* infile = fopen(fileName, "r");
|
||||
|
||||
if (!infile)
|
||||
{
|
||||
@@ -872,8 +491,7 @@ bool DiskState::DiscardDownloadQueue()
|
||||
bool res = false;
|
||||
char FileSignatur[128];
|
||||
fgets(FileSignatur, sizeof(FileSignatur), infile);
|
||||
int iFormatVersion = ParseFormatVersion(FileSignatur);
|
||||
if (3 <= iFormatVersion && iFormatVersion <= 12)
|
||||
if (!strcmp(FileSignatur, FORMATVERSION_SIGNATURE))
|
||||
{
|
||||
// skip nzb-infos
|
||||
int size = 0;
|
||||
@@ -881,71 +499,17 @@ bool DiskState::DiscardDownloadQueue()
|
||||
fscanf(infile, "%i\n", &size);
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
if (!fgets(buf, sizeof(buf), infile)) break; // filename
|
||||
if (!fgets(buf, sizeof(buf), infile)) break; // destdir
|
||||
if (iFormatVersion >= 5)
|
||||
{
|
||||
if (!fgets(buf, sizeof(buf), infile)) break; // localfile
|
||||
}
|
||||
if (iFormatVersion >= 4)
|
||||
{
|
||||
if (!fgets(buf, sizeof(buf), infile)) break; // category
|
||||
if (!fgets(buf, sizeof(buf), infile)) break; // postprocess
|
||||
}
|
||||
if (iFormatVersion >= 8)
|
||||
{
|
||||
if (!fgets(buf, sizeof(buf), infile)) break; // ParStatus
|
||||
}
|
||||
if (iFormatVersion >= 9)
|
||||
{
|
||||
if (!fgets(buf, sizeof(buf), infile)) break; // ScriptStatus
|
||||
}
|
||||
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 (!fgets(buf, sizeof(buf), infile)) break;
|
||||
if (!fgets(buf, sizeof(buf), infile)) break;
|
||||
if (!fgets(buf, sizeof(buf), infile)) break;
|
||||
if (!fgets(buf, sizeof(buf), infile)) break;
|
||||
}
|
||||
|
||||
// file-infos
|
||||
fscanf(infile, "%i\n", &size);
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
int id;
|
||||
char tr[100];
|
||||
if (fscanf(infile, "%i,%s\n", &id, &tr) == 2)
|
||||
int id, group, paused;
|
||||
if (fscanf(infile, "%i,%i,%i\n", &id, &group, &paused) == 3)
|
||||
{
|
||||
char fileName[1024];
|
||||
snprintf(fileName, 1024, "%s%i", g_pOptions->GetQueueDir(), id);
|
||||
@@ -957,7 +521,7 @@ bool DiskState::DiscardDownloadQueue()
|
||||
}
|
||||
else
|
||||
{
|
||||
error("Could not discard diskstate due to file version mismatch");
|
||||
error("Could not discard diskstate due file version mismatch");
|
||||
res = false;
|
||||
}
|
||||
|
||||
@@ -970,6 +534,27 @@ bool DiskState::DiscardDownloadQueue()
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete all files from Queue.
|
||||
* Returns true if successful, false if not
|
||||
*/
|
||||
bool DiskState::DiscardPostQueue()
|
||||
{
|
||||
debug("Discarding post-queue");
|
||||
|
||||
char fileName[1024];
|
||||
|
||||
snprintf(fileName, 1024, "%s%s", g_pOptions->GetQueueDir(), "postq");
|
||||
fileName[1024-1] = '\0';
|
||||
remove(fileName);
|
||||
|
||||
snprintf(fileName, 1024, "%s%s", g_pOptions->GetQueueDir(), "postc");
|
||||
fileName[1024-1] = '\0';
|
||||
remove(fileName);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DiskState::DownloadQueueExists()
|
||||
{
|
||||
debug("Checking if a saved queue exists on disk");
|
||||
@@ -980,7 +565,17 @@ bool DiskState::DownloadQueueExists()
|
||||
return Util::FileExists(fileName);
|
||||
}
|
||||
|
||||
bool DiskState::DiscardFile(FileInfo* pFileInfo)
|
||||
bool DiskState::PostQueueExists(bool bCompleted)
|
||||
{
|
||||
debug("Checking if a saved queue exists on disk");
|
||||
|
||||
char fileName[1024];
|
||||
snprintf(fileName, 1024, "%s%s", g_pOptions->GetQueueDir(), bCompleted ? "postc" : "postq");
|
||||
fileName[1024-1] = '\0';
|
||||
return Util::FileExists(fileName);
|
||||
}
|
||||
|
||||
bool DiskState::DiscardFile(DownloadQueue* pDownloadQueue, FileInfo* pFileInfo)
|
||||
{
|
||||
// delete diskstate-file for file-info
|
||||
char fileName[1024];
|
||||
@@ -988,15 +583,15 @@ bool DiskState::DiscardFile(FileInfo* pFileInfo)
|
||||
fileName[1024-1] = '\0';
|
||||
remove(fileName);
|
||||
|
||||
return true;
|
||||
return !pDownloadQueue || SaveDownloadQueue(pDownloadQueue);
|
||||
}
|
||||
|
||||
void DiskState::CleanupTempDir(DownloadQueue* pDownloadQueue)
|
||||
{
|
||||
// build array of IDs of files in queue for faster access
|
||||
int* ids = (int*)malloc(sizeof(int) * (pDownloadQueue->GetFileQueue()->size() + 1));
|
||||
int* ids = (int*)malloc(sizeof(int) * (pDownloadQueue->size() + 1));
|
||||
int* ptr = ids;
|
||||
for (FileQueue::iterator it = pDownloadQueue->GetFileQueue()->begin(); it != pDownloadQueue->GetFileQueue()->end(); it++)
|
||||
for (DownloadQueue::iterator it = pDownloadQueue->begin(); it != pDownloadQueue->end(); it++)
|
||||
{
|
||||
FileInfo* pFileInfo = *it;
|
||||
*ptr++ = pFileInfo->GetID();
|
||||
@@ -1009,13 +604,12 @@ void DiskState::CleanupTempDir(DownloadQueue* pDownloadQueue)
|
||||
{
|
||||
int id, part;
|
||||
bool del = strstr(filename, ".tmp") || strstr(filename, ".dec") ||
|
||||
((strstr(filename, ".out") && (sscanf(filename, "%i.out", &id) == 1) &&
|
||||
!(g_pOptions->GetContinuePartial() && g_pOptions->GetDirectWrite())) ||
|
||||
((sscanf(filename, "%i.%i", &id, &part) == 2) && !g_pOptions->GetContinuePartial()));
|
||||
((sscanf(filename, "%i.out", &id) == 1) &&
|
||||
!(g_pOptions->GetContinuePartial() && g_pOptions->GetDirectWrite()));
|
||||
if (!del)
|
||||
{
|
||||
if ((sscanf(filename, "%i.%i", &id, &part) == 2) ||
|
||||
(strstr(filename, ".out") && (sscanf(filename, "%i.out", &id) == 1)))
|
||||
(sscanf(filename, "%i.out", &id) == 1))
|
||||
{
|
||||
del = true;
|
||||
ptr = ids;
|
||||
|
||||
21
DiskState.h
21
DiskState.h
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2007-2009 Andrei Prygounkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2007 Andrei Prygounkov <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,24 +27,14 @@
|
||||
#define DISKSTATE_H
|
||||
|
||||
#include "DownloadInfo.h"
|
||||
#include "PostInfo.h"
|
||||
|
||||
class DiskState
|
||||
{
|
||||
private:
|
||||
int ParseFormatVersion(const char* szFormatSignature);
|
||||
bool SaveFileInfo(FileInfo* pFileInfo, const char* szFilename);
|
||||
bool LoadFileInfo(FileInfo* pFileInfo, const char* szFilename, bool bFileSummary, bool bArticles);
|
||||
void SaveNZBList(DownloadQueue* pDownloadQueue, FILE* outfile);
|
||||
bool LoadNZBList(DownloadQueue* pDownloadQueue, FILE* infile, int iFormatVersion);
|
||||
void SaveFileQueue(DownloadQueue* pDownloadQueue, FileQueue* pFileQueue, FILE* outfile);
|
||||
bool LoadFileQueue(DownloadQueue* pDownloadQueue, FileQueue* pFileQueue, FILE* infile, int iFormatVersion);
|
||||
void SavePostQueue(DownloadQueue* pDownloadQueue, FILE* outfile);
|
||||
bool LoadPostQueue(DownloadQueue* pDownloadQueue, FILE* infile);
|
||||
bool LoadOldPostQueue(DownloadQueue* pDownloadQueue);
|
||||
void SaveHistory(DownloadQueue* pDownloadQueue, FILE* outfile);
|
||||
bool LoadHistory(DownloadQueue* pDownloadQueue, FILE* infile);
|
||||
int FindNZBInfoIndex(DownloadQueue* pDownloadQueue, NZBInfo* pNZBInfo);
|
||||
|
||||
|
||||
public:
|
||||
bool DownloadQueueExists();
|
||||
bool PostQueueExists(bool bCompleted);
|
||||
@@ -52,8 +42,11 @@ public:
|
||||
bool LoadDownloadQueue(DownloadQueue* pDownloadQueue);
|
||||
bool SaveFile(FileInfo* pFileInfo);
|
||||
bool LoadArticles(FileInfo* pFileInfo);
|
||||
bool SavePostQueue(PostQueue* pPostQueue, bool bCompleted);
|
||||
bool LoadPostQueue(PostQueue* pPostQueue, bool bCompleted);
|
||||
bool DiscardDownloadQueue();
|
||||
bool DiscardFile(FileInfo* pFileInfo);
|
||||
bool DiscardPostQueue();
|
||||
bool DiscardFile(DownloadQueue* pDownloadQueue, FileInfo* pFileInfo);
|
||||
void CleanupTempDir(DownloadQueue* pDownloadQueue);
|
||||
};
|
||||
|
||||
|
||||
408
DownloadInfo.cpp
408
DownloadInfo.cpp
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007-2010 Andrei Prygounkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007 Andrei Prygounkov <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
|
||||
@@ -40,79 +40,10 @@
|
||||
|
||||
#include "nzbget.h"
|
||||
#include "DownloadInfo.h"
|
||||
#include "Options.h"
|
||||
#include "Log.h"
|
||||
#include "Util.h"
|
||||
|
||||
extern Options* g_pOptions;
|
||||
|
||||
int FileInfo::m_iIDGen = 0;
|
||||
int NZBInfo::m_iIDGen = 0;
|
||||
int PostInfo::m_iIDGen = 0;
|
||||
|
||||
NZBParameter::NZBParameter(const char* szName)
|
||||
{
|
||||
m_szName = strdup(szName);
|
||||
m_szValue = NULL;
|
||||
}
|
||||
|
||||
NZBParameter::~NZBParameter()
|
||||
{
|
||||
if (m_szName)
|
||||
{
|
||||
free(m_szName);
|
||||
}
|
||||
if (m_szValue)
|
||||
{
|
||||
free(m_szValue);
|
||||
}
|
||||
}
|
||||
|
||||
void NZBParameter::SetValue(const char* szValue)
|
||||
{
|
||||
if (m_szValue)
|
||||
{
|
||||
free(m_szValue);
|
||||
}
|
||||
m_szValue = strdup(szValue);
|
||||
}
|
||||
|
||||
|
||||
void NZBParameterList::SetParameter(const char* szName, const char* szValue)
|
||||
{
|
||||
NZBParameter* pParameter = NULL;
|
||||
bool bDelete = !szValue || !*szValue;
|
||||
|
||||
for (iterator it = begin(); it != end(); it++)
|
||||
{
|
||||
NZBParameter* pLookupParameter = *it;
|
||||
if (!strcmp(pLookupParameter->GetName(), szName))
|
||||
{
|
||||
if (bDelete)
|
||||
{
|
||||
delete pLookupParameter;
|
||||
erase(it);
|
||||
return;
|
||||
}
|
||||
pParameter = pLookupParameter;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bDelete)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!pParameter)
|
||||
{
|
||||
pParameter = new NZBParameter(szName);
|
||||
push_back(pParameter);
|
||||
}
|
||||
|
||||
pParameter->SetValue(szValue);
|
||||
}
|
||||
|
||||
|
||||
NZBInfo::NZBInfo()
|
||||
{
|
||||
@@ -120,24 +51,9 @@ NZBInfo::NZBInfo()
|
||||
|
||||
m_szFilename = NULL;
|
||||
m_szDestDir = NULL;
|
||||
m_szCategory = strdup("");
|
||||
m_iFileCount = 0;
|
||||
m_iParkedFileCount = 0;
|
||||
m_lSize = 0;
|
||||
m_iRefCount = 0;
|
||||
m_bPostProcess = false;
|
||||
m_eParStatus = prNone;
|
||||
m_eScriptStatus = srNone;
|
||||
m_bDeleted = false;
|
||||
m_bParCleanup = false;
|
||||
m_bCleanupDisk = false;
|
||||
m_szQueuedFilename = strdup("");
|
||||
m_tHistoryTime = 0;
|
||||
m_Owner = NULL;
|
||||
m_Messages.clear();
|
||||
m_iIDMessageGen = 0;
|
||||
m_iIDGen++;
|
||||
m_iID = m_iIDGen;
|
||||
}
|
||||
|
||||
NZBInfo::~NZBInfo()
|
||||
@@ -152,33 +68,6 @@ NZBInfo::~NZBInfo()
|
||||
{
|
||||
free(m_szDestDir);
|
||||
}
|
||||
if (m_szCategory)
|
||||
{
|
||||
free(m_szCategory);
|
||||
}
|
||||
if (m_szQueuedFilename)
|
||||
{
|
||||
free(m_szQueuedFilename);
|
||||
}
|
||||
|
||||
ClearCompletedFiles();
|
||||
|
||||
for (NZBParameterList::iterator it = m_ppParameters.begin(); it != m_ppParameters.end(); it++)
|
||||
{
|
||||
delete *it;
|
||||
}
|
||||
m_ppParameters.clear();
|
||||
|
||||
for (Messages::iterator it = m_Messages.begin(); it != m_Messages.end(); it++)
|
||||
{
|
||||
delete *it;
|
||||
}
|
||||
m_Messages.clear();
|
||||
|
||||
if (m_Owner)
|
||||
{
|
||||
m_Owner->Remove(this);
|
||||
}
|
||||
}
|
||||
|
||||
void NZBInfo::AddReference()
|
||||
@@ -195,51 +84,16 @@ void NZBInfo::Release()
|
||||
}
|
||||
}
|
||||
|
||||
void NZBInfo::ClearCompletedFiles()
|
||||
{
|
||||
for (Files::iterator it = m_completedFiles.begin(); it != m_completedFiles.end(); it++)
|
||||
{
|
||||
free(*it);
|
||||
}
|
||||
m_completedFiles.clear();
|
||||
}
|
||||
|
||||
void NZBInfo::SetDestDir(const char* szDestDir)
|
||||
{
|
||||
if (m_szDestDir)
|
||||
{
|
||||
free(m_szDestDir);
|
||||
}
|
||||
m_szDestDir = strdup(szDestDir);
|
||||
}
|
||||
|
||||
void NZBInfo::SetFilename(const char * szFilename)
|
||||
{
|
||||
if (m_szFilename)
|
||||
{
|
||||
free(m_szFilename);
|
||||
}
|
||||
m_szFilename = strdup(szFilename);
|
||||
}
|
||||
|
||||
void NZBInfo::SetCategory(const char* szCategory)
|
||||
{
|
||||
if (m_szCategory)
|
||||
{
|
||||
free(m_szCategory);
|
||||
}
|
||||
m_szCategory = strdup(szCategory);
|
||||
}
|
||||
|
||||
void NZBInfo::SetQueuedFilename(const char * szQueuedFilename)
|
||||
{
|
||||
if (m_szQueuedFilename)
|
||||
{
|
||||
free(m_szQueuedFilename);
|
||||
}
|
||||
m_szQueuedFilename = strdup(szQueuedFilename);
|
||||
}
|
||||
|
||||
void NZBInfo::GetNiceNZBName(char* szBuffer, int iSize)
|
||||
{
|
||||
MakeNiceNZBName(m_szFilename, szBuffer, iSize);
|
||||
@@ -265,7 +119,7 @@ void NZBInfo::MakeNiceNZBName(const char * szNZBFilename, char * szBuffer, int i
|
||||
// wipe out ".nzb"
|
||||
if (char* p = strrchr(postname, '.')) *p = '\0';
|
||||
|
||||
Util::MakeValidFilename(postname, '_', false);
|
||||
Util::MakeValidFilename(postname, '_');
|
||||
|
||||
// if the resulting name is empty, use basename without cleaning up "msgid_"
|
||||
if (strlen(postname) == 0)
|
||||
@@ -277,7 +131,7 @@ void NZBInfo::MakeNiceNZBName(const char * szNZBFilename, char * szBuffer, int i
|
||||
// wipe out ".nzb"
|
||||
if (char* p = strrchr(postname, '.')) *p = '\0';
|
||||
|
||||
Util::MakeValidFilename(postname, '_', false);
|
||||
Util::MakeValidFilename(postname, '_');
|
||||
|
||||
// if the resulting name is STILL empty, use "noname"
|
||||
if (strlen(postname) == 0)
|
||||
@@ -290,117 +144,6 @@ void NZBInfo::MakeNiceNZBName(const char * szNZBFilename, char * szBuffer, int i
|
||||
szBuffer[iSize-1] = '\0';
|
||||
}
|
||||
|
||||
void NZBInfo::BuildDestDirName()
|
||||
{
|
||||
char szBuffer[1024];
|
||||
char szCategory[1024];
|
||||
bool bHasCategory = m_szCategory && m_szCategory[0] != '\0';
|
||||
if (g_pOptions->GetAppendCategoryDir() && bHasCategory)
|
||||
{
|
||||
strncpy(szCategory, m_szCategory, 1024);
|
||||
szCategory[1024 - 1] = '\0';
|
||||
Util::MakeValidFilename(szCategory, '_', true);
|
||||
}
|
||||
|
||||
if (g_pOptions->GetAppendNZBDir())
|
||||
{
|
||||
char szNiceNZBName[1024];
|
||||
GetNiceNZBName(szNiceNZBName, 1024);
|
||||
if (g_pOptions->GetAppendCategoryDir() && bHasCategory)
|
||||
{
|
||||
snprintf(szBuffer, 1024, "%s%s%c%s", g_pOptions->GetDestDir(), szCategory, PATH_SEPARATOR, szNiceNZBName);
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(szBuffer, 1024, "%s%s", g_pOptions->GetDestDir(), szNiceNZBName);
|
||||
}
|
||||
szBuffer[1024-1] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
if (g_pOptions->GetAppendCategoryDir() && bHasCategory)
|
||||
{
|
||||
snprintf(szBuffer, 1024, "%s%s", g_pOptions->GetDestDir(), szCategory);
|
||||
}
|
||||
else
|
||||
{
|
||||
strncpy(szBuffer, g_pOptions->GetDestDir(), 1024);
|
||||
}
|
||||
szBuffer[1024-1] = '\0'; // trim the last slash, always returned by GetDestDir()
|
||||
}
|
||||
|
||||
SetDestDir(szBuffer);
|
||||
}
|
||||
|
||||
void NZBInfo::SetParameter(const char* szName, const char* szValue)
|
||||
{
|
||||
m_ppParameters.SetParameter(szName, szValue);
|
||||
}
|
||||
|
||||
NZBInfo::Messages* NZBInfo::LockMessages()
|
||||
{
|
||||
m_mutexLog.Lock();
|
||||
return &m_Messages;
|
||||
}
|
||||
|
||||
void NZBInfo::UnlockMessages()
|
||||
{
|
||||
m_mutexLog.Unlock();
|
||||
}
|
||||
|
||||
void NZBInfo::AppendMessage(Message::EKind eKind, time_t tTime, const char * szText)
|
||||
{
|
||||
if (tTime == 0)
|
||||
{
|
||||
tTime = time(NULL);
|
||||
}
|
||||
|
||||
Message* pMessage = new Message(++m_iIDMessageGen, eKind, tTime, szText);
|
||||
|
||||
m_mutexLog.Lock();
|
||||
m_Messages.push_back(pMessage);
|
||||
m_mutexLog.Unlock();
|
||||
}
|
||||
|
||||
void NZBInfoList::Add(NZBInfo* pNZBInfo)
|
||||
{
|
||||
pNZBInfo->m_Owner = this;
|
||||
push_back(pNZBInfo);
|
||||
}
|
||||
|
||||
void NZBInfoList::Remove(NZBInfo* pNZBInfo)
|
||||
{
|
||||
for (iterator it = begin(); it != end(); it++)
|
||||
{
|
||||
NZBInfo* pNZBInfo2 = *it;
|
||||
if (pNZBInfo2 == pNZBInfo)
|
||||
{
|
||||
erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NZBInfoList::ReleaseAll()
|
||||
{
|
||||
int i = 0;
|
||||
for (iterator it = begin(); it != end(); )
|
||||
{
|
||||
NZBInfo* pNZBInfo = *it;
|
||||
bool bObjDeleted = pNZBInfo->m_iRefCount == 1;
|
||||
pNZBInfo->Release();
|
||||
if (bObjDeleted)
|
||||
{
|
||||
it = begin() + i;
|
||||
}
|
||||
else
|
||||
{
|
||||
it++;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ArticleInfo::ArticleInfo()
|
||||
{
|
||||
//debug("Creating ArticleInfo");
|
||||
@@ -431,10 +174,6 @@ void ArticleInfo::SetMessageID(const char * szMessageID)
|
||||
|
||||
void ArticleInfo::SetResultFilename(const char * v)
|
||||
{
|
||||
if (m_szResultFilename)
|
||||
{
|
||||
free(m_szResultFilename);
|
||||
}
|
||||
m_szResultFilename = strdup(v);
|
||||
}
|
||||
|
||||
@@ -450,7 +189,6 @@ FileInfo::FileInfo()
|
||||
m_bFilenameConfirmed = false;
|
||||
m_lSize = 0;
|
||||
m_lRemainingSize = 0;
|
||||
m_tTime = 0;
|
||||
m_bPaused = false;
|
||||
m_bDeleted = false;
|
||||
m_iCompleted = 0;
|
||||
@@ -507,10 +245,6 @@ void FileInfo::SetID(int s)
|
||||
|
||||
void FileInfo::SetNZBInfo(NZBInfo* pNZBInfo)
|
||||
{
|
||||
if (m_pNZBInfo)
|
||||
{
|
||||
m_pNZBInfo->Release();
|
||||
}
|
||||
m_pNZBInfo = pNZBInfo;
|
||||
m_pNZBInfo->AddReference();
|
||||
}
|
||||
@@ -531,7 +265,7 @@ void FileInfo::SetFilename(const char* szFilename)
|
||||
|
||||
void FileInfo::MakeValidFilename()
|
||||
{
|
||||
Util::MakeValidFilename(m_szFilename, '_', false);
|
||||
Util::MakeValidFilename(m_szFilename, '_');
|
||||
}
|
||||
|
||||
void FileInfo::LockOutputFile()
|
||||
@@ -568,12 +302,9 @@ GroupInfo::GroupInfo()
|
||||
m_iFirstID = 0;
|
||||
m_iLastID = 0;
|
||||
m_iRemainingFileCount = 0;
|
||||
m_iPausedFileCount = 0;
|
||||
m_lRemainingSize = 0;
|
||||
m_lPausedSize = 0;
|
||||
m_iRemainingParCount = 0;
|
||||
m_tMinTime = 0;
|
||||
m_tMaxTime = 0;
|
||||
}
|
||||
|
||||
GroupInfo::~GroupInfo()
|
||||
@@ -584,120 +315,9 @@ GroupInfo::~GroupInfo()
|
||||
}
|
||||
}
|
||||
|
||||
PostInfo::PostInfo()
|
||||
void GroupInfo::BuildGroups(DownloadQueue* pDownloadQueue, GroupQueue* pGroupQueue)
|
||||
{
|
||||
debug("Creating PostInfo");
|
||||
|
||||
m_pNZBInfo = NULL;
|
||||
m_szParFilename = NULL;
|
||||
m_szInfoName = NULL;
|
||||
m_bWorking = false;
|
||||
m_bDeleted = false;
|
||||
m_bParCheck = false;
|
||||
m_eParStatus = psNone;
|
||||
m_eRequestParCheck = rpNone;
|
||||
m_eScriptStatus = srNone;
|
||||
m_szProgressLabel = strdup("");
|
||||
m_iFileProgress = 0;
|
||||
m_iStageProgress = 0;
|
||||
m_tStartTime = 0;
|
||||
m_tStageTime = 0;
|
||||
m_eStage = ptQueued;
|
||||
m_pScriptThread = NULL;
|
||||
m_Messages.clear();
|
||||
m_iIDMessageGen = 0;
|
||||
m_iIDGen++;
|
||||
m_iID = m_iIDGen;
|
||||
}
|
||||
|
||||
PostInfo::~ PostInfo()
|
||||
{
|
||||
debug("Destroying PostInfo");
|
||||
|
||||
if (m_szParFilename)
|
||||
{
|
||||
free(m_szParFilename);
|
||||
}
|
||||
if (m_szInfoName)
|
||||
{
|
||||
free(m_szInfoName);
|
||||
}
|
||||
if (m_szProgressLabel)
|
||||
{
|
||||
free(m_szProgressLabel);
|
||||
}
|
||||
|
||||
for (Messages::iterator it = m_Messages.begin(); it != m_Messages.end(); it++)
|
||||
{
|
||||
delete *it;
|
||||
}
|
||||
m_Messages.clear();
|
||||
|
||||
if (m_pNZBInfo)
|
||||
{
|
||||
m_pNZBInfo->Release();
|
||||
}
|
||||
}
|
||||
|
||||
void PostInfo::SetNZBInfo(NZBInfo* pNZBInfo)
|
||||
{
|
||||
if (m_pNZBInfo)
|
||||
{
|
||||
m_pNZBInfo->Release();
|
||||
}
|
||||
m_pNZBInfo = pNZBInfo;
|
||||
m_pNZBInfo->AddReference();
|
||||
}
|
||||
|
||||
void PostInfo::SetParFilename(const char* szParFilename)
|
||||
{
|
||||
m_szParFilename = strdup(szParFilename);
|
||||
}
|
||||
|
||||
void PostInfo::SetInfoName(const char* szInfoName)
|
||||
{
|
||||
m_szInfoName = strdup(szInfoName);
|
||||
}
|
||||
|
||||
void PostInfo::SetProgressLabel(const char* szProgressLabel)
|
||||
{
|
||||
if (m_szProgressLabel)
|
||||
{
|
||||
free(m_szProgressLabel);
|
||||
}
|
||||
m_szProgressLabel = strdup(szProgressLabel);
|
||||
}
|
||||
|
||||
PostInfo::Messages* PostInfo::LockMessages()
|
||||
{
|
||||
m_mutexLog.Lock();
|
||||
return &m_Messages;
|
||||
}
|
||||
|
||||
void PostInfo::UnlockMessages()
|
||||
{
|
||||
m_mutexLog.Unlock();
|
||||
}
|
||||
|
||||
void PostInfo::AppendMessage(Message::EKind eKind, const char * szText)
|
||||
{
|
||||
Message* pMessage = new Message(++m_iIDMessageGen, eKind, time(NULL), szText);
|
||||
|
||||
m_mutexLog.Lock();
|
||||
m_Messages.push_back(pMessage);
|
||||
|
||||
while (m_Messages.size() > (unsigned int)g_pOptions->GetLogBufferSize())
|
||||
{
|
||||
Message* pMessage = m_Messages.front();
|
||||
delete pMessage;
|
||||
m_Messages.pop_front();
|
||||
}
|
||||
m_mutexLog.Unlock();
|
||||
}
|
||||
|
||||
void DownloadQueue::BuildGroups(GroupQueue* pGroupQueue)
|
||||
{
|
||||
for (FileQueue::iterator it = GetFileQueue()->begin(); it != GetFileQueue()->end(); it++)
|
||||
for (DownloadQueue::iterator it = pDownloadQueue->begin(); it != pDownloadQueue->end(); it++)
|
||||
{
|
||||
FileInfo* pFileInfo = *it;
|
||||
GroupInfo* pGroupInfo = NULL;
|
||||
@@ -717,8 +337,6 @@ void DownloadQueue::BuildGroups(GroupQueue* pGroupQueue)
|
||||
pGroupInfo->m_pNZBInfo->AddReference();
|
||||
pGroupInfo->m_iFirstID = pFileInfo->GetID();
|
||||
pGroupInfo->m_iLastID = pFileInfo->GetID();
|
||||
pGroupInfo->m_tMinTime = pFileInfo->GetTime();
|
||||
pGroupInfo->m_tMaxTime = pFileInfo->GetTime();
|
||||
pGroupQueue->push_back(pGroupInfo);
|
||||
}
|
||||
if (pFileInfo->GetID() < pGroupInfo->GetFirstID())
|
||||
@@ -729,23 +347,11 @@ void DownloadQueue::BuildGroups(GroupQueue* pGroupQueue)
|
||||
{
|
||||
pGroupInfo->m_iLastID = pFileInfo->GetID();
|
||||
}
|
||||
if (pFileInfo->GetTime() > 0)
|
||||
{
|
||||
if (pFileInfo->GetTime() < pGroupInfo->GetMinTime())
|
||||
{
|
||||
pGroupInfo->m_tMinTime = pFileInfo->GetTime();
|
||||
}
|
||||
if (pFileInfo->GetTime() > pGroupInfo->GetMaxTime())
|
||||
{
|
||||
pGroupInfo->m_tMaxTime = pFileInfo->GetTime();
|
||||
}
|
||||
}
|
||||
pGroupInfo->m_iRemainingFileCount++;
|
||||
pGroupInfo->m_lRemainingSize += pFileInfo->GetRemainingSize();
|
||||
if (pFileInfo->GetPaused())
|
||||
{
|
||||
pGroupInfo->m_lPausedSize += pFileInfo->GetRemainingSize();
|
||||
pGroupInfo->m_iPausedFileCount++;
|
||||
}
|
||||
|
||||
char szLoFileName[1024];
|
||||
|
||||
321
DownloadInfo.h
321
DownloadInfo.h
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007-2010 Andrei Prygounkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007 Andrei Prygounkov <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,13 +29,34 @@
|
||||
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <time.h>
|
||||
|
||||
#include "Log.h"
|
||||
#include "Thread.h"
|
||||
|
||||
class NZBInfo;
|
||||
class DownloadQueue;
|
||||
class NZBInfo
|
||||
{
|
||||
private:
|
||||
int m_iRefCount;
|
||||
char* m_szFilename;
|
||||
char* m_szDestDir;
|
||||
int m_iFileCount;
|
||||
long long m_lSize;
|
||||
|
||||
public:
|
||||
NZBInfo();
|
||||
~NZBInfo();
|
||||
void AddReference();
|
||||
void Release();
|
||||
const char* GetFilename() { return m_szFilename; }
|
||||
void SetFilename(const char* szFilename);
|
||||
void GetNiceNZBName(char* szBuffer, int iSize);
|
||||
static void MakeNiceNZBName(const char* szNZBFilename, char* szBuffer, int iSize);
|
||||
const char* GetDestDir() { return m_szDestDir; }
|
||||
void SetDestDir(const char* szDestDir);
|
||||
long long GetSize() { return m_lSize; }
|
||||
void SetSize(long long s) { m_lSize = s; }
|
||||
int GetFileCount() { return m_iFileCount; }
|
||||
void SetFileCount(int s) { m_iFileCount = s; }
|
||||
};
|
||||
|
||||
class ArticleInfo
|
||||
{
|
||||
@@ -85,7 +106,6 @@ private:
|
||||
char* m_szFilename;
|
||||
long long m_lSize;
|
||||
long long m_lRemainingSize;
|
||||
time_t m_tTime;
|
||||
bool m_bPaused;
|
||||
bool m_bDeleted;
|
||||
bool m_bFilenameConfirmed;
|
||||
@@ -115,8 +135,6 @@ public:
|
||||
long long GetSize() { return m_lSize; }
|
||||
long long GetRemainingSize() { return m_lRemainingSize; }
|
||||
void SetRemainingSize(long long s) { m_lRemainingSize = s; }
|
||||
time_t GetTime() { return m_tTime; }
|
||||
void SetTime(time_t tTime) { m_tTime = tTime; }
|
||||
bool GetPaused() { return m_bPaused; }
|
||||
void SetPaused(bool Paused) { m_bPaused = Paused; }
|
||||
bool GetDeleted() { return m_bDeleted; }
|
||||
@@ -131,7 +149,10 @@ public:
|
||||
bool IsDupe(const char* szFilename);
|
||||
};
|
||||
|
||||
typedef std::deque<FileInfo*> FileQueue;
|
||||
typedef std::deque<FileInfo*> DownloadQueue;
|
||||
|
||||
class GroupInfo;
|
||||
typedef std::deque<GroupInfo*> GroupQueue;
|
||||
|
||||
class GroupInfo
|
||||
{
|
||||
@@ -140,14 +161,9 @@ private:
|
||||
int m_iFirstID;
|
||||
int m_iLastID;
|
||||
int m_iRemainingFileCount;
|
||||
int m_iPausedFileCount;
|
||||
long long m_lRemainingSize;
|
||||
long long m_lPausedSize;
|
||||
int m_iRemainingParCount;
|
||||
time_t m_tMinTime;
|
||||
time_t m_tMaxTime;
|
||||
|
||||
friend class DownloadQueue;
|
||||
|
||||
public:
|
||||
GroupInfo();
|
||||
@@ -158,282 +174,9 @@ public:
|
||||
long long GetRemainingSize() { return m_lRemainingSize; }
|
||||
long long GetPausedSize() { return m_lPausedSize; }
|
||||
int GetRemainingFileCount() { return m_iRemainingFileCount; }
|
||||
int GetPausedFileCount() { return m_iPausedFileCount; }
|
||||
int GetRemainingParCount() { return m_iRemainingParCount; }
|
||||
time_t GetMinTime() { return m_tMinTime; }
|
||||
time_t GetMaxTime() { return m_tMaxTime; }
|
||||
};
|
||||
|
||||
typedef std::deque<GroupInfo*> GroupQueue;
|
||||
|
||||
class NZBParameter
|
||||
{
|
||||
private:
|
||||
char* m_szName;
|
||||
char* m_szValue;
|
||||
|
||||
void SetValue(const char* szValue);
|
||||
|
||||
friend class NZBParameterList;
|
||||
|
||||
public:
|
||||
NZBParameter(const char* szName);
|
||||
~NZBParameter();
|
||||
const char* GetName() { return m_szName; }
|
||||
const char* GetValue() { return m_szValue; }
|
||||
};
|
||||
|
||||
typedef std::deque<NZBParameter*> NZBParameterListBase;
|
||||
|
||||
class NZBParameterList : public NZBParameterListBase
|
||||
{
|
||||
public:
|
||||
void SetParameter(const char* szName, const char* szValue);
|
||||
};
|
||||
|
||||
class NZBInfoList;
|
||||
|
||||
class NZBInfo
|
||||
{
|
||||
public:
|
||||
enum EParStatus
|
||||
{
|
||||
prNone,
|
||||
prFailure,
|
||||
prRepairPossible,
|
||||
prSuccess
|
||||
};
|
||||
|
||||
enum EScriptStatus
|
||||
{
|
||||
srNone,
|
||||
srUnknown,
|
||||
srFailure,
|
||||
srSuccess
|
||||
};
|
||||
|
||||
typedef std::vector<char*> Files;
|
||||
typedef std::deque<Message*> Messages;
|
||||
|
||||
private:
|
||||
int m_iID;
|
||||
int m_iRefCount;
|
||||
char* m_szFilename;
|
||||
char* m_szDestDir;
|
||||
char* m_szCategory;
|
||||
int m_iFileCount;
|
||||
int m_iParkedFileCount;
|
||||
long long m_lSize;
|
||||
Files m_completedFiles;
|
||||
bool m_bPostProcess;
|
||||
EParStatus m_eParStatus;
|
||||
EScriptStatus m_eScriptStatus;
|
||||
char* m_szQueuedFilename;
|
||||
bool m_bDeleted;
|
||||
bool m_bParCleanup;
|
||||
bool m_bCleanupDisk;
|
||||
time_t m_tHistoryTime;
|
||||
NZBInfoList* m_Owner;
|
||||
NZBParameterList m_ppParameters;
|
||||
Mutex m_mutexLog;
|
||||
Messages m_Messages;
|
||||
int m_iIDMessageGen;
|
||||
|
||||
static int m_iIDGen;
|
||||
|
||||
friend class NZBInfoList;
|
||||
|
||||
public:
|
||||
NZBInfo();
|
||||
~NZBInfo();
|
||||
void AddReference();
|
||||
void Release();
|
||||
int GetID() { return m_iID; }
|
||||
const char* GetFilename() { return m_szFilename; }
|
||||
void SetFilename(const char* szFilename);
|
||||
void GetNiceNZBName(char* szBuffer, int iSize);
|
||||
static void MakeNiceNZBName(const char* szNZBFilename, char* szBuffer, int iSize);
|
||||
const char* GetDestDir() { return m_szDestDir; } // needs locking (for shared objects)
|
||||
void SetDestDir(const char* szDestDir); // needs locking (for shared objects)
|
||||
const char* GetCategory() { return m_szCategory; } // needs locking (for shared objects)
|
||||
void SetCategory(const char* szCategory); // needs locking (for shared objects)
|
||||
long long GetSize() { return m_lSize; }
|
||||
void SetSize(long long lSize) { m_lSize = lSize; }
|
||||
int GetFileCount() { return m_iFileCount; }
|
||||
void SetFileCount(int iFileCount) { m_iFileCount = iFileCount; }
|
||||
int GetParkedFileCount() { return m_iParkedFileCount; }
|
||||
void SetParkedFileCount(int iParkedFileCount) { m_iParkedFileCount = iParkedFileCount; }
|
||||
void BuildDestDirName();
|
||||
Files* GetCompletedFiles() { return &m_completedFiles; } // needs locking (for shared objects)
|
||||
void ClearCompletedFiles();
|
||||
bool GetPostProcess() { return m_bPostProcess; }
|
||||
void SetPostProcess(bool bPostProcess) { m_bPostProcess = bPostProcess; }
|
||||
EParStatus GetParStatus() { return m_eParStatus; }
|
||||
void SetParStatus(EParStatus eParStatus) { m_eParStatus = eParStatus; }
|
||||
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; }
|
||||
void SetDeleted(bool bDeleted) { m_bDeleted = bDeleted; }
|
||||
bool GetParCleanup() { return m_bParCleanup; }
|
||||
void SetParCleanup(bool bParCleanup) { m_bParCleanup = bParCleanup; }
|
||||
bool GetCleanupDisk() { return m_bCleanupDisk; }
|
||||
void SetCleanupDisk(bool bCleanupDisk) { m_bCleanupDisk = bCleanupDisk; }
|
||||
time_t GetHistoryTime() { return m_tHistoryTime; }
|
||||
void SetHistoryTime(time_t tHistoryTime) { m_tHistoryTime = tHistoryTime; }
|
||||
NZBParameterList* GetParameters() { return &m_ppParameters; } // needs locking (for shared objects)
|
||||
void SetParameter(const char* szName, const char* szValue); // needs locking (for shared objects)
|
||||
void AppendMessage(Message::EKind eKind, time_t tTime, const char* szText);
|
||||
Messages* LockMessages();
|
||||
void UnlockMessages();
|
||||
};
|
||||
|
||||
typedef std::deque<NZBInfo*> NZBInfoListBase;
|
||||
|
||||
class NZBInfoList : public NZBInfoListBase
|
||||
{
|
||||
public:
|
||||
void Add(NZBInfo* pNZBInfo);
|
||||
void Remove(NZBInfo* pNZBInfo);
|
||||
void ReleaseAll();
|
||||
};
|
||||
|
||||
class PostInfo
|
||||
{
|
||||
public:
|
||||
enum EStage
|
||||
{
|
||||
ptQueued,
|
||||
ptLoadingPars,
|
||||
ptVerifyingSources,
|
||||
ptRepairing,
|
||||
ptVerifyingRepaired,
|
||||
ptExecutingScript,
|
||||
ptFinished
|
||||
};
|
||||
|
||||
enum EParStatus
|
||||
{
|
||||
psNone,
|
||||
psFailure,
|
||||
psSuccess,
|
||||
psRepairPossible
|
||||
};
|
||||
|
||||
enum ERequestParCheck
|
||||
{
|
||||
rpNone,
|
||||
rpCurrent,
|
||||
rpAll
|
||||
};
|
||||
|
||||
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_bParCheck;
|
||||
EParStatus m_eParStatus;
|
||||
EScriptStatus m_eScriptStatus;
|
||||
ERequestParCheck m_eRequestParCheck;
|
||||
EStage m_eStage;
|
||||
char* m_szProgressLabel;
|
||||
int m_iFileProgress;
|
||||
int m_iStageProgress;
|
||||
time_t m_tStartTime;
|
||||
time_t m_tStageTime;
|
||||
Thread* m_pScriptThread;
|
||||
|
||||
Mutex m_mutexLog;
|
||||
Messages m_Messages;
|
||||
int m_iIDMessageGen;
|
||||
|
||||
static int m_iIDGen;
|
||||
|
||||
public:
|
||||
PostInfo();
|
||||
~PostInfo();
|
||||
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; }
|
||||
void SetStage(EStage eStage) { m_eStage = eStage; }
|
||||
void SetProgressLabel(const char* szProgressLabel);
|
||||
const char* GetProgressLabel() { return m_szProgressLabel; }
|
||||
int GetFileProgress() { return m_iFileProgress; }
|
||||
void SetFileProgress(int iFileProgress) { m_iFileProgress = iFileProgress; }
|
||||
int GetStageProgress() { return m_iStageProgress; }
|
||||
void SetStageProgress(int iStageProgress) { m_iStageProgress = iStageProgress; }
|
||||
time_t GetStartTime() { return m_tStartTime; }
|
||||
void SetStartTime(time_t tStartTime) { m_tStartTime = tStartTime; }
|
||||
time_t GetStageTime() { return m_tStageTime; }
|
||||
void SetStageTime(time_t tStageTime) { m_tStageTime = tStageTime; }
|
||||
bool GetWorking() { return m_bWorking; }
|
||||
void SetWorking(bool bWorking) { m_bWorking = bWorking; }
|
||||
bool GetDeleted() { return m_bDeleted; }
|
||||
void SetDeleted(bool bDeleted) { m_bDeleted = bDeleted; }
|
||||
bool GetParCheck() { return m_bParCheck; }
|
||||
void SetParCheck(bool bParCheck) { m_bParCheck = bParCheck; }
|
||||
EParStatus GetParStatus() { return m_eParStatus; }
|
||||
void SetParStatus(EParStatus eParStatus) { m_eParStatus = eParStatus; }
|
||||
ERequestParCheck GetRequestParCheck() { return m_eRequestParCheck; }
|
||||
void SetRequestParCheck(ERequestParCheck eRequestParCheck) { m_eRequestParCheck = eRequestParCheck; }
|
||||
EScriptStatus GetScriptStatus() { return m_eScriptStatus; }
|
||||
void SetScriptStatus(EScriptStatus eScriptStatus) { m_eScriptStatus = eScriptStatus; }
|
||||
void AppendMessage(Message::EKind eKind, const char* szText);
|
||||
Thread* GetScriptThread() { return m_pScriptThread; }
|
||||
void SetScriptThread(Thread* pScriptThread) { m_pScriptThread = pScriptThread; }
|
||||
Messages* LockMessages();
|
||||
void UnlockMessages();
|
||||
};
|
||||
|
||||
typedef std::deque<PostInfo*> PostQueue;
|
||||
|
||||
typedef std::vector<int> IDList;
|
||||
|
||||
typedef std::deque<NZBInfo*> HistoryList;
|
||||
|
||||
class DownloadQueue
|
||||
{
|
||||
protected:
|
||||
NZBInfoList m_NZBInfoList;
|
||||
FileQueue m_FileQueue;
|
||||
PostQueue m_PostQueue;
|
||||
HistoryList m_HistoryList;
|
||||
FileQueue m_ParkedFiles;
|
||||
|
||||
public:
|
||||
NZBInfoList* GetNZBInfoList() { return &m_NZBInfoList; }
|
||||
FileQueue* GetFileQueue() { return &m_FileQueue; }
|
||||
PostQueue* GetPostQueue() { return &m_PostQueue; }
|
||||
HistoryList* GetHistoryList() { return &m_HistoryList; }
|
||||
FileQueue* GetParkedFiles() { return &m_ParkedFiles; }
|
||||
void BuildGroups(GroupQueue* pGroupQueue);
|
||||
};
|
||||
|
||||
class DownloadQueueHolder
|
||||
{
|
||||
public:
|
||||
virtual ~DownloadQueueHolder() {};
|
||||
virtual DownloadQueue* LockQueue() = 0;
|
||||
virtual void UnlockQueue() = 0;
|
||||
static void BuildGroups(DownloadQueue* pDownloadQueue, GroupQueue* pGroupQueue);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
110
Frontend.cpp
110
Frontend.cpp
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007-2010 Andrei Prygounkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007 Andrei Prygounkov <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
|
||||
@@ -49,10 +49,12 @@
|
||||
#include "Connection.h"
|
||||
#include "MessageBase.h"
|
||||
#include "QueueCoordinator.h"
|
||||
#include "PrePostProcessor.h"
|
||||
#include "RemoteClient.h"
|
||||
#include "Util.h"
|
||||
|
||||
extern QueueCoordinator* g_pQueueCoordinator;
|
||||
extern PrePostProcessor* g_pPrePostProcessor;
|
||||
extern Options* g_pOptions;
|
||||
|
||||
Frontend::Frontend()
|
||||
@@ -65,8 +67,7 @@ Frontend::Frontend()
|
||||
m_bFileList = false;
|
||||
m_fCurrentDownloadSpeed = 0;
|
||||
m_lRemainingSize = 0;
|
||||
m_bPauseDownload = false;
|
||||
m_bPauseDownload2 = false;
|
||||
m_bPause = false;
|
||||
m_fDownloadLimit = 0;
|
||||
m_iThreadCount = 0;
|
||||
m_iPostJobCount = 0;
|
||||
@@ -74,6 +75,8 @@ Frontend::Frontend()
|
||||
m_iDnTimeSec = 0;
|
||||
m_iAllBytes = 0;
|
||||
m_bStandBy = 0;
|
||||
m_RemoteMessages.clear();
|
||||
m_RemoteQueue.clear();
|
||||
m_iUpdateInterval = g_pOptions->GetUpdateInterval();
|
||||
}
|
||||
|
||||
@@ -98,13 +101,12 @@ bool Frontend::PrepareData()
|
||||
{
|
||||
m_fCurrentDownloadSpeed = g_pQueueCoordinator->CalcCurrentDownloadSpeed();
|
||||
m_lRemainingSize = g_pQueueCoordinator->CalcRemainingSize();
|
||||
m_bPauseDownload = g_pOptions->GetPauseDownload();
|
||||
m_bPauseDownload2 = g_pOptions->GetPauseDownload2();
|
||||
m_bPause = g_pOptions->GetPause();
|
||||
m_fDownloadLimit = g_pOptions->GetDownloadRate();
|
||||
m_iThreadCount = Thread::GetThreadCount();
|
||||
PostQueue* pPostQueue = g_pQueueCoordinator->LockQueue()->GetPostQueue();
|
||||
PostQueue* pPostQueue = g_pPrePostProcessor->LockPostQueue();
|
||||
m_iPostJobCount = pPostQueue->size();
|
||||
g_pQueueCoordinator->UnlockQueue();
|
||||
g_pPrePostProcessor->UnlockPostQueue();
|
||||
g_pQueueCoordinator->CalcStat(&m_iUpTimeSec, &m_iDnTimeSec, &m_iAllBytes, &m_bStandBy);
|
||||
}
|
||||
}
|
||||
@@ -121,11 +123,11 @@ void Frontend::FreeData()
|
||||
}
|
||||
m_RemoteMessages.clear();
|
||||
|
||||
for (FileQueue::iterator it = m_RemoteQueue.GetFileQueue()->begin(); it != m_RemoteQueue.GetFileQueue()->end(); it++)
|
||||
for (DownloadQueue::iterator it = m_RemoteQueue.begin(); it != m_RemoteQueue.end(); it++)
|
||||
{
|
||||
delete *it;
|
||||
}
|
||||
m_RemoteQueue.GetFileQueue()->clear();
|
||||
m_RemoteQueue.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,7 +151,7 @@ void Frontend::UnlockMessages()
|
||||
}
|
||||
}
|
||||
|
||||
DownloadQueue* Frontend::LockQueue()
|
||||
DownloadQueue * Frontend::LockQueue()
|
||||
{
|
||||
if (IsRemoteMode())
|
||||
{
|
||||
@@ -174,22 +176,15 @@ bool Frontend::IsRemoteMode()
|
||||
return g_pOptions->GetRemoteClientMode();
|
||||
}
|
||||
|
||||
void Frontend::ServerPauseUnpause(bool bPause, bool bSecondRegister)
|
||||
void Frontend::ServerPauseUnpause(bool bPause)
|
||||
{
|
||||
if (IsRemoteMode())
|
||||
{
|
||||
RequestPauseUnpause(bPause, bSecondRegister);
|
||||
RequestPauseUnpause(bPause);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bSecondRegister)
|
||||
{
|
||||
g_pOptions->SetPauseDownload2(bPause);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_pOptions->SetPauseDownload(bPause);
|
||||
}
|
||||
g_pOptions->SetPause(bPause);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,11 +216,11 @@ bool Frontend::ServerEditQueue(QueueEditor::EEditAction eAction, int iOffset, in
|
||||
{
|
||||
if (IsRemoteMode())
|
||||
{
|
||||
return RequestEditQueue((eRemoteEditAction)eAction, iOffset, iID);
|
||||
return RequestEditQueue(eAction, iOffset, iID);
|
||||
}
|
||||
else
|
||||
{
|
||||
return g_pQueueCoordinator->GetQueueEditor()->EditEntry(iID, true, eAction, iOffset, NULL);
|
||||
return g_pQueueCoordinator->GetQueueEditor()->EditEntry(iID, true, eAction, iOffset);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -244,7 +239,7 @@ bool Frontend::RequestMessages()
|
||||
NetAddress netAddress(g_pOptions->GetServerIP(), g_pOptions->GetServerPort());
|
||||
Connection connection(&netAddress);
|
||||
|
||||
bool OK = connection.Connect();
|
||||
bool OK = connection.Connect() >= 0;
|
||||
if (!OK)
|
||||
{
|
||||
return false;
|
||||
@@ -316,7 +311,7 @@ bool Frontend::RequestFileList()
|
||||
NetAddress netAddress(g_pOptions->GetServerIP(), g_pOptions->GetServerPort());
|
||||
Connection connection(&netAddress);
|
||||
|
||||
bool OK = connection.Connect();
|
||||
bool OK = connection.Connect() >= 0;
|
||||
if (!OK)
|
||||
{
|
||||
return false;
|
||||
@@ -357,8 +352,7 @@ bool Frontend::RequestFileList()
|
||||
|
||||
if (m_bSummary)
|
||||
{
|
||||
m_bPauseDownload = ntohl(ListResponse.m_bDownloadPaused);
|
||||
m_bPauseDownload2 = ntohl(ListResponse.m_bDownload2Paused);
|
||||
m_bPause = ntohl(ListResponse.m_bServerPaused);
|
||||
m_lRemainingSize = Util::JoinInt64(ntohl(ListResponse.m_iRemainingSizeHi), ntohl(ListResponse.m_iRemainingSizeLo));
|
||||
m_fCurrentDownloadSpeed = ntohl(ListResponse.m_iDownloadRate) / 1024.0f;
|
||||
m_fDownloadLimit = ntohl(ListResponse.m_iDownloadLimit) / 1024.0f;
|
||||
@@ -366,17 +360,61 @@ bool Frontend::RequestFileList()
|
||||
m_iPostJobCount = ntohl(ListResponse.m_iPostJobCount);
|
||||
m_iUpTimeSec = ntohl(ListResponse.m_iUpTimeSec);
|
||||
m_iDnTimeSec = ntohl(ListResponse.m_iDownloadTimeSec);
|
||||
m_bStandBy = ntohl(ListResponse.m_bDownloadStandBy);
|
||||
m_bStandBy = ntohl(ListResponse.m_bServerStandBy);
|
||||
m_iAllBytes = Util::JoinInt64(ntohl(ListResponse.m_iDownloadedBytesHi), ntohl(ListResponse.m_iDownloadedBytesLo));
|
||||
}
|
||||
|
||||
if (m_bFileList && ntohl(ListResponse.m_iTrailingDataLength) > 0)
|
||||
{
|
||||
RemoteClient client;
|
||||
client.SetVerbose(false);
|
||||
client.BuildFileList(&ListResponse, pBuf, &m_RemoteQueue);
|
||||
}
|
||||
typedef std::deque<NZBInfo*> NZBList;
|
||||
NZBList cNZBList;
|
||||
|
||||
char* pBufPtr = (char*)pBuf;
|
||||
for (unsigned int i = 0; i < ntohl(ListResponse.m_iNrTrailingEntries); i++)
|
||||
{
|
||||
SNZBListResponseEntry* pListAnswer = (SNZBListResponseEntry*) pBufPtr;
|
||||
|
||||
char* szNZBFilename = pBufPtr + sizeof(SNZBListResponseEntry);
|
||||
char* szSubject = pBufPtr + sizeof(SNZBListResponseEntry) + ntohl(pListAnswer->m_iNZBFilenameLen);
|
||||
char* szFileName = pBufPtr + sizeof(SNZBListResponseEntry) + ntohl(pListAnswer->m_iNZBFilenameLen) + ntohl(pListAnswer->m_iSubjectLen);
|
||||
char* szDestDir = pBufPtr + sizeof(SNZBListResponseEntry) + ntohl(pListAnswer->m_iNZBFilenameLen) + ntohl(pListAnswer->m_iSubjectLen) + ntohl(pListAnswer->m_iFilenameLen);
|
||||
|
||||
FileInfo* pFileInfo = new FileInfo();
|
||||
pFileInfo->SetID(ntohl(pListAnswer->m_iID));
|
||||
pFileInfo->SetSize(Util::JoinInt64(ntohl(pListAnswer->m_iFileSizeHi), ntohl(pListAnswer->m_iFileSizeLo)));
|
||||
pFileInfo->SetRemainingSize(Util::JoinInt64(ntohl(pListAnswer->m_iRemainingSizeHi), ntohl(pListAnswer->m_iRemainingSizeLo)));
|
||||
pFileInfo->SetPaused(ntohl(pListAnswer->m_bPaused));
|
||||
pFileInfo->SetSubject(szSubject);
|
||||
pFileInfo->SetFilename(szFileName);
|
||||
pFileInfo->SetFilenameConfirmed(ntohl(pListAnswer->m_bFilenameConfirmed));
|
||||
|
||||
// find nzb-info or create new
|
||||
NZBInfo* pNZBInfo = NULL;
|
||||
for (NZBList::iterator it = cNZBList.begin(); it != cNZBList.end(); it++)
|
||||
{
|
||||
NZBInfo* pNZBInfo2 = *it;
|
||||
if (!strcmp(pNZBInfo2->GetFilename(), szNZBFilename))
|
||||
{
|
||||
pNZBInfo = pNZBInfo2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!pNZBInfo)
|
||||
{
|
||||
pNZBInfo = new NZBInfo();
|
||||
pNZBInfo->SetFilename(szNZBFilename);
|
||||
pNZBInfo->SetDestDir(szDestDir);
|
||||
cNZBList.push_back(pNZBInfo);
|
||||
}
|
||||
|
||||
pFileInfo->SetNZBInfo(pNZBInfo);
|
||||
|
||||
m_RemoteQueue.push_back(pFileInfo);
|
||||
|
||||
pBufPtr += sizeof(SNZBListResponseEntry) + ntohl(pListAnswer->m_iNZBFilenameLen) +
|
||||
ntohl(pListAnswer->m_iSubjectLen) + ntohl(pListAnswer->m_iFilenameLen) + ntohl(pListAnswer->m_iDestDirLen);
|
||||
}
|
||||
}
|
||||
if (pBuf)
|
||||
{
|
||||
free(pBuf);
|
||||
@@ -385,11 +423,11 @@ bool Frontend::RequestFileList()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Frontend::RequestPauseUnpause(bool bPause, bool bSecondRegister)
|
||||
bool Frontend::RequestPauseUnpause(bool bPause)
|
||||
{
|
||||
RemoteClient client;
|
||||
client.SetVerbose(false);
|
||||
return client.RequestServerPauseUnpause(bPause, bSecondRegister ? eRemotePauseUnpauseActionDownload2 : eRemotePauseUnpauseActionDownload);
|
||||
return client.RequestServerPauseUnpause(bPause);
|
||||
}
|
||||
|
||||
bool Frontend::RequestSetDownloadRate(float fRate)
|
||||
@@ -406,9 +444,9 @@ bool Frontend::RequestDumpDebug()
|
||||
return client.RequestServerDumpDebug();
|
||||
}
|
||||
|
||||
bool Frontend::RequestEditQueue(eRemoteEditAction iAction, int iOffset, int iID)
|
||||
bool Frontend::RequestEditQueue(int iAction, int iOffset, int iID)
|
||||
{
|
||||
RemoteClient client;
|
||||
client.SetVerbose(false);
|
||||
return client.RequestServerEditQueue(iAction, iOffset, NULL, &iID, 1, false);
|
||||
return client.RequestServerEditQueue(iAction, iOffset, &iID, 1, false);
|
||||
}
|
||||
|
||||
13
Frontend.h
13
Frontend.h
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007-2010 Andrei Prygounkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007 Andrei Prygounkov <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
|
||||
@@ -52,8 +52,7 @@ protected:
|
||||
// summary
|
||||
float m_fCurrentDownloadSpeed;
|
||||
long long m_lRemainingSize;
|
||||
bool m_bPauseDownload;
|
||||
bool m_bPauseDownload2;
|
||||
bool m_bPause;
|
||||
float m_fDownloadLimit;
|
||||
int m_iThreadCount;
|
||||
int m_iPostJobCount;
|
||||
@@ -70,14 +69,14 @@ protected:
|
||||
void UnlockQueue();
|
||||
bool IsRemoteMode();
|
||||
void InitMessageBase(SNZBRequestBase* pMessageBase, int iRequest, int iSize);
|
||||
void ServerPauseUnpause(bool bPause, bool bSecondRegister);
|
||||
bool RequestPauseUnpause(bool bPause, bool bSecondRegister);
|
||||
void ServerPauseUnpause(bool bPause);
|
||||
bool RequestPauseUnpause(bool bPause);
|
||||
void ServerSetDownloadRate(float fRate);
|
||||
bool RequestSetDownloadRate(float fRate);
|
||||
void ServerDumpDebug();
|
||||
bool RequestDumpDebug();
|
||||
bool ServerEditQueue(QueueEditor::EEditAction eAction, int iOffset, int iEntry);
|
||||
bool RequestEditQueue(eRemoteEditAction iAction, int iOffset, int iID);
|
||||
bool RequestEditQueue(int iAction, int iOffset, int iID);
|
||||
|
||||
public:
|
||||
Frontend();
|
||||
|
||||
116
Log.cpp
116
Log.cpp
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007-2009 Andrei Prygounkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007 Andrei Prygounkov <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
|
||||
@@ -30,8 +30,6 @@
|
||||
|
||||
#ifdef WIN32
|
||||
#include "win32.h"
|
||||
#else
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
@@ -72,8 +70,18 @@ Log::~Log()
|
||||
|
||||
void Log::Filelog(const char* msg, ...)
|
||||
{
|
||||
if (m_szLogFilename)
|
||||
if (
|
||||
(g_pOptions && g_pOptions->GetCreateLog() && g_pOptions->GetLogFile())
|
||||
#ifdef DEBUG
|
||||
|| (m_szLogFilename && m_bExtraDebug)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
if (!m_szLogFilename)
|
||||
{
|
||||
m_szLogFilename = strdup(g_pOptions->GetLogFile());
|
||||
}
|
||||
|
||||
char tmp2[1024];
|
||||
|
||||
va_list ap;
|
||||
@@ -94,7 +102,7 @@ void Log::Filelog(const char* msg, ...)
|
||||
szTime[50-1] = '\0';
|
||||
szTime[strlen(szTime) - 1] = '\0'; // trim LF
|
||||
|
||||
FILE* file = fopen(m_szLogFilename, "ab+");
|
||||
FILE* file = fopen(m_szLogFilename, "a+");
|
||||
if (file)
|
||||
{
|
||||
#ifdef WIN32
|
||||
@@ -103,9 +111,9 @@ void Log::Filelog(const char* msg, ...)
|
||||
unsigned long iThreadId = (unsigned long)pthread_self();
|
||||
#endif
|
||||
#ifdef DEBUG
|
||||
fprintf(file, "%s\t%lu\t%s%s", szTime, iThreadId, tmp2, LINE_ENDING);
|
||||
fprintf(file, "%s\t%lu\t%s\n", szTime, iThreadId, tmp2);
|
||||
#else
|
||||
fprintf(file, "%s\t%s%s", szTime, tmp2, LINE_ENDING);
|
||||
fprintf(file, "%s\t%s\n", szTime, tmp2);
|
||||
#endif
|
||||
fclose(file);
|
||||
}
|
||||
@@ -116,7 +124,6 @@ void Log::Filelog(const char* msg, ...)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
#undef debug
|
||||
#ifdef HAVE_VARIADIC_MACROS
|
||||
void debug(const char* szFilename, const char* szFuncname, int iLineNr, const char* msg, ...)
|
||||
@@ -124,6 +131,7 @@ void debug(const char* szFilename, const char* szFuncname, int iLineNr, const ch
|
||||
void debug(const char* msg, ...)
|
||||
#endif
|
||||
{
|
||||
#ifdef DEBUG
|
||||
char tmp1[1024];
|
||||
|
||||
va_list ap;
|
||||
@@ -149,12 +157,18 @@ void debug(const char* msg, ...)
|
||||
|
||||
g_pLog->m_mutexLog.Lock();
|
||||
|
||||
if (!g_pOptions && g_pLog->m_bExtraDebug)
|
||||
if (!g_pOptions)
|
||||
{
|
||||
printf("%s\n", tmp2);
|
||||
if (g_pLog->m_bExtraDebug)
|
||||
{
|
||||
printf("%s\n", tmp2);
|
||||
g_pLog->Filelog("DEBUG\t%s", tmp2);
|
||||
}
|
||||
g_pLog->m_mutexLog.Unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
Options::EMessageTarget eMessageTarget = g_pOptions ? g_pOptions->GetDebugTarget() : Options::mtScreen;
|
||||
Options::EMessageTarget eMessageTarget = g_pOptions->GetDebugTarget();
|
||||
if (eMessageTarget == Options::mtLog || eMessageTarget == Options::mtBoth)
|
||||
{
|
||||
g_pLog->Filelog("DEBUG\t%s", tmp2);
|
||||
@@ -165,8 +179,8 @@ void debug(const char* msg, ...)
|
||||
}
|
||||
|
||||
g_pLog->m_mutexLog.Unlock();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void error(const char* msg, ...)
|
||||
{
|
||||
@@ -180,7 +194,7 @@ void error(const char* msg, ...)
|
||||
|
||||
g_pLog->m_mutexLog.Lock();
|
||||
|
||||
Options::EMessageTarget eMessageTarget = g_pOptions ? g_pOptions->GetErrorTarget() : Options::mtBoth;
|
||||
Options::EMessageTarget eMessageTarget = g_pOptions->GetErrorTarget();
|
||||
if (eMessageTarget == Options::mtLog || eMessageTarget == Options::mtBoth)
|
||||
{
|
||||
g_pLog->Filelog("ERROR\t%s", tmp2);
|
||||
@@ -205,7 +219,7 @@ void warn(const char* msg, ...)
|
||||
|
||||
g_pLog->m_mutexLog.Lock();
|
||||
|
||||
Options::EMessageTarget eMessageTarget = g_pOptions ? g_pOptions->GetWarningTarget() : Options::mtScreen;
|
||||
Options::EMessageTarget eMessageTarget = g_pOptions->GetWarningTarget();
|
||||
if (eMessageTarget == Options::mtLog || eMessageTarget == Options::mtBoth)
|
||||
{
|
||||
g_pLog->Filelog("WARNING\t%s", tmp2);
|
||||
@@ -230,7 +244,7 @@ void info(const char* msg, ...)
|
||||
|
||||
g_pLog->m_mutexLog.Lock();
|
||||
|
||||
Options::EMessageTarget eMessageTarget = g_pOptions ? g_pOptions->GetInfoTarget() : Options::mtScreen;
|
||||
Options::EMessageTarget eMessageTarget = g_pOptions->GetInfoTarget();
|
||||
if (eMessageTarget == Options::mtLog || eMessageTarget == Options::mtBoth)
|
||||
{
|
||||
g_pLog->Filelog("INFO\t%s", tmp2);
|
||||
@@ -255,7 +269,7 @@ void detail(const char* msg, ...)
|
||||
|
||||
g_pLog->m_mutexLog.Lock();
|
||||
|
||||
Options::EMessageTarget eMessageTarget = g_pOptions ? g_pOptions->GetDetailTarget() : Options::mtScreen;
|
||||
Options::EMessageTarget eMessageTarget = g_pOptions->GetDetailTarget();
|
||||
if (eMessageTarget == Options::mtLog || eMessageTarget == Options::mtBoth)
|
||||
{
|
||||
g_pLog->Filelog("DETAIL\t%s", tmp2);
|
||||
@@ -320,14 +334,11 @@ void Log::AppendMessage(Message::EKind eKind, const char * szText)
|
||||
Message* pMessage = new Message(++m_iIDGen, eKind, time(NULL), szText);
|
||||
m_Messages.push_back(pMessage);
|
||||
|
||||
if (g_pOptions)
|
||||
while (m_Messages.size() > (unsigned int)g_pOptions->GetLogBufferSize())
|
||||
{
|
||||
while (m_Messages.size() > (unsigned int)g_pOptions->GetLogBufferSize())
|
||||
{
|
||||
Message* pMessage = m_Messages.front();
|
||||
delete pMessage;
|
||||
m_Messages.pop_front();
|
||||
}
|
||||
Message* pMessage = m_Messages.front();
|
||||
delete pMessage;
|
||||
m_Messages.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -346,60 +357,3 @@ void Log::ResetLog()
|
||||
{
|
||||
remove(g_pOptions->GetLogFile());
|
||||
}
|
||||
|
||||
/*
|
||||
* During intializing stage (when options were not read yet) all messages
|
||||
* are saved in screen log, even if they shouldn't (according to options).
|
||||
* Method "InitOptions()" check all messages added to screen log during
|
||||
* intializing stage and does two things:
|
||||
* 1) save the messages to log-file (if they should according to options);
|
||||
* 2) delete messages from screen log (if they should not be saved in screen log).
|
||||
*/
|
||||
void Log::InitOptions()
|
||||
{
|
||||
const char* szMessageType[] = { "INFO", "WARNING", "ERROR", "DEBUG", "DETAIL"};
|
||||
|
||||
if (g_pOptions->GetCreateLog() && g_pOptions->GetLogFile())
|
||||
{
|
||||
m_szLogFilename = strdup(g_pOptions->GetLogFile());
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < m_Messages.size(); )
|
||||
{
|
||||
Message* pMessage = m_Messages.at(i);
|
||||
Options::EMessageTarget eTarget = Options::mtNone;
|
||||
switch (pMessage->GetKind())
|
||||
{
|
||||
case Message::mkDebug:
|
||||
eTarget = g_pOptions->GetDebugTarget();
|
||||
break;
|
||||
case Message::mkDetail:
|
||||
eTarget = g_pOptions->GetDetailTarget();
|
||||
break;
|
||||
case Message::mkInfo:
|
||||
eTarget = g_pOptions->GetInfoTarget();
|
||||
break;
|
||||
case Message::mkWarning:
|
||||
eTarget = g_pOptions->GetWarningTarget();
|
||||
break;
|
||||
case Message::mkError:
|
||||
eTarget = g_pOptions->GetErrorTarget();
|
||||
break;
|
||||
}
|
||||
|
||||
if (eTarget == Options::mtLog || eTarget == Options::mtBoth)
|
||||
{
|
||||
Filelog("%s\t%s", szMessageType[pMessage->GetKind()], pMessage->GetText());
|
||||
}
|
||||
|
||||
if (eTarget == Options::mtLog || eTarget == Options::mtNone)
|
||||
{
|
||||
delete pMessage;
|
||||
m_Messages.erase(m_Messages.begin() + i);
|
||||
}
|
||||
else
|
||||
{
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
26
Log.h
26
Log.h
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
* This file if part of nzbget
|
||||
*
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007-2009 Andrei Prygounkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007 Andrei Prygounkov <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,13 +38,12 @@ void info(const char* msg, ...);
|
||||
void detail(const char* msg, ...);
|
||||
void abort(const char* msg, ...);
|
||||
|
||||
#ifdef DEBUG
|
||||
#ifdef HAVE_VARIADIC_MACROS
|
||||
void debug(const char* szFilename, const char* szFuncname, int iLineNr, const char* msg, ...);
|
||||
#else
|
||||
void debug(const char* msg, ...);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
class Message
|
||||
{
|
||||
@@ -95,29 +94,26 @@ private:
|
||||
friend void info(const char* msg, ...);
|
||||
friend void abort(const char* msg, ...);
|
||||
friend void detail(const char* msg, ...);
|
||||
#ifdef DEBUG
|
||||
#ifdef HAVE_VARIADIC_MACROS
|
||||
friend void debug(const char* szFilename, const char* szFuncname, int iLineNr, const char* msg, ...);
|
||||
#else
|
||||
friend void debug(const char* msg, ...);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
public:
|
||||
Log();
|
||||
~Log();
|
||||
Log();
|
||||
~Log();
|
||||
Messages* LockMessages();
|
||||
void UnlockMessages();
|
||||
void ResetLog();
|
||||
void InitOptions();
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
#ifdef HAVE_VARIADIC_MACROS
|
||||
#define debug(...) debug(__FILE__, FUNCTION_MACRO_NAME, __LINE__, __VA_ARGS__)
|
||||
#endif
|
||||
#else
|
||||
#define debug(...) do { } while(0)
|
||||
#ifdef DEBUG
|
||||
#define debug(...) debug(__FILE__, FUNCTION_MACRO_NAME, __LINE__, __VA_ARGS__)
|
||||
#else
|
||||
#define debug(...) do { } while(0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
extern Log* g_pLog;
|
||||
|
||||
66
Makefile.am
66
Makefile.am
@@ -1,59 +1,19 @@
|
||||
bin_PROGRAMS = nzbget
|
||||
nzbget_SOURCES = ArticleDownloader.cpp ArticleDownloader.h BinRpc.cpp BinRpc.h \
|
||||
ColoredFrontend.cpp ColoredFrontend.h Connection.cpp Connection.h Decoder.cpp Decoder.h \
|
||||
DiskState.cpp DiskState.h DownloadInfo.cpp DownloadInfo.h Frontend.cpp Frontend.h \
|
||||
Log.cpp Log.h LoggableFrontend.cpp LoggableFrontend.h MessageBase.h \
|
||||
NCursesFrontend.cpp NCursesFrontend.h NNTPConnection.cpp NNTPConnection.h NZBFile.cpp \
|
||||
NZBFile.h NetAddress.cpp NetAddress.h NewsServer.cpp NewsServer.h Observer.cpp \
|
||||
Observer.h Options.cpp Options.h ParChecker.cpp ParChecker.h \
|
||||
PrePostProcessor.cpp PrePostProcessor.h QueueCoordinator.cpp \
|
||||
QueueCoordinator.h QueueEditor.cpp QueueEditor.h RemoteClient.cpp RemoteClient.h \
|
||||
RemoteServer.cpp RemoteServer.h Scanner.cpp Scanner.h Scheduler.cpp Scheduler.h ScriptController.cpp \
|
||||
ScriptController.h ServerPool.cpp ServerPool.h svn_version.cpp TLS.cpp TLS.h Thread.cpp Thread.h Util.cpp \
|
||||
Util.h XmlRpc.cpp XmlRpc.h nzbget.cpp nzbget.h
|
||||
nzbget_SOURCES = ArticleDownloader.cpp ArticleDownloader.h ColoredFrontend.cpp \
|
||||
ColoredFrontend.h Connection.cpp Connection.h Decoder.cpp Decoder.h DiskState.cpp \
|
||||
DiskState.h DownloadInfo.cpp DownloadInfo.h Frontend.cpp Frontend.h Log.cpp Log.h \
|
||||
LoggableFrontend.cpp LoggableFrontend.h MessageBase.h NCursesFrontend.cpp NCursesFrontend.h \
|
||||
NNTPConnection.cpp NNTPConnection.h NZBFile.cpp NZBFile.h NetAddress.cpp NetAddress.h \
|
||||
NewsServer.cpp NewsServer.h Observer.cpp Observer.h Options.cpp Options.h \
|
||||
ParChecker.cpp ParChecker.h PrePostProcessor.cpp PrePostProcessor.h \
|
||||
QueueCoordinator.cpp QueueCoordinator.h QueueEditor.cpp QueueEditor.h RemoteClient.cpp \
|
||||
RemoteClient.h RemoteServer.cpp RemoteServer.h ServerPool.cpp ServerPool.h Thread.cpp \
|
||||
Thread.h Util.cpp Util.h nzbget.cpp nzbget.h BinRpc.cpp BinRpc.h XmlRpc.cpp XmlRpc.h \
|
||||
PostInfo.cpp PostInfo.h ScriptController.cpp ScriptController.h
|
||||
|
||||
EXTRA_DIST = nzbget.conf.example postprocess-example.sh postprocess-example.conf \
|
||||
EXTRA_DIST = nzbget.conf.example \
|
||||
win32.h NTService.cpp NTService.h \
|
||||
libpar2-0.2-bugfixes.patch libpar2-0.2-cancel.patch \
|
||||
libpar2-0.2-MSVC8.patch libsigc++-2.0.18-MSVC8.patch \
|
||||
Makefile.cvs nzbget.kdevelop nzbget.sln nzbget.vcproj \
|
||||
nzbgetd nzbget-shell.bat
|
||||
|
||||
# Determining subversion revision:
|
||||
# 1) If directory ".svn" exists we take revision from it using program svnversion (part of subversion package)
|
||||
# File is recreated only if revision number was changed.
|
||||
# 2) If directory ".svn" doesn't exists we keep and reuse file "svn_version.cpp",
|
||||
# which was possibly created early.
|
||||
# 3) If neither directory ".svn" nor file "svn_version.cpp" are available
|
||||
# we create new file "svn_version.c" with empty revision number.
|
||||
svn_version.cpp: FORCE
|
||||
@ if test -d ./.svn ; then \
|
||||
V="$(shell svnversion -n .)"; \
|
||||
H="$(shell test -f ./svn_version.cpp && head -n 1 svn_version.cpp)"; \
|
||||
if test "/* $$V */" != "$$H" ; then \
|
||||
( \
|
||||
echo "/* $$V */" ;\
|
||||
echo "/* This file is automatically regenerated on each build. Do not edit it. */" ;\
|
||||
echo "const char* svn_version(void)" ;\
|
||||
echo "{" ;\
|
||||
echo " const char* SVN_Version = \"$$V\";" ;\
|
||||
echo " return SVN_Version;" ;\
|
||||
echo "}" ;\
|
||||
) > svn_version.cpp ; \
|
||||
fi \
|
||||
elif test -f ./svn_version.cpp ; then \
|
||||
test "ok, reuse existing file"; \
|
||||
else \
|
||||
( \
|
||||
echo "/* */" ;\
|
||||
echo "/* This file is automatically regenerated on each build. Do not edit it. */" ;\
|
||||
echo "const char* svn_version(void)" ;\
|
||||
echo "{" ;\
|
||||
echo " const char* SVN_Version = \"\";" ;\
|
||||
echo " return SVN_Version;" ;\
|
||||
echo "}" ;\
|
||||
) > svn_version.cpp ; \
|
||||
fi
|
||||
FORCE:
|
||||
Makefile.cvs nzbget.kdevelop nzbget.sln nzbget.vcproj
|
||||
|
||||
clean-bak: rm *~
|
||||
|
||||
196
Makefile.in
196
Makefile.in
@@ -1,8 +1,8 @@
|
||||
# Makefile.in generated by automake 1.9.6 from Makefile.am.
|
||||
# Makefile.in generated by automake 1.10 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
||||
# 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
# 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
@@ -14,15 +14,11 @@
|
||||
|
||||
@SET_MAKE@
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
top_builddir = .
|
||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||
INSTALL = @INSTALL@
|
||||
install_sh_DATA = $(install_sh) -c -m 644
|
||||
install_sh_PROGRAM = $(install_sh) -c
|
||||
install_sh_SCRIPT = $(install_sh) -c
|
||||
@@ -37,24 +33,24 @@ POST_UNINSTALL = :
|
||||
build_triplet = @build@
|
||||
host_triplet = @host@
|
||||
bin_PROGRAMS = nzbget$(EXEEXT)
|
||||
subdir = .
|
||||
DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \
|
||||
$(srcdir)/Makefile.in $(srcdir)/config.h.in \
|
||||
$(top_srcdir)/configure AUTHORS COPYING ChangeLog INSTALL NEWS \
|
||||
config.guess config.sub depcomp install-sh missing
|
||||
subdir = .
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/configure.ac
|
||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
$(ACLOCAL_M4)
|
||||
am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
|
||||
configure.lineno configure.status.lineno
|
||||
configure.lineno config.status.lineno
|
||||
mkinstalldirs = $(install_sh) -d
|
||||
CONFIG_HEADER = config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
am__installdirs = "$(DESTDIR)$(bindir)"
|
||||
binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
|
||||
PROGRAMS = $(bin_PROGRAMS)
|
||||
am_nzbget_OBJECTS = ArticleDownloader.$(OBJEXT) BinRpc.$(OBJEXT) \
|
||||
am_nzbget_OBJECTS = ArticleDownloader.$(OBJEXT) \
|
||||
ColoredFrontend.$(OBJEXT) Connection.$(OBJEXT) \
|
||||
Decoder.$(OBJEXT) DiskState.$(OBJEXT) DownloadInfo.$(OBJEXT) \
|
||||
Frontend.$(OBJEXT) Log.$(OBJEXT) LoggableFrontend.$(OBJEXT) \
|
||||
@@ -63,13 +59,12 @@ am_nzbget_OBJECTS = ArticleDownloader.$(OBJEXT) BinRpc.$(OBJEXT) \
|
||||
Observer.$(OBJEXT) Options.$(OBJEXT) ParChecker.$(OBJEXT) \
|
||||
PrePostProcessor.$(OBJEXT) QueueCoordinator.$(OBJEXT) \
|
||||
QueueEditor.$(OBJEXT) RemoteClient.$(OBJEXT) \
|
||||
RemoteServer.$(OBJEXT) Scanner.$(OBJEXT) Scheduler.$(OBJEXT) \
|
||||
ScriptController.$(OBJEXT) ServerPool.$(OBJEXT) \
|
||||
svn_version.$(OBJEXT) TLS.$(OBJEXT) Thread.$(OBJEXT) \
|
||||
Util.$(OBJEXT) XmlRpc.$(OBJEXT) nzbget.$(OBJEXT)
|
||||
RemoteServer.$(OBJEXT) ServerPool.$(OBJEXT) Thread.$(OBJEXT) \
|
||||
Util.$(OBJEXT) nzbget.$(OBJEXT) BinRpc.$(OBJEXT) \
|
||||
XmlRpc.$(OBJEXT) PostInfo.$(OBJEXT) ScriptController.$(OBJEXT)
|
||||
nzbget_OBJECTS = $(am_nzbget_OBJECTS)
|
||||
nzbget_LDADD = $(LDADD)
|
||||
DEFAULT_INCLUDES = -I. -I$(srcdir) -I.
|
||||
DEFAULT_INCLUDES = -I.@am__isrc@
|
||||
depcomp = $(SHELL) $(top_srcdir)/depcomp
|
||||
am__depfiles_maybe = depfiles
|
||||
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
|
||||
@@ -98,15 +93,17 @@ distuninstallcheck_listfiles = find . -type f -print
|
||||
distcleancheck_listfiles = find . -type f -print
|
||||
ACLOCAL = @ACLOCAL@
|
||||
ADDSRCS = @ADDSRCS@
|
||||
AMDEP_FALSE = @AMDEP_FALSE@
|
||||
AMDEP_TRUE = @AMDEP_TRUE@
|
||||
AMTAR = @AMTAR@
|
||||
AR = @AR@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AWK = @AWK@
|
||||
CC = @CC@
|
||||
CCDEPMODE = @CCDEPMODE@
|
||||
CFLAGS = @CFLAGS@
|
||||
CP = @CP@
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CXX = @CXX@
|
||||
CXXCPP = @CXXCPP@
|
||||
@@ -120,7 +117,9 @@ ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
EXEEXT = @EXEEXT@
|
||||
FALSE = @FALSE@
|
||||
GREP = @GREP@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
@@ -128,9 +127,13 @@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBS = @LIBS@
|
||||
LN = @LN@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
MAKE = @MAKE@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MKDIR = @MKDIR@
|
||||
MKDIR_P = @MKDIR_P@
|
||||
MV = @MV@
|
||||
OBJEXT = @OBJEXT@
|
||||
PACKAGE = @PACKAGE@
|
||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||
@@ -139,15 +142,20 @@ PACKAGE_STRING = @PACKAGE_STRING@
|
||||
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||
PKG_CONFIG = @PKG_CONFIG@
|
||||
RANLIB = @RANLIB@
|
||||
RM = @RM@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
STRIP = @STRIP@
|
||||
TAR = @TAR@
|
||||
TRUE = @TRUE@
|
||||
VERSION = @VERSION@
|
||||
abs_builddir = @abs_builddir@
|
||||
abs_srcdir = @abs_srcdir@
|
||||
abs_top_builddir = @abs_top_builddir@
|
||||
abs_top_srcdir = @abs_top_srcdir@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_CXX = @ac_ct_CXX@
|
||||
am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
|
||||
am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
|
||||
am__include = @am__include@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
am__quote = @am__quote@
|
||||
@@ -159,6 +167,7 @@ build_alias = @build_alias@
|
||||
build_cpu = @build_cpu@
|
||||
build_os = @build_os@
|
||||
build_vendor = @build_vendor@
|
||||
builddir = @builddir@
|
||||
datadir = @datadir@
|
||||
datarootdir = @datarootdir@
|
||||
docdir = @docdir@
|
||||
@@ -175,10 +184,6 @@ infodir = @infodir@
|
||||
install_sh = @install_sh@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
libsigc_CFLAGS = @libsigc_CFLAGS@
|
||||
libsigc_LIBS = @libsigc_LIBS@
|
||||
libxml2_CFLAGS = @libxml2_CFLAGS@
|
||||
libxml2_LIBS = @libxml2_LIBS@
|
||||
localedir = @localedir@
|
||||
localstatedir = @localstatedir@
|
||||
mandir = @mandir@
|
||||
@@ -190,27 +195,27 @@ program_transform_name = @program_transform_name@
|
||||
psdir = @psdir@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
srcdir = @srcdir@
|
||||
sysconfdir = @sysconfdir@
|
||||
target_alias = @target_alias@
|
||||
nzbget_SOURCES = ArticleDownloader.cpp ArticleDownloader.h BinRpc.cpp BinRpc.h \
|
||||
ColoredFrontend.cpp ColoredFrontend.h Connection.cpp Connection.h Decoder.cpp Decoder.h \
|
||||
DiskState.cpp DiskState.h DownloadInfo.cpp DownloadInfo.h Frontend.cpp Frontend.h \
|
||||
Log.cpp Log.h LoggableFrontend.cpp LoggableFrontend.h MessageBase.h \
|
||||
NCursesFrontend.cpp NCursesFrontend.h NNTPConnection.cpp NNTPConnection.h NZBFile.cpp \
|
||||
NZBFile.h NetAddress.cpp NetAddress.h NewsServer.cpp NewsServer.h Observer.cpp \
|
||||
Observer.h Options.cpp Options.h ParChecker.cpp ParChecker.h \
|
||||
PrePostProcessor.cpp PrePostProcessor.h QueueCoordinator.cpp \
|
||||
QueueCoordinator.h QueueEditor.cpp QueueEditor.h RemoteClient.cpp RemoteClient.h \
|
||||
RemoteServer.cpp RemoteServer.h Scanner.cpp Scanner.h Scheduler.cpp Scheduler.h ScriptController.cpp \
|
||||
ScriptController.h ServerPool.cpp ServerPool.h svn_version.cpp TLS.cpp TLS.h Thread.cpp Thread.h Util.cpp \
|
||||
Util.h XmlRpc.cpp XmlRpc.h nzbget.cpp nzbget.h
|
||||
top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
nzbget_SOURCES = ArticleDownloader.cpp ArticleDownloader.h ColoredFrontend.cpp \
|
||||
ColoredFrontend.h Connection.cpp Connection.h Decoder.cpp Decoder.h DiskState.cpp \
|
||||
DiskState.h DownloadInfo.cpp DownloadInfo.h Frontend.cpp Frontend.h Log.cpp Log.h \
|
||||
LoggableFrontend.cpp LoggableFrontend.h MessageBase.h NCursesFrontend.cpp NCursesFrontend.h \
|
||||
NNTPConnection.cpp NNTPConnection.h NZBFile.cpp NZBFile.h NetAddress.cpp NetAddress.h \
|
||||
NewsServer.cpp NewsServer.h Observer.cpp Observer.h Options.cpp Options.h \
|
||||
ParChecker.cpp ParChecker.h PrePostProcessor.cpp PrePostProcessor.h \
|
||||
QueueCoordinator.cpp QueueCoordinator.h QueueEditor.cpp QueueEditor.h RemoteClient.cpp \
|
||||
RemoteClient.h RemoteServer.cpp RemoteServer.h ServerPool.cpp ServerPool.h Thread.cpp \
|
||||
Thread.h Util.cpp Util.h nzbget.cpp nzbget.h BinRpc.cpp BinRpc.h XmlRpc.cpp XmlRpc.h \
|
||||
PostInfo.cpp PostInfo.h ScriptController.cpp ScriptController.h
|
||||
|
||||
EXTRA_DIST = nzbget.conf.example postprocess-example.sh postprocess-example.conf \
|
||||
EXTRA_DIST = nzbget.conf.example \
|
||||
win32.h NTService.cpp NTService.h \
|
||||
libpar2-0.2-bugfixes.patch libpar2-0.2-cancel.patch \
|
||||
libpar2-0.2-MSVC8.patch libsigc++-2.0.18-MSVC8.patch \
|
||||
Makefile.cvs nzbget.kdevelop nzbget.sln nzbget.vcproj \
|
||||
nzbgetd nzbget-shell.bat
|
||||
Makefile.cvs nzbget.kdevelop nzbget.sln nzbget.vcproj
|
||||
|
||||
all: config.h
|
||||
$(MAKE) $(AM_MAKEFLAGS) all-am
|
||||
@@ -254,7 +259,7 @@ $(ACLOCAL_M4): $(am__aclocal_m4_deps)
|
||||
config.h: stamp-h1
|
||||
@if test ! -f $@; then \
|
||||
rm -f stamp-h1; \
|
||||
$(MAKE) stamp-h1; \
|
||||
$(MAKE) $(AM_MAKEFLAGS) stamp-h1; \
|
||||
else :; fi
|
||||
|
||||
stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
|
||||
@@ -269,7 +274,7 @@ distclean-hdr:
|
||||
-rm -f config.h stamp-h1
|
||||
install-binPROGRAMS: $(bin_PROGRAMS)
|
||||
@$(NORMAL_INSTALL)
|
||||
test -z "$(bindir)" || $(mkdir_p) "$(DESTDIR)$(bindir)"
|
||||
test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
|
||||
@list='$(bin_PROGRAMS)'; for p in $$list; do \
|
||||
p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
|
||||
if test -f $$p \
|
||||
@@ -292,7 +297,7 @@ clean-binPROGRAMS:
|
||||
-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
|
||||
nzbget$(EXEEXT): $(nzbget_OBJECTS) $(nzbget_DEPENDENCIES)
|
||||
@rm -f nzbget$(EXEEXT)
|
||||
$(CXXLINK) $(nzbget_LDFLAGS) $(nzbget_OBJECTS) $(nzbget_LDADD) $(LIBS)
|
||||
$(CXXLINK) $(nzbget_OBJECTS) $(nzbget_LDADD) $(LIBS)
|
||||
|
||||
mostlyclean-compile:
|
||||
-rm -f *.$(OBJEXT)
|
||||
@@ -318,36 +323,32 @@ distclean-compile:
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Observer.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Options.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ParChecker.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PostInfo.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PrePostProcessor.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/QueueCoordinator.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/QueueEditor.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RemoteClient.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RemoteServer.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Scanner.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Scheduler.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ScriptController.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ServerPool.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TLS.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Thread.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Util.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XmlRpc.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nzbget.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/svn_version.Po@am__quote@
|
||||
|
||||
.cpp.o:
|
||||
@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
|
||||
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
|
||||
@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
|
||||
@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
|
||||
|
||||
.cpp.obj:
|
||||
@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
|
||||
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
|
||||
@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
|
||||
@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
|
||||
uninstall-info-am:
|
||||
|
||||
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
@@ -399,23 +400,22 @@ distclean-tags:
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
$(am__remove_distdir)
|
||||
mkdir $(distdir)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
|
||||
list='$(DISTFILES)'; for file in $$list; do \
|
||||
case $$file in \
|
||||
$(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
|
||||
$(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
|
||||
esac; \
|
||||
test -d $(distdir) || mkdir $(distdir)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
list='$(DISTFILES)'; \
|
||||
dist_files=`for file in $$list; do echo $$file; done | \
|
||||
sed -e "s|^$$srcdirstrip/||;t" \
|
||||
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
|
||||
case $$dist_files in \
|
||||
*/*) $(MKDIR_P) `echo "$$dist_files" | \
|
||||
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
|
||||
sort -u` ;; \
|
||||
esac; \
|
||||
for file in $$dist_files; do \
|
||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
|
||||
dir="/$$dir"; \
|
||||
$(mkdir_p) "$(distdir)$$dir"; \
|
||||
else \
|
||||
dir=''; \
|
||||
fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
|
||||
fi; \
|
||||
@@ -429,7 +429,7 @@ distdir: $(DISTFILES)
|
||||
-find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \
|
||||
! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
|
||||
! -type d ! -perm -400 -exec chmod a+r {} \; -o \
|
||||
! -type d ! -perm -444 -exec $(SHELL) $(install_sh) -c -m a+r {} {} \; \
|
||||
! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
|
||||
|| chmod -R a+r $(distdir)
|
||||
dist-gzip: distdir
|
||||
tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
|
||||
@@ -504,7 +504,7 @@ distcheck: dist
|
||||
$(am__remove_distdir)
|
||||
@(echo "$(distdir) archives ready for distribution: "; \
|
||||
list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
|
||||
sed -e '1{h;s/./=/g;p;x;}' -e '$${p;x;}'
|
||||
sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'
|
||||
distuninstallcheck:
|
||||
@cd $(distuninstallcheck_dir) \
|
||||
&& test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \
|
||||
@@ -528,7 +528,7 @@ check: check-am
|
||||
all-am: Makefile $(PROGRAMS) config.h
|
||||
installdirs:
|
||||
for dir in "$(DESTDIR)$(bindir)"; do \
|
||||
test -z "$$dir" || $(mkdir_p) "$$dir"; \
|
||||
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
|
||||
done
|
||||
install: install-am
|
||||
install-exec: install-exec-am
|
||||
@@ -577,12 +577,20 @@ info-am:
|
||||
|
||||
install-data-am:
|
||||
|
||||
install-dvi: install-dvi-am
|
||||
|
||||
install-exec-am: install-binPROGRAMS
|
||||
|
||||
install-html: install-html-am
|
||||
|
||||
install-info: install-info-am
|
||||
|
||||
install-man:
|
||||
|
||||
install-pdf: install-pdf-am
|
||||
|
||||
install-ps: install-ps-am
|
||||
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
@@ -604,7 +612,9 @@ ps: ps-am
|
||||
|
||||
ps-am:
|
||||
|
||||
uninstall-am: uninstall-binPROGRAMS uninstall-info-am
|
||||
uninstall-am: uninstall-binPROGRAMS
|
||||
|
||||
.MAKE: install-am install-strip
|
||||
|
||||
.PHONY: CTAGS GTAGS all all-am am--refresh check check-am clean \
|
||||
clean-binPROGRAMS clean-generic ctags dist dist-all dist-bzip2 \
|
||||
@@ -612,52 +622,16 @@ uninstall-am: uninstall-binPROGRAMS uninstall-info-am
|
||||
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-exec \
|
||||
install-exec-am install-info install-info-am install-man \
|
||||
install-binPROGRAMS install-data install-data-am install-dvi \
|
||||
install-dvi-am install-exec install-exec-am install-html \
|
||||
install-html-am install-info install-info-am install-man \
|
||||
install-pdf install-pdf-am install-ps install-ps-am \
|
||||
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-info-am
|
||||
tags uninstall uninstall-am uninstall-binPROGRAMS
|
||||
|
||||
|
||||
# Determining subversion revision:
|
||||
# 1) If directory ".svn" exists we take revision from it using program svnversion (part of subversion package)
|
||||
# File is recreated only if revision number was changed.
|
||||
# 2) If directory ".svn" doesn't exists we keep and reuse file "svn_version.cpp",
|
||||
# which was possibly created early.
|
||||
# 3) If neither directory ".svn" nor file "svn_version.cpp" are available
|
||||
# we create new file "svn_version.c" with empty revision number.
|
||||
svn_version.cpp: FORCE
|
||||
@ if test -d ./.svn ; then \
|
||||
V="$(shell svnversion -n .)"; \
|
||||
H="$(shell test -f ./svn_version.cpp && head -n 1 svn_version.cpp)"; \
|
||||
if test "/* $$V */" != "$$H" ; then \
|
||||
( \
|
||||
echo "/* $$V */" ;\
|
||||
echo "/* This file is automatically regenerated on each build. Do not edit it. */" ;\
|
||||
echo "const char* svn_version(void)" ;\
|
||||
echo "{" ;\
|
||||
echo " const char* SVN_Version = \"$$V\";" ;\
|
||||
echo " return SVN_Version;" ;\
|
||||
echo "}" ;\
|
||||
) > svn_version.cpp ; \
|
||||
fi \
|
||||
elif test -f ./svn_version.cpp ; then \
|
||||
test "ok, reuse existing file"; \
|
||||
else \
|
||||
( \
|
||||
echo "/* */" ;\
|
||||
echo "/* This file is automatically regenerated on each build. Do not edit it. */" ;\
|
||||
echo "const char* svn_version(void)" ;\
|
||||
echo "{" ;\
|
||||
echo " const char* SVN_Version = \"\";" ;\
|
||||
echo " return SVN_Version;" ;\
|
||||
echo "}" ;\
|
||||
) > svn_version.cpp ; \
|
||||
fi
|
||||
FORCE:
|
||||
|
||||
clean-bak: rm *~
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
|
||||
177
MessageBase.h
177
MessageBase.h
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2005 Bo Cordes Petersen <placebodk@users.sourceforge.net>
|
||||
* Copyright (C) 2007-2010 Andrei Prygounkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2005 Bo Cordes Petersen <placebodk@users.sourceforge.net>
|
||||
* Copyright (C) 2007 Andrei Prygounkov <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 = 0x6E7A6208; // = "nzb8" (protocol version)
|
||||
static const int32_t NZBMESSAGE_SIGNATURE = 0x6E7A6202; // = "nzb2" (nzb version 2)
|
||||
static const int NZBREQUESTFILENAMESIZE = 512;
|
||||
static const int NZBREQUESTPASSWORDSIZE = 32;
|
||||
|
||||
@@ -35,14 +35,8 @@ static const int NZBREQUESTPASSWORDSIZE = 32;
|
||||
* NZBGet communication protocol uses only two basic data types: integer and char.
|
||||
* Integer values are passed using network byte order (Big-Endian).
|
||||
* Use function "htonl" and "ntohl" to convert integers to/from machine
|
||||
* (host) byte order.
|
||||
' (host) byte order.
|
||||
* All char-strings ends with NULL-char.
|
||||
*
|
||||
* NOTE:
|
||||
* NZBGet communication protocol is intended for usage only by NZBGet itself.
|
||||
* The communication works only if server and client has the same version.
|
||||
* The compatibility with previous program versions is not provided.
|
||||
* Third-party programs should use JSON-RPC or XML-RPC to communicate with NZBGet.
|
||||
*/
|
||||
|
||||
// Possible values for field "m_iType" of struct "SNZBRequestBase":
|
||||
@@ -58,9 +52,7 @@ enum eRemoteRequest
|
||||
eRemoteRequestShutdown,
|
||||
eRemoteRequestVersion,
|
||||
eRemoteRequestPostQueue,
|
||||
eRemoteRequestWriteLog,
|
||||
eRemoteRequestScan,
|
||||
eRemoteRequestHistory
|
||||
eRemoteRequestWriteLog
|
||||
};
|
||||
|
||||
// Possible values for field "m_iAction" of struct "SNZBEditQueueRequest":
|
||||
@@ -68,41 +60,22 @@ enum eRemoteRequest
|
||||
// Group is a list of files, added to queue from one NZB-File.
|
||||
enum eRemoteEditAction
|
||||
{
|
||||
eRemoteEditActionFileMoveOffset = 1, // move files to m_iOffset relative to the current position in download-queue
|
||||
eRemoteEditActionFileMoveTop, // move files to the top of download-queue
|
||||
eRemoteEditActionFileMoveBottom, // move files to the bottom of download-queue
|
||||
eRemoteEditActionFilePause, // pause files
|
||||
eRemoteEditActionFileResume, // resume (unpause) files
|
||||
eRemoteEditActionFileDelete, // delete files
|
||||
eRemoteEditActionFileMoveOffset = 1, // move to m_iOffset relative to the current position in queue
|
||||
eRemoteEditActionFileMoveTop, // move to top of queue
|
||||
eRemoteEditActionFileMoveBottom, // move to bottom of queue
|
||||
eRemoteEditActionFilePause, // pause
|
||||
eRemoteEditActionFileResume, // resume (unpause)
|
||||
eRemoteEditActionFileDelete, // delete
|
||||
eRemoteEditActionFilePauseAllPars, // pause only (all) pars (does not affect other files)
|
||||
eRemoteEditActionFilePauseExtraPars, // pause only (almost all) pars, except main par-file (does not affect other 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
|
||||
eRemoteEditActionGroupPause, // pause group
|
||||
eRemoteEditActionGroupResume, // resume (unpause) group
|
||||
eRemoteEditActionGroupDelete, // delete group
|
||||
eRemoteEditActionGroupPauseAllPars, // pause only (all) pars (does not affect other files) in group
|
||||
eRemoteEditActionGroupPauseExtraPars, // pause only (almost all) pars in group, except main par-file (does not affect other files)
|
||||
eRemoteEditActionGroupSetCategory, // set or change category for a group
|
||||
eRemoteEditActionGroupMerge, // merge group
|
||||
eRemoteEditActionGroupSetParameter, // set post-process parameter for group
|
||||
eRemoteEditActionPostMoveOffset = 51, // move post-job to m_iOffset relative to the current position in post-queue
|
||||
eRemoteEditActionPostMoveTop, // move post-job to the top of post-queue
|
||||
eRemoteEditActionPostMoveBottom, // move post-job to the bottom of post-queue
|
||||
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
|
||||
};
|
||||
|
||||
// Possible values for field "m_iAction" of struct "SNZBPauseUnpauseRequest":
|
||||
enum eRemotePauseUnpauseAction
|
||||
{
|
||||
eRemotePauseUnpauseActionDownload = 1, // pause/unpause download queue
|
||||
eRemotePauseUnpauseActionDownload2, // pause/unpause download queue (second pause-register)
|
||||
eRemotePauseUnpauseActionPostProcess, // pause/unpause post-processor queue
|
||||
eRemotePauseUnpauseActionScan // pause/unpause scan of incoming nzb-directory
|
||||
eRemoteEditActionGroupMoveOffset, // move to m_iOffset relative to the current position in queue
|
||||
eRemoteEditActionGroupMoveTop, // move to top of queue
|
||||
eRemoteEditActionGroupMoveBottom, // move to bottom of queue
|
||||
eRemoteEditActionGroupPause, // pause
|
||||
eRemoteEditActionGroupResume, // resume (unpause)
|
||||
eRemoteEditActionGroupDelete, // delete
|
||||
eRemoteEditActionGroupPauseAllPars, // pause only (all) pars (does not affect other files)
|
||||
eRemoteEditActionGroupPauseExtraPars // pause only (almost all) pars, except main par-file (does not affect other files)
|
||||
};
|
||||
|
||||
// The basic SNZBRequestBase struct, used in all requests
|
||||
@@ -126,7 +99,6 @@ struct SNZBDownloadRequest
|
||||
{
|
||||
SNZBRequestBase m_MessageBase; // Must be the first in the struct
|
||||
char m_szFilename[NZBREQUESTFILENAMESIZE]; // Name of nzb-file, may contain full path (local path on client) or only filename
|
||||
char m_szCategory[NZBREQUESTFILENAMESIZE]; // Category, be empty
|
||||
int32_t m_bAddFirst; // 1 - add file to the top of download queue
|
||||
int32_t m_iTrailingDataLength; // Length of nzb-file in bytes
|
||||
//char m_szContent[m_iTrailingDataLength]; // variable sized
|
||||
@@ -158,66 +130,37 @@ struct SNZBListResponse
|
||||
int32_t m_iRemainingSizeHi; // Remaining size in bytes, High 32-bits of 64-bit value
|
||||
int32_t m_iDownloadRate; // Current download speed, in Bytes pro Second
|
||||
int32_t m_iDownloadLimit; // Current download limit, in Bytes pro Second
|
||||
int32_t m_bDownloadPaused; // 1 - download queue is currently in paused-state
|
||||
int32_t m_bDownload2Paused; // 1 - download queue is currently in paused-state (second pause-register)
|
||||
int32_t m_bDownloadStandBy; // 0 - there are currently downloads running, 1 - no downloads in progress (download queue paused or all download jobs completed)
|
||||
int32_t m_bPostPaused; // 1 - post-processor queue is currently in paused-state
|
||||
int32_t m_bScanPaused; // 1 - scaning of incoming directory is currently in paused-state
|
||||
int32_t m_bServerPaused; // 1 - server is currently in paused-state
|
||||
int32_t m_iThreadCount; // Number of threads running
|
||||
int32_t m_iPostJobCount; // Number of jobs in post-processor queue (including current job)
|
||||
int32_t m_iUpTimeSec; // Server up time in seconds
|
||||
int32_t m_iDownloadTimeSec; // Server download time in seconds (up_time - standby_time)
|
||||
int32_t m_iDownloadedBytesLo; // Amount of data downloaded since server start, Low 32-bits of 64-bit value
|
||||
int32_t m_iDownloadedBytesHi; // Amount of data downloaded since server start, High 32-bits of 64-bit value
|
||||
int32_t m_iNrTrailingNZBEntries; // Number of List-NZB-entries, following to this structure
|
||||
int32_t m_iNrTrailingPPPEntries; // Number of List-PPP-entries, following to this structure
|
||||
int32_t m_iNrTrailingFileEntries; // Number of List-File-entries, following to this structure
|
||||
int32_t m_iTrailingDataLength; // Length of all List-entries, following to this structure
|
||||
// SNZBListResponseEntry m_NZBEntries[m_iNrTrailingNZBEntries] // variable sized
|
||||
// SNZBListResponseEntry m_PPPEntries[m_iNrTrailingPPPEntries] // variable sized
|
||||
// SNZBListResponseEntry m_FileEntries[m_iNrTrailingFileEntries] // variable sized
|
||||
int32_t m_bServerStandBy; // 0 - there are currently downloads running, 1 - no downloads in progress (server paused or all jobs completed)
|
||||
int32_t m_iNrTrailingEntries; // Number of List-entries, following to this structure
|
||||
int32_t m_iTrailingDataLength; // Length of all List-entries, following to this structure
|
||||
// SNZBListResponseEntry m_Entries[m_iNrTrailingEntries] // variable sized
|
||||
};
|
||||
|
||||
// A list response nzb entry
|
||||
struct SNZBListResponseNZBEntry
|
||||
{
|
||||
int32_t m_iSizeLo; // Size of all files in bytes, Low 32-bits of 64-bit value
|
||||
int32_t m_iSizeHi; // Size of all files in bytes, High 32-bits of 64-bit value
|
||||
int32_t m_iFilenameLen; // 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_iCategoryLen; // Length of Category-string (m_szCategory), following to this record
|
||||
int32_t m_iQueuedFilenameLen; // Length of queued file name (m_szQueuedFilename), following to this record
|
||||
//char m_szFilename[m_iFilenameLen]; // variable sized
|
||||
//char m_szDestDir[m_iDestDirLen]; // variable sized
|
||||
//char m_szCategory[m_iCategoryLen]; // variable sized
|
||||
//char m_szQueuedFilename[m_iQueuedFilenameLen]; // variable sized
|
||||
};
|
||||
|
||||
// A list response pp-parameter entry
|
||||
struct SNZBListResponsePPPEntry
|
||||
{
|
||||
int32_t m_iNZBIndex; // Index of NZB-Entry in m_NZBEntries-list
|
||||
int32_t m_iNameLen; // Length of Name-string (m_szName), following to this record
|
||||
int32_t m_iValueLen; // Length of Value-string (m_szValue), following to this record
|
||||
//char m_szName[m_iNameLen]; // variable sized
|
||||
//char m_szValue[m_iValueLen]; // variable sized
|
||||
};
|
||||
|
||||
// A list response file entry
|
||||
struct SNZBListResponseFileEntry
|
||||
// A list response entry
|
||||
struct SNZBListResponseEntry
|
||||
{
|
||||
int32_t m_iID; // Entry-ID
|
||||
int32_t m_iNZBIndex; // Index of NZB-Entry in m_NZBEntries-list
|
||||
int32_t m_iFileSizeLo; // Filesize in bytes, Low 32-bits of 64-bit value
|
||||
int32_t m_iFileSizeHi; // Filesize in bytes, High 32-bits of 64-bit value
|
||||
int32_t m_iRemainingSizeLo; // Remaining size in bytes, Low 32-bits of 64-bit value
|
||||
int32_t m_iRemainingSizeHi; // Remaining size in bytes, High 32-bits of 64-bit value
|
||||
int32_t m_bPaused; // 1 - file is paused
|
||||
int32_t m_bFilenameConfirmed; // 1 - Filename confirmed (read from article body), 0 - Filename parsed from subject (can be changed after reading of article)
|
||||
int32_t m_iNZBFilenameLen; // Length of NZBFileName-string (m_szNZBFilename), following to this record
|
||||
int32_t m_iSubjectLen; // Length of Subject-string (m_szSubject), following to this record
|
||||
int32_t m_iFilenameLen; // Length of Filename-string (m_szFilename), following to this record
|
||||
int32_t m_iDestDirLen; // Length of DestDir-string (m_szDestDir), following to this record
|
||||
//char m_szNZBFilename[m_iNZBFilenameLen]; // variable sized, may contain full path (local path on client) or only filename
|
||||
//char m_szSubject[m_iSubjectLen]; // variable sized
|
||||
//char m_szFilename[m_iFilenameLen]; // variable sized
|
||||
//char m_szDestDir[m_iDestDirLen]; // variable sized
|
||||
};
|
||||
|
||||
// A log request
|
||||
@@ -253,7 +196,6 @@ struct SNZBPauseUnpauseRequest
|
||||
{
|
||||
SNZBRequestBase m_MessageBase; // Must be the first in the struct
|
||||
int32_t m_bPause; // 1 - server must be paused, 0 - server must be unpaused
|
||||
int32_t m_iAction; // Action to be executed, see enum eRemotePauseUnpauseAction
|
||||
};
|
||||
|
||||
// A Pause/Unpause response
|
||||
@@ -285,14 +227,12 @@ struct SNZBSetDownloadRateResponse
|
||||
struct SNZBEditQueueRequest
|
||||
{
|
||||
SNZBRequestBase m_MessageBase; // Must be the first in the struct
|
||||
int32_t m_iAction; // Action to be executed, see enum eRemoteEditAction
|
||||
int32_t m_iAction; // Action to be executed, see enum in NZBMessageRequest-namespace
|
||||
int32_t m_iOffset; // Offset to move (for m_iAction = 0)
|
||||
int32_t m_bSmartOrder; // For Move-Actions: 0 - execute action for each ID in order they are placed in array;
|
||||
// 1 - smart execute to ensure that the relative order of all affected IDs are not changed.
|
||||
int32_t m_iNrTrailingEntries; // Number of ID-entries, following to this structure
|
||||
int32_t m_iTextLen; // Length of Text-string (m_szText), following to this record
|
||||
int32_t m_iTrailingDataLength; // Length of Text-string and all ID-entries, following to this structure
|
||||
//char m_szText[m_iTextLen]; // variable sized
|
||||
int32_t m_iTrailingDataLength; // Length of all ID-entries, following to this structure
|
||||
//int32_t m_iIDs[m_iNrTrailingEntries]; // variable sized array of IDs. For File-Actions - ID of file, for Group-Actions - ID of any file belonging to group
|
||||
};
|
||||
|
||||
@@ -396,7 +336,7 @@ struct SNZBWriteLogRequest
|
||||
//char m_szText[m_iTrailingDataLength]; // variable sized
|
||||
};
|
||||
|
||||
// Write log response
|
||||
// Write log response
|
||||
struct SNZBWriteLogResponse
|
||||
{
|
||||
SNZBResponseBase m_MessageBase; // Must be the first in the struct
|
||||
@@ -405,55 +345,4 @@ struct SNZBWriteLogResponse
|
||||
//char m_szText[m_iTrailingDataLength]; // variable sized
|
||||
};
|
||||
|
||||
// Scan nzb directory request
|
||||
struct SNZBScanRequest
|
||||
{
|
||||
SNZBRequestBase m_MessageBase; // Must be the first in the struct
|
||||
};
|
||||
|
||||
// Scan nzb directory response
|
||||
struct SNZBScanResponse
|
||||
{
|
||||
SNZBResponseBase m_MessageBase; // Must be the first in the struct
|
||||
int32_t m_bSuccess; // 0 - command failed, 1 - command executed successfully
|
||||
int32_t m_iTrailingDataLength; // Length of Text-string (m_szText), following to this record
|
||||
//char m_szText[m_iTrailingDataLength]; // variable sized
|
||||
};
|
||||
|
||||
// A history request
|
||||
struct SNZBHistoryRequest
|
||||
{
|
||||
SNZBRequestBase m_MessageBase; // Must be the first in the struct
|
||||
};
|
||||
|
||||
// A history response
|
||||
struct SNZBHistoryResponse
|
||||
{
|
||||
SNZBResponseBase m_MessageBase; // Must be the first in the struct
|
||||
int32_t m_iEntrySize; // Size of the SNZBHistoryResponseEntry-struct
|
||||
int32_t m_iNrTrailingEntries; // Number of History-entries, following to this structure
|
||||
int32_t m_iTrailingDataLength; // Length of all History-entries, following to this structure
|
||||
// SNZBHistoryResponseEntry m_NZBEntries[m_iNrTrailingNZBEntries] // variable sized
|
||||
};
|
||||
|
||||
// A list response nzb entry
|
||||
struct SNZBHistoryResponseEntry
|
||||
{
|
||||
int32_t m_iID; // NZBID
|
||||
int32_t m_tTime; // When the item was added to history. time since the Epoch (00:00:00 UTC, January 1, 1970), measured in seconds.
|
||||
int32_t m_iSizeLo; // Size of all files in bytes, Low 32-bits of 64-bit value
|
||||
int32_t m_iSizeHi; // Size of all files in bytes, High 32-bits of 64-bit value
|
||||
int32_t m_iFileCount; // Initial number of files included in NZB-file
|
||||
int32_t m_iParStatus; // See NZBInfo::EParStatus
|
||||
int32_t m_iScriptStatus; // See NZBInfo::EScriptStatus
|
||||
int32_t m_iFilenameLen; // 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_iCategoryLen; // Length of Category-string (m_szCategory), following to this record
|
||||
int32_t m_iQueuedFilenameLen; // Length of queued file name (m_szQueuedFilename), following to this record
|
||||
//char m_szFilename[m_iFilenameLen]; // variable sized
|
||||
//char m_szDestDir[m_iDestDirLen]; // variable sized
|
||||
//char m_szCategory[m_iCategoryLen]; // variable sized
|
||||
//char m_szQueuedFilename[m_iQueuedFilenameLen]; // variable sized
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007-2010 Andrei Prygounkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007 Andrei Prygounkov <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
|
||||
@@ -60,18 +60,6 @@
|
||||
#undef erase
|
||||
#endif
|
||||
|
||||
#ifndef WIN32
|
||||
// curses.h on Solaris declares "clear()" via DEFINE. That causes problems, because
|
||||
// it also affects calls to deque's method "clear()", producing compiler errors.
|
||||
// We use function "curses_clear()" to call macro "clear" of curses, then
|
||||
// undefine macro "clear".
|
||||
void curses_clear()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
#undef clear
|
||||
#endif
|
||||
|
||||
extern Options* g_pOptions;
|
||||
extern void ExitProc();
|
||||
|
||||
@@ -143,6 +131,8 @@ NCursesFrontend::NCursesFrontend()
|
||||
m_bLastPausePars = false;
|
||||
m_szHint = NULL;
|
||||
|
||||
m_groupQueue.clear();
|
||||
|
||||
// Setup curses
|
||||
#ifdef WIN32
|
||||
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
@@ -316,7 +306,7 @@ void NCursesFrontend::Update(int iKey)
|
||||
}
|
||||
|
||||
//------------------------------------------
|
||||
// Print Current NZBInfoList
|
||||
// Print Current NZBQueue
|
||||
//------------------------------------------
|
||||
if (m_iQueueWinHeight > 0)
|
||||
{
|
||||
@@ -361,7 +351,7 @@ void NCursesFrontend::CalcWindowSizes()
|
||||
m_pOldScreenBuffer = (CHAR_INFO*)realloc(m_pOldScreenBuffer, m_iScreenBufferSize);
|
||||
memset(m_pOldScreenBuffer, 0, m_iScreenBufferSize);
|
||||
#else
|
||||
curses_clear();
|
||||
clear();
|
||||
#endif
|
||||
m_iScreenHeight = iNrRows;
|
||||
m_iScreenWidth = iNrColumns;
|
||||
@@ -399,7 +389,7 @@ int NCursesFrontend::CalcQueueSize()
|
||||
else
|
||||
{
|
||||
DownloadQueue* pDownloadQueue = LockQueue();
|
||||
int iQueueSize = pDownloadQueue->GetFileQueue()->size();
|
||||
int iQueueSize = pDownloadQueue->size();
|
||||
UnlockQueue();
|
||||
return iQueueSize;
|
||||
}
|
||||
@@ -614,7 +604,7 @@ void NCursesFrontend::PrintStatus()
|
||||
timeString[0] = '\0';
|
||||
|
||||
float fCurrentDownloadSpeed = m_bStandBy ? 0 : m_fCurrentDownloadSpeed;
|
||||
if (fCurrentDownloadSpeed > 0.0 && !(m_bPauseDownload || m_bPauseDownload2))
|
||||
if (fCurrentDownloadSpeed > 0.0 && !m_bPause)
|
||||
{
|
||||
long long remain_sec = (long long)(m_lRemainingSize / (fCurrentDownloadSpeed * 1024));
|
||||
int h = (int)(remain_sec / 3600);
|
||||
@@ -643,15 +633,11 @@ void NCursesFrontend::PrintStatus()
|
||||
szPostStatus[0] = 0;
|
||||
}
|
||||
|
||||
float fAverageSpeed = (float)(Util::Int64ToFloat(m_iDnTimeSec > 0 ? m_iAllBytes / m_iDnTimeSec : 0) / 1024.0);
|
||||
float fAverageSpeed = Util::Int64ToFloat(m_iDnTimeSec > 0 ? m_iAllBytes / m_iDnTimeSec / 1024 : 0);
|
||||
|
||||
snprintf(tmp, MAX_SCREEN_WIDTH, " %d threads, %.*f KB/s, %.2f MB remaining%s%s%s%s%s, Avg. %.*f KB/s",
|
||||
m_iThreadCount, (fCurrentDownloadSpeed >= 10 ? 0 : 1), fCurrentDownloadSpeed,
|
||||
(float)(Util::Int64ToFloat(m_lRemainingSize) / 1024.0 / 1024.0), timeString, szPostStatus,
|
||||
m_bPauseDownload || m_bPauseDownload2 ? (m_bStandBy ? ", Paused" : ", Pausing") : "",
|
||||
m_bPauseDownload || m_bPauseDownload2 ?
|
||||
(m_bPauseDownload && m_bPauseDownload2 ? " (+2)" : m_bPauseDownload2 ? " (2)" : "") : "",
|
||||
szDownloadLimit, (fAverageSpeed >= 10 ? 0 : 1), fAverageSpeed);
|
||||
snprintf(tmp, MAX_SCREEN_WIDTH, " %d threads, %.0f KB/s, %.2f MB remaining%s%s%s%s, Avg. %.0f KB/s",
|
||||
m_iThreadCount, fCurrentDownloadSpeed, (float)(Util::Int64ToFloat(m_lRemainingSize) / 1024.0 / 1024.0), timeString,
|
||||
szPostStatus, m_bPause ? (m_bStandBy ? ", Paused" : ", Pausing") : "", szDownloadLimit, fAverageSpeed);
|
||||
tmp[MAX_SCREEN_WIDTH - 1] = '\0';
|
||||
PlotLine(tmp, iStatusRow, 0, NCURSES_COLORPAIR_STATUS);
|
||||
}
|
||||
@@ -752,7 +738,7 @@ void NCursesFrontend::PrintFileQueue()
|
||||
int iLineNr = m_iQueueWinTop;
|
||||
|
||||
DownloadQueue* pDownloadQueue = LockQueue();
|
||||
if (pDownloadQueue->GetFileQueue()->empty())
|
||||
if (pDownloadQueue->empty())
|
||||
{
|
||||
char szBuffer[MAX_SCREEN_WIDTH];
|
||||
snprintf(szBuffer, sizeof(szBuffer), "%s Files for downloading", m_bUseColor ? "" : "*** ");
|
||||
@@ -767,7 +753,7 @@ void NCursesFrontend::PrintFileQueue()
|
||||
long long lPaused = 0;
|
||||
int iPausedFiles = 0;
|
||||
int i = 0;
|
||||
for (FileQueue::iterator it = pDownloadQueue->GetFileQueue()->begin(); it != pDownloadQueue->GetFileQueue()->end(); it++, i++)
|
||||
for (DownloadQueue::iterator it = pDownloadQueue->begin(); it != pDownloadQueue->end(); it++, i++)
|
||||
{
|
||||
FileInfo* pFileInfo = *it;
|
||||
|
||||
@@ -785,15 +771,14 @@ void NCursesFrontend::PrintFileQueue()
|
||||
}
|
||||
|
||||
char szRemaining[20];
|
||||
Util::FormatFileSize(szRemaining, sizeof(szRemaining), lRemaining);
|
||||
FormatFileSize(szRemaining, sizeof(szRemaining), lRemaining);
|
||||
|
||||
char szUnpaused[20];
|
||||
Util::FormatFileSize(szUnpaused, sizeof(szUnpaused), lRemaining - lPaused);
|
||||
FormatFileSize(szUnpaused, sizeof(szUnpaused), lRemaining - lPaused);
|
||||
|
||||
char szBuffer[MAX_SCREEN_WIDTH];
|
||||
snprintf(szBuffer, sizeof(szBuffer), " %sFiles for downloading - %i / %i files in queue - %s / %s",
|
||||
m_bUseColor ? "" : "*** ", pDownloadQueue->GetFileQueue()->size(),
|
||||
pDownloadQueue->GetFileQueue()->size() - iPausedFiles, szRemaining, szUnpaused);
|
||||
m_bUseColor ? "" : "*** ", pDownloadQueue->size(), pDownloadQueue->size() - iPausedFiles, szRemaining, szUnpaused);
|
||||
szBuffer[MAX_SCREEN_WIDTH - 1] = '\0';
|
||||
PrintTopHeader(szBuffer, m_iQueueWinTop, true);
|
||||
}
|
||||
@@ -848,6 +833,27 @@ void NCursesFrontend::PrintFilename(FileInfo * pFileInfo, int iRow, bool bSelect
|
||||
PlotLine(szBuffer, iRow, 0, color);
|
||||
}
|
||||
|
||||
void NCursesFrontend::FormatFileSize(char * szBuffer, int iBufLen, long long lFileSize)
|
||||
{
|
||||
if (lFileSize > 1024 * 1024 * 1024)
|
||||
{
|
||||
snprintf(szBuffer, iBufLen, "%.2f GB", (float)(Util::Int64ToFloat(lFileSize) / 1024 / 1024 / 1024));
|
||||
}
|
||||
else if (lFileSize > 1024 * 1024)
|
||||
{
|
||||
snprintf(szBuffer, iBufLen, "%.2f MB", (float)(Util::Int64ToFloat(lFileSize) / 1024 / 1024));
|
||||
}
|
||||
else if (lFileSize > 1024)
|
||||
{
|
||||
snprintf(szBuffer, iBufLen, "%.2f KB", (float)(Util::Int64ToFloat(lFileSize) / 1024));
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(szBuffer, iBufLen, "%i", (int)lFileSize);
|
||||
}
|
||||
szBuffer[iBufLen - 1] = '\0';
|
||||
}
|
||||
|
||||
void NCursesFrontend::PrintTopHeader(char* szHeader, int iLineNr, bool bUpTime)
|
||||
{
|
||||
char szBuffer[MAX_SCREEN_WIDTH];
|
||||
@@ -924,9 +930,8 @@ void NCursesFrontend::PrintGroupQueue()
|
||||
else
|
||||
{
|
||||
iLineNr++;
|
||||
|
||||
ResetColWidths();
|
||||
int iCalcLineNr = iLineNr;
|
||||
long long lRemaining = 0;
|
||||
long long lPaused = 0;
|
||||
int i = 0;
|
||||
for (GroupQueue::iterator it = pGroupQueue->begin(); it != pGroupQueue->end(); it++, i++)
|
||||
{
|
||||
@@ -934,20 +939,7 @@ void NCursesFrontend::PrintGroupQueue()
|
||||
|
||||
if (i >= m_iQueueScrollOffset && i < m_iQueueScrollOffset + m_iQueueWinHeight -1)
|
||||
{
|
||||
PrintGroupname(pGroupInfo, iCalcLineNr++, false, true);
|
||||
}
|
||||
}
|
||||
|
||||
long long lRemaining = 0;
|
||||
long long lPaused = 0;
|
||||
i = 0;
|
||||
for (GroupQueue::iterator it = pGroupQueue->begin(); it != pGroupQueue->end(); it++, i++)
|
||||
{
|
||||
GroupInfo* pGroupInfo = *it;
|
||||
|
||||
if (i >= m_iQueueScrollOffset && i < m_iQueueScrollOffset + m_iQueueWinHeight -1)
|
||||
{
|
||||
PrintGroupname(pGroupInfo, iLineNr++, i == m_iSelectedQueueEntry, false);
|
||||
PrintGroupname(pGroupInfo, iLineNr++, i == m_iSelectedQueueEntry);
|
||||
}
|
||||
|
||||
lRemaining += pGroupInfo->GetRemainingSize();
|
||||
@@ -955,10 +947,10 @@ void NCursesFrontend::PrintGroupQueue()
|
||||
}
|
||||
|
||||
char szRemaining[20];
|
||||
Util::FormatFileSize(szRemaining, sizeof(szRemaining), lRemaining);
|
||||
FormatFileSize(szRemaining, sizeof(szRemaining), lRemaining);
|
||||
|
||||
char szUnpaused[20];
|
||||
Util::FormatFileSize(szUnpaused, sizeof(szUnpaused), lRemaining - lPaused);
|
||||
FormatFileSize(szUnpaused, sizeof(szUnpaused), lRemaining - lPaused);
|
||||
|
||||
char szBuffer[MAX_SCREEN_WIDTH];
|
||||
snprintf(szBuffer, sizeof(szBuffer), " %sNZBs for downloading - %i NZBs in queue - %s / %s",
|
||||
@@ -968,14 +960,7 @@ void NCursesFrontend::PrintGroupQueue()
|
||||
}
|
||||
}
|
||||
|
||||
void NCursesFrontend::ResetColWidths()
|
||||
{
|
||||
m_iColWidthFiles = 0;
|
||||
m_iColWidthTotal = 0;
|
||||
m_iColWidthLeft = 0;
|
||||
}
|
||||
|
||||
void NCursesFrontend::PrintGroupname(GroupInfo * pGroupInfo, int iRow, bool bSelected, bool bCalcColWidth)
|
||||
void NCursesFrontend::PrintGroupname(GroupInfo * pGroupInfo, int iRow, bool bSelected)
|
||||
{
|
||||
int color = 0;
|
||||
const char* Brace1 = "[";
|
||||
@@ -997,93 +982,26 @@ void NCursesFrontend::PrintGroupname(GroupInfo * pGroupInfo, int iRow, bool bSel
|
||||
long long lUnpausedRemainingSize = pGroupInfo->GetRemainingSize() - pGroupInfo->GetPausedSize();
|
||||
|
||||
char szRemaining[20];
|
||||
Util::FormatFileSize(szRemaining, sizeof(szRemaining), lUnpausedRemainingSize);
|
||||
FormatFileSize(szRemaining, sizeof(szRemaining), lUnpausedRemainingSize);
|
||||
|
||||
char szPaused[20];
|
||||
szPaused[0] = '\0';
|
||||
if (pGroupInfo->GetPausedSize() > 0)
|
||||
{
|
||||
char szPausedSize[20];
|
||||
FormatFileSize(szPausedSize, sizeof(szPausedSize), pGroupInfo->GetPausedSize());
|
||||
sprintf(szPaused, " + %s paused", szPausedSize);
|
||||
}
|
||||
|
||||
char szNZBNiceName[1024];
|
||||
pGroupInfo->GetNZBInfo()->GetNiceNZBName(szNZBNiceName, 1023);
|
||||
|
||||
char szBuffer[MAX_SCREEN_WIDTH];
|
||||
|
||||
// Format:
|
||||
// [id - id] Name Left-Files/Paused Total Left Time
|
||||
// [1-2] Nzb-name 999/999 999.99 MB 999.99 MB 00:00:00
|
||||
|
||||
int iNameLen = 0;
|
||||
if (bCalcColWidth)
|
||||
{
|
||||
iNameLen = m_iScreenWidth - 1 - 9 - 11 - 11 - 9;
|
||||
}
|
||||
else
|
||||
{
|
||||
iNameLen = m_iScreenWidth - 1 - m_iColWidthFiles - 2 - m_iColWidthTotal - 2 - m_iColWidthLeft - 2 - 9;
|
||||
}
|
||||
|
||||
bool bPrintFormatted = iNameLen > 20;
|
||||
|
||||
if (bPrintFormatted)
|
||||
{
|
||||
char szFiles[20];
|
||||
snprintf(szFiles, 20, "%i/%i", pGroupInfo->GetRemainingFileCount(), pGroupInfo->GetPausedFileCount());
|
||||
szFiles[20-1] = '\0';
|
||||
|
||||
char szTotal[20];
|
||||
Util::FormatFileSize(szTotal, sizeof(szTotal), pGroupInfo->GetNZBInfo()->GetSize());
|
||||
|
||||
char szNameWithIds[1024];
|
||||
snprintf(szNameWithIds, 1024, "%s%i-%i%s %s", Brace1, pGroupInfo->GetFirstID(), pGroupInfo->GetLastID(), Brace2, szNZBNiceName);
|
||||
szNameWithIds[iNameLen] = '\0';
|
||||
|
||||
char szTime[100];
|
||||
szTime[0] = '\0';
|
||||
float fCurrentDownloadSpeed = m_bStandBy ? 0 : m_fCurrentDownloadSpeed;
|
||||
if (pGroupInfo->GetPausedSize() > 0 && lUnpausedRemainingSize == 0)
|
||||
{
|
||||
snprintf(szTime, 100, "[paused]");
|
||||
Util::FormatFileSize(szRemaining, sizeof(szRemaining), pGroupInfo->GetRemainingSize());
|
||||
}
|
||||
else if (fCurrentDownloadSpeed > 0.0 && !(m_bPauseDownload || m_bPauseDownload2))
|
||||
{
|
||||
long long remain_sec = (long long)(lUnpausedRemainingSize / (fCurrentDownloadSpeed * 1024));
|
||||
int h = (int)(remain_sec / 3600);
|
||||
int m = (int)((remain_sec % 3600) / 60);
|
||||
int s = (int)(remain_sec % 60);
|
||||
if (h < 100)
|
||||
{
|
||||
snprintf(szTime, 100, "%.2d:%.2d:%.2d", h, m, s);
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(szTime, 100, "99:99:99");
|
||||
}
|
||||
}
|
||||
|
||||
if (bCalcColWidth)
|
||||
{
|
||||
int iColWidthFiles = strlen(szFiles);
|
||||
m_iColWidthFiles = iColWidthFiles > m_iColWidthFiles ? iColWidthFiles : m_iColWidthFiles;
|
||||
|
||||
int iColWidthTotal = strlen(szTotal);
|
||||
m_iColWidthTotal = iColWidthTotal > m_iColWidthTotal ? iColWidthTotal : m_iColWidthTotal;
|
||||
|
||||
int iColWidthLeft = strlen(szRemaining);
|
||||
m_iColWidthLeft = iColWidthLeft > m_iColWidthLeft ? iColWidthLeft : m_iColWidthLeft;
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(szBuffer, MAX_SCREEN_WIDTH, "%-*s %*s %*s %*s %8s", iNameLen, szNameWithIds, m_iColWidthFiles, szFiles, m_iColWidthTotal, szTotal, m_iColWidthLeft, szRemaining, szTime);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(szBuffer, MAX_SCREEN_WIDTH, "%s%i-%i%s %s", Brace1, pGroupInfo->GetFirstID(), pGroupInfo->GetLastID(), Brace2, szNZBNiceName);
|
||||
}
|
||||
|
||||
snprintf(szBuffer, MAX_SCREEN_WIDTH, "%s%i-%i%s %s (%i file%s, %s%s)", Brace1, pGroupInfo->GetFirstID(), pGroupInfo->GetLastID(), Brace2, szNZBNiceName,
|
||||
pGroupInfo->GetRemainingFileCount(), pGroupInfo->GetRemainingFileCount() > 1 ? "s" : "", szRemaining, szPaused);
|
||||
szBuffer[MAX_SCREEN_WIDTH - 1] = '\0';
|
||||
|
||||
if (!bCalcColWidth)
|
||||
{
|
||||
PlotLine(szBuffer, iRow, 0, color);
|
||||
}
|
||||
PlotLine(szBuffer, iRow, 0, color);
|
||||
}
|
||||
|
||||
void NCursesFrontend::PrepareGroupQueue()
|
||||
@@ -1091,7 +1009,7 @@ void NCursesFrontend::PrepareGroupQueue()
|
||||
m_groupQueue.clear();
|
||||
|
||||
DownloadQueue* pDownloadQueue = LockQueue();
|
||||
pDownloadQueue->BuildGroups(&m_groupQueue);
|
||||
GroupInfo::BuildGroups(pDownloadQueue, &m_groupQueue);
|
||||
UnlockQueue();
|
||||
}
|
||||
|
||||
@@ -1150,9 +1068,9 @@ bool NCursesFrontend::EditQueue(QueueEditor::EEditAction eAction, int iOffset)
|
||||
else
|
||||
{
|
||||
DownloadQueue* pDownloadQueue = LockQueue();
|
||||
if (m_iSelectedQueueEntry >= 0 && m_iSelectedQueueEntry < (int)pDownloadQueue->GetFileQueue()->size())
|
||||
if (m_iSelectedQueueEntry >= 0 && m_iSelectedQueueEntry < (int)pDownloadQueue->size())
|
||||
{
|
||||
FileInfo* pFileInfo = pDownloadQueue->GetFileQueue()->at(m_iSelectedQueueEntry);
|
||||
FileInfo* pFileInfo = (*pDownloadQueue)[m_iSelectedQueueEntry];
|
||||
ID = pFileInfo->GetID();
|
||||
if (eAction == QueueEditor::eaFilePause)
|
||||
{
|
||||
@@ -1275,9 +1193,9 @@ void NCursesFrontend::UpdateInput(int initialKey)
|
||||
// Key 'p' for pause
|
||||
if (!IsRemoteMode())
|
||||
{
|
||||
info(m_bPauseDownload || m_bPauseDownload2 ? "Unpausing download" : "Pausing download");
|
||||
info(m_bPause ? "Unpausing download" : "Pausing download");
|
||||
}
|
||||
ServerPauseUnpause(!(m_bPauseDownload || m_bPauseDownload2), m_bPauseDownload2 && !m_bPauseDownload);
|
||||
ServerPauseUnpause(!m_bPause);
|
||||
break;
|
||||
case '\'':
|
||||
ServerDumpDebug();
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
* This file if part of nzbget
|
||||
*
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007-2009 Andrei Prygounkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007 Andrei Prygounkov <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
|
||||
@@ -30,7 +30,6 @@
|
||||
#ifndef DISABLE_CURSES
|
||||
|
||||
#include <vector>
|
||||
#include <time.h>
|
||||
|
||||
#include "Frontend.h"
|
||||
#include "Log.h"
|
||||
@@ -65,9 +64,6 @@ private:
|
||||
GroupQueue m_groupQueue;
|
||||
char* m_szHint;
|
||||
time_t m_tStartHint;
|
||||
int m_iColWidthFiles;
|
||||
int m_iColWidthTotal;
|
||||
int m_iColWidthLeft;
|
||||
|
||||
// Inputting numbers
|
||||
int m_iInputNumberIndex;
|
||||
@@ -98,8 +94,7 @@ private:
|
||||
void PrintFileQueue();
|
||||
void PrintFilename(FileInfo* pFileInfo, int iRow, bool bSelected);
|
||||
void PrintGroupQueue();
|
||||
void ResetColWidths();
|
||||
void PrintGroupname(GroupInfo * pGroupInfo, int iRow, bool bSelected, bool bCalcColWidth);
|
||||
void PrintGroupname(GroupInfo * pGroupInfo, int iRow, bool bSelected);
|
||||
void PrepareGroupQueue();
|
||||
void PrintTopHeader(char* szHeader, int iLineNr, bool bUpTime);
|
||||
void ClearGroupQueue();
|
||||
@@ -110,6 +105,7 @@ private:
|
||||
void Update(int iKey);
|
||||
void SetCurrentQueueEntry(int iEntry);
|
||||
void CalcWindowSizes();
|
||||
void FormatFileSize(char* szBuffer, int iBufLen, long long lFileSize);
|
||||
void RefreshScreen();
|
||||
int ReadConsoleKey();
|
||||
int CalcQueueSize();
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007-2008 Andrei Prygounkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007 Andrei Prygounkov <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
|
||||
@@ -126,13 +126,13 @@ bool NNTPConnection::AuthInfoUser(int iRecur)
|
||||
char* answer = ReadLine(m_szLineBuf, CONNECTION_LINEBUFFER_SIZE, NULL);
|
||||
if (!answer)
|
||||
{
|
||||
ReportError("Authorization for %s failed: Connection closed by remote host.", m_pNetAddress->GetHost(), true, 0);
|
||||
ReportError("authorization for %s failed: Connection closed by remote host.", m_pNetAddress->GetHost(), 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!strncmp(answer, "281", 3))
|
||||
{
|
||||
debug("Authorization for %s successful", m_pNetAddress->GetHost());
|
||||
debug("authorization for %s successful", m_pNetAddress->GetHost());
|
||||
return true;
|
||||
}
|
||||
else if (!strncmp(answer, "381", 3))
|
||||
@@ -148,7 +148,7 @@ bool NNTPConnection::AuthInfoUser(int iRecur)
|
||||
|
||||
if (GetStatus() != csCancelled)
|
||||
{
|
||||
ReportErrorAnswer("Authorization for %s failed (Answer: %s)", answer);
|
||||
error("authorization for %s failed (Answer: %s)", m_pNetAddress->GetHost(), answer);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -169,12 +169,12 @@ bool NNTPConnection::AuthInfoPass(int iRecur)
|
||||
char* answer = ReadLine(m_szLineBuf, CONNECTION_LINEBUFFER_SIZE, NULL);
|
||||
if (!answer)
|
||||
{
|
||||
ReportError("Authorization for %s failed: Connection closed by remote host.", m_pNetAddress->GetHost(), true, 0);
|
||||
ReportError("authorization for %s failed: Connection closed by remote host.", m_pNetAddress->GetHost(), 0);
|
||||
return false;
|
||||
}
|
||||
else if (!strncmp(answer, "2", 1))
|
||||
{
|
||||
debug("Authorization for %s successful", m_pNetAddress->GetHost());
|
||||
debug("authorization for %s successful", m_pNetAddress->GetHost());
|
||||
return true;
|
||||
}
|
||||
else if (!strncmp(answer, "381", 3))
|
||||
@@ -186,7 +186,7 @@ bool NNTPConnection::AuthInfoPass(int iRecur)
|
||||
|
||||
if (GetStatus() != csCancelled)
|
||||
{
|
||||
ReportErrorAnswer("Authorization for %s failed (Answer: %s)", answer);
|
||||
error("authorization for %s failed (Answer: %s)", m_pNetAddress->GetHost(), answer);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -229,45 +229,34 @@ const char* NNTPConnection::JoinGroup(const char* grp)
|
||||
return answer;
|
||||
}
|
||||
|
||||
bool NNTPConnection::DoConnect()
|
||||
int NNTPConnection::DoConnect()
|
||||
{
|
||||
debug("Opening connection to %s", GetServer()->GetHost());
|
||||
bool res = Connection::DoConnect();
|
||||
if (!res)
|
||||
int res = Connection::DoConnect();
|
||||
if (res < 0)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
|
||||
#ifndef DISABLE_TLS
|
||||
if (GetNewsServer()->GetTLS())
|
||||
{
|
||||
if (!StartTLS())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
char* answer = DoReadLine(m_szLineBuf, CONNECTION_LINEBUFFER_SIZE, NULL);
|
||||
|
||||
if (!answer)
|
||||
{
|
||||
ReportError("Connection to %s failed: Connection closed by remote host.", m_pNetAddress->GetHost(), true, 0);
|
||||
return false;
|
||||
ReportError("Connection to %s failed: Connection closed by remote host.", m_pNetAddress->GetHost(), 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strncmp(answer, "2", 1))
|
||||
{
|
||||
ReportErrorAnswer("Connection to %s failed (Answer: %s)", answer);
|
||||
return false;
|
||||
error("Connection to %s failed. Answer: ", m_pNetAddress->GetHost(), answer);
|
||||
return -1;
|
||||
}
|
||||
|
||||
debug("Connection to %s established", GetServer()->GetHost());
|
||||
|
||||
return true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool NNTPConnection::DoDisconnect()
|
||||
int NNTPConnection::DoDisconnect()
|
||||
{
|
||||
if (m_eStatus == csConnected)
|
||||
{
|
||||
@@ -280,12 +269,3 @@ bool NNTPConnection::DoDisconnect()
|
||||
}
|
||||
return Connection::DoDisconnect();
|
||||
}
|
||||
|
||||
void NNTPConnection::ReportErrorAnswer(const char* szMsgPrefix, const char* szAnswer)
|
||||
{
|
||||
char szErrStr[1024];
|
||||
snprintf(szErrStr, 1024, szMsgPrefix, m_pNetAddress->GetHost(), szAnswer);
|
||||
szErrStr[1024-1] = '\0';
|
||||
|
||||
ReportError(szErrStr, NULL, false, 0);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007-2008 Andrei Prygounkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007 Andrei Prygounkov <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,14 +37,13 @@ private:
|
||||
char* m_szLineBuf;
|
||||
bool m_bAuthError;
|
||||
|
||||
virtual bool DoConnect();
|
||||
virtual bool DoDisconnect();
|
||||
virtual int DoConnect();
|
||||
virtual int DoDisconnect();
|
||||
void Clear();
|
||||
void ReportErrorAnswer(const char* szMsgPrefix, const char* szAnswer);
|
||||
|
||||
public:
|
||||
NNTPConnection(NewsServer* server);
|
||||
virtual ~NNTPConnection();
|
||||
~NNTPConnection();
|
||||
NewsServer* GetNewsServer() { return(NewsServer*)m_pNetAddress; }
|
||||
const char* Request(const char* req);
|
||||
bool Authenticate();
|
||||
|
||||
82
NZBFile.cpp
82
NZBFile.cpp
@@ -41,7 +41,6 @@ using namespace MSXML;
|
||||
#else
|
||||
#include <libxml/parser.h>
|
||||
#include <libxml/xmlreader.h>
|
||||
#include <libxml/xmlerror.h>
|
||||
#endif
|
||||
|
||||
#include "nzbget.h"
|
||||
@@ -55,24 +54,7 @@ using namespace MSXML;
|
||||
extern Options* g_pOptions;
|
||||
extern DiskState* g_pDiskState;
|
||||
|
||||
#ifndef WIN32
|
||||
static void libxml_errorhandler(void *ebuf, const char *fmt, ...)
|
||||
{
|
||||
va_list argp;
|
||||
va_start(argp, fmt);
|
||||
char szErrMsg[1024];
|
||||
vsnprintf(szErrMsg, sizeof(szErrMsg), fmt, argp);
|
||||
szErrMsg[1024-1] = '\0';
|
||||
va_end(argp);
|
||||
|
||||
// remove trailing CRLF
|
||||
for (char* pend = szErrMsg + strlen(szErrMsg) - 1; pend >= szErrMsg && (*pend == '\n' || *pend == '\r' || *pend == ' '); pend--) *pend = '\0';
|
||||
|
||||
error("Error parsing nzb-file: %s", szErrMsg);
|
||||
}
|
||||
#endif
|
||||
|
||||
NZBFile::NZBFile(const char* szFileName, const char* szCategory)
|
||||
NZBFile::NZBFile(const char* szFileName)
|
||||
{
|
||||
debug("Creating NZBFile");
|
||||
|
||||
@@ -80,8 +62,7 @@ NZBFile::NZBFile(const char* szFileName, const char* szCategory)
|
||||
m_pNZBInfo = new NZBInfo();
|
||||
m_pNZBInfo->AddReference();
|
||||
m_pNZBInfo->SetFilename(szFileName);
|
||||
m_pNZBInfo->SetCategory(szCategory);
|
||||
m_pNZBInfo->BuildDestDirName();
|
||||
BuildDestDirName();
|
||||
|
||||
m_FileInfos.clear();
|
||||
}
|
||||
@@ -118,14 +99,14 @@ void NZBFile::DetachFileInfos()
|
||||
m_FileInfos.clear();
|
||||
}
|
||||
|
||||
NZBFile* NZBFile::CreateFromBuffer(const char* szFileName, const char* szCategory, const char* szBuffer, int iSize)
|
||||
NZBFile* NZBFile::CreateFromBuffer(const char* szFileName, const char* szBuffer, int iSize)
|
||||
{
|
||||
return Create(szFileName, szCategory, szBuffer, iSize, true);
|
||||
return Create(szFileName, szBuffer, iSize, true);
|
||||
}
|
||||
|
||||
NZBFile* NZBFile::CreateFromFile(const char* szFileName, const char* szCategory)
|
||||
NZBFile* NZBFile::CreateFromFile(const char* szFileName)
|
||||
{
|
||||
return Create(szFileName, szCategory, NULL, 0, false);
|
||||
return Create(szFileName, NULL, 0, false);
|
||||
}
|
||||
|
||||
void NZBFile::AddArticle(FileInfo* pFileInfo, ArticleInfo* pArticleInfo)
|
||||
@@ -264,6 +245,26 @@ void NZBFile::ParseSubject(FileInfo* pFileInfo)
|
||||
pFileInfo->MakeValidFilename();
|
||||
}
|
||||
|
||||
void NZBFile::BuildDestDirName()
|
||||
{
|
||||
char szBuffer[1024];
|
||||
|
||||
if (g_pOptions->GetAppendNZBDir())
|
||||
{
|
||||
char szNiceNZBName[1024];
|
||||
m_pNZBInfo->GetNiceNZBName(szNiceNZBName, 1024);
|
||||
snprintf(szBuffer, 1024, "%s%s", g_pOptions->GetDestDir(), szNiceNZBName);
|
||||
szBuffer[1024-1] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
strncpy(szBuffer, g_pOptions->GetDestDir(), 1024);
|
||||
szBuffer[1024-1] = '\0'; // trim the last slash, always returned by GetDestDir()
|
||||
}
|
||||
|
||||
m_pNZBInfo->SetDestDir(szBuffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the parsing of subject was correct
|
||||
*/
|
||||
@@ -309,7 +310,7 @@ void NZBFile::CheckFilenames()
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
NZBFile* NZBFile::Create(const char* szFileName, const char* szCategory, const char* szBuffer, int iSize, bool bFromBuffer)
|
||||
NZBFile* NZBFile::Create(const char* szFileName, const char* szBuffer, int iSize, bool bFromBuffer)
|
||||
{
|
||||
CoInitialize(NULL);
|
||||
|
||||
@@ -349,7 +350,7 @@ NZBFile* NZBFile::Create(const char* szFileName, const char* szCategory, const c
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NZBFile* pFile = new NZBFile(szFileName, szCategory);
|
||||
NZBFile* pFile = new NZBFile(szFileName);
|
||||
if (pFile->ParseNZB(doc))
|
||||
{
|
||||
pFile->CheckFilenames();
|
||||
@@ -400,13 +401,6 @@ bool NZBFile::ParseNZB(IUnknown* nzb)
|
||||
FileInfo* pFileInfo = new FileInfo();
|
||||
pFileInfo->SetSubject(subject);
|
||||
|
||||
attribute = node->Getattributes()->getNamedItem("date");
|
||||
if (attribute)
|
||||
{
|
||||
_bstr_t date(attribute->Gettext());
|
||||
pFileInfo->SetTime(atoi(date));
|
||||
}
|
||||
|
||||
MSXML::IXMLDOMNodeListPtr groupList = node->selectNodes("groups/group");
|
||||
for (int g = 0; g < groupList->Getlength(); g++)
|
||||
{
|
||||
@@ -453,10 +447,8 @@ bool NZBFile::ParseNZB(IUnknown* nzb)
|
||||
|
||||
#else
|
||||
|
||||
NZBFile* NZBFile::Create(const char* szFileName, const char* szCategory, const char* szBuffer, int iSize, bool bFromBuffer)
|
||||
NZBFile* NZBFile::Create(const char* szFileName, const char* szBuffer, int iSize, bool bFromBuffer)
|
||||
{
|
||||
xmlSetGenericErrorFunc(NULL, libxml_errorhandler);
|
||||
|
||||
xmlTextReaderPtr doc;
|
||||
if (bFromBuffer)
|
||||
{
|
||||
@@ -468,11 +460,10 @@ NZBFile* NZBFile::Create(const char* szFileName, const char* szCategory, const c
|
||||
}
|
||||
if (!doc)
|
||||
{
|
||||
error("Could not create XML-Reader");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NZBFile* pFile = new NZBFile(szFileName, szCategory);
|
||||
NZBFile* pFile = new NZBFile(szFileName);
|
||||
if (pFile->ParseNZB(doc))
|
||||
{
|
||||
pFile->CheckFilenames();
|
||||
@@ -524,12 +515,6 @@ bool NZBFile::ParseNZB(void* nzb)
|
||||
value = xmlTextReaderValue(node);
|
||||
pFileInfo->SetSubject((char*)value);
|
||||
}
|
||||
if (!strcmp("date",(char*)name))
|
||||
{
|
||||
xmlFree(value);
|
||||
value = xmlTextReaderValue(node);
|
||||
pFileInfo->SetTime(atoi((char*)value));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!strcmp("segment",(char*)name))
|
||||
@@ -579,11 +564,6 @@ bool NZBFile::ParseNZB(void* nzb)
|
||||
ret = xmlTextReaderRead(node);
|
||||
xmlFree(value);
|
||||
value = xmlTextReaderValue(node);
|
||||
if (!pFileInfo)
|
||||
{
|
||||
// error: bad nzb-file
|
||||
break;
|
||||
}
|
||||
pFileInfo->GetGroups()->push_back(strdup((char*)value));
|
||||
}
|
||||
}
|
||||
@@ -604,7 +584,7 @@ bool NZBFile::ParseNZB(void* nzb)
|
||||
}
|
||||
if (ret != 0)
|
||||
{
|
||||
error("Failed to parse nzb-file");
|
||||
error("Failed to parse nzb-file\n");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
10
NZBFile.h
10
NZBFile.h
@@ -41,10 +41,11 @@ private:
|
||||
NZBInfo* m_pNZBInfo;
|
||||
char* m_szFileName;
|
||||
|
||||
NZBFile(const char* szFileName, const char* szCategory);
|
||||
NZBFile(const char* szFileName);
|
||||
void AddArticle(FileInfo* pFileInfo, ArticleInfo* pArticleInfo);
|
||||
void AddFileInfo(FileInfo* pFileInfo);
|
||||
void ParseSubject(FileInfo* pFileInfo);
|
||||
void BuildDestDirName();
|
||||
void CheckFilenames();
|
||||
#ifdef WIN32
|
||||
bool ParseNZB(IUnknown* nzb);
|
||||
@@ -52,15 +53,14 @@ private:
|
||||
#else
|
||||
bool ParseNZB(void* nzb);
|
||||
#endif
|
||||
static NZBFile* Create(const char* szFileName, const char* szCategory, const char* szBuffer, int iSize, bool bFromBuffer);
|
||||
static NZBFile* Create(const char* szFileName, const char* szBuffer, int iSize, bool bFromBuffer);
|
||||
|
||||
public:
|
||||
virtual ~NZBFile();
|
||||
static NZBFile* CreateFromBuffer(const char* szFileName, const char* szCategory, const char* szBuffer, int iSize);
|
||||
static NZBFile* CreateFromFile(const char* szFileName, const char* szCategory);
|
||||
static NZBFile* CreateFromBuffer(const char* szFileName, const char* szBuffer, int iSize);
|
||||
static NZBFile* CreateFromFile(const char* szFileName);
|
||||
const char* GetFileName() const { return m_szFileName; }
|
||||
FileInfos* GetFileInfos() { return &m_FileInfos; }
|
||||
NZBInfo* GetNZBInfo() { return m_pNZBInfo; }
|
||||
void DetachFileInfos();
|
||||
|
||||
void LogDebugInfo();
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file if part of nzbget
|
||||
*
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007-2008 Andrei Prygounkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007 Andrei Prygounkov <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
|
||||
@@ -39,22 +39,20 @@
|
||||
#include "NewsServer.h"
|
||||
#include "Log.h"
|
||||
|
||||
NewsServer::NewsServer(const char* szHost, int iPort, const char* szUser, const char* szPass, bool bJoinGroup, bool bTLS, int iMaxConnections, int iLevel) : NetAddress(szHost, iPort)
|
||||
NewsServer::NewsServer(const char* host, int port, const char* user, const char* pass, int maxConnections, int level) : NetAddress(host, port)
|
||||
{
|
||||
m_szUser = NULL;
|
||||
m_szPassword = NULL;
|
||||
m_iLevel = iLevel;
|
||||
m_iMaxConnections = iMaxConnections;
|
||||
m_bJoinGroup = bJoinGroup;
|
||||
m_bTLS = bTLS;
|
||||
m_iLevel = level;
|
||||
m_iMaxConnections = maxConnections;
|
||||
|
||||
if (szUser)
|
||||
if (pass)
|
||||
{
|
||||
m_szUser = strdup(szUser);
|
||||
m_szPassword = strdup(pass);
|
||||
}
|
||||
if (szPass)
|
||||
if (user)
|
||||
{
|
||||
m_szPassword = strdup(szPass);
|
||||
m_szUser = strdup(user);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
18
NewsServer.h
18
NewsServer.h
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file if part of nzbget
|
||||
*
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007-2008 Andrei Prygounkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007 Andrei Prygounkov <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
|
||||
@@ -32,22 +32,18 @@
|
||||
class NewsServer : public NetAddress
|
||||
{
|
||||
private:
|
||||
char* m_szUser;
|
||||
char* m_szPassword;
|
||||
int m_iMaxConnections;
|
||||
int m_iLevel;
|
||||
bool m_bJoinGroup;
|
||||
bool m_bTLS;
|
||||
char* m_szUser;
|
||||
char* m_szPassword;
|
||||
int m_iMaxConnections;
|
||||
int m_iLevel;
|
||||
|
||||
public:
|
||||
NewsServer(const char* szHost, int iPort, const char* szUser, const char* szPass, bool bJoinGroup, bool bTLS, int iMaxConnections, int iLevel);
|
||||
NewsServer(const char* host, int port, const char* user, const char* pass, int maxConnections, int level);
|
||||
virtual ~NewsServer();
|
||||
const char* GetUser() { return m_szUser; }
|
||||
const char* GetPassword() { return m_szPassword; }
|
||||
int GetMaxConnections() { return m_iMaxConnections; }
|
||||
int GetLevel() { return m_iLevel; }
|
||||
int GetJoinGroup() { return m_bJoinGroup; }
|
||||
bool GetTLS() { return m_bTLS; }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
967
Options.cpp
967
Options.cpp
File diff suppressed because it is too large
Load Diff
134
Options.h
134
Options.h
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007-2010 Andrei Prygounkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007 Andrei Prygounkov <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
|
||||
@@ -28,7 +28,6 @@
|
||||
#define OPTIONS_H
|
||||
|
||||
#include <vector>
|
||||
#include "Thread.h"
|
||||
|
||||
class Options
|
||||
{
|
||||
@@ -37,9 +36,9 @@ public:
|
||||
{
|
||||
opClientNoOperation,
|
||||
opClientRequestDownload,
|
||||
opClientRequestListFiles,
|
||||
opClientRequestListGroups,
|
||||
opClientRequestListStatus,
|
||||
opClientRequestList,
|
||||
opClientRequestPause,
|
||||
opClientRequestUnpause,
|
||||
opClientRequestSetRate,
|
||||
opClientRequestDumpDebug,
|
||||
opClientRequestEditQueue,
|
||||
@@ -47,17 +46,7 @@ public:
|
||||
opClientRequestShutdown,
|
||||
opClientRequestVersion,
|
||||
opClientRequestPostQueue,
|
||||
opClientRequestWriteLog,
|
||||
opClientRequestScan,
|
||||
opClientRequestDownloadPause,
|
||||
opClientRequestDownloadUnpause,
|
||||
opClientRequestDownload2Pause,
|
||||
opClientRequestDownload2Unpause,
|
||||
opClientRequestPostPause,
|
||||
opClientRequestPostUnpause,
|
||||
opClientRequestScanPause,
|
||||
opClientRequestScanUnpause,
|
||||
opClientRequestHistory
|
||||
opClientRequestWriteLog
|
||||
};
|
||||
enum EMessageTarget
|
||||
{
|
||||
@@ -78,40 +67,27 @@ public:
|
||||
lpOne,
|
||||
lpAll
|
||||
};
|
||||
enum EScriptLogKind
|
||||
|
||||
enum EPostLogKind
|
||||
{
|
||||
slNone,
|
||||
slDetail,
|
||||
slInfo,
|
||||
slWarning,
|
||||
slError,
|
||||
slDebug
|
||||
plNone,
|
||||
plDetail,
|
||||
plInfo,
|
||||
plWarning,
|
||||
plError,
|
||||
plDebug
|
||||
};
|
||||
|
||||
class OptEntry
|
||||
{
|
||||
private:
|
||||
char* m_szName;
|
||||
char* m_szValue;
|
||||
|
||||
void SetName(const char* szName);
|
||||
void SetValue(const char* szValue);
|
||||
|
||||
friend class Options;
|
||||
|
||||
public:
|
||||
OptEntry();
|
||||
~OptEntry();
|
||||
const char* GetName() { return m_szName; }
|
||||
const char* GetValue() { return m_szValue; }
|
||||
};
|
||||
|
||||
typedef std::vector<OptEntry*> OptEntries;
|
||||
|
||||
private:
|
||||
OptEntries m_OptEntries;
|
||||
struct OptEntry
|
||||
{
|
||||
char* name;
|
||||
char* value;
|
||||
};
|
||||
|
||||
std::vector< struct OptEntry > optEntries;
|
||||
|
||||
bool m_bConfigInitialized;
|
||||
Mutex m_mutexOptEntries;
|
||||
|
||||
// Options
|
||||
char* m_szConfigFilename;
|
||||
@@ -130,7 +106,6 @@ private:
|
||||
int m_iConnectionTimeout;
|
||||
int m_iTerminateTimeout;
|
||||
bool m_bAppendNZBDir;
|
||||
bool m_bAppendCategoryDir;
|
||||
bool m_bContinuePartial;
|
||||
bool m_bRenameBroken;
|
||||
int m_iRetries;
|
||||
@@ -152,7 +127,6 @@ private:
|
||||
bool m_bParCheck;
|
||||
bool m_bParRepair;
|
||||
char* m_szPostProcess;
|
||||
char* m_szNZBProcess;
|
||||
bool m_bStrictParName;
|
||||
bool m_bNoConfig;
|
||||
int m_iUMask;
|
||||
@@ -169,17 +143,8 @@ private:
|
||||
int m_iNzbDirFileAge;
|
||||
bool m_bParCleanupQueue;
|
||||
int m_iDiskSpace;
|
||||
EScriptLogKind m_eProcessLogKind;
|
||||
EPostLogKind m_ePostLogKind;
|
||||
bool m_bAllowReProcess;
|
||||
bool m_bTLS;
|
||||
bool m_bDumpCore;
|
||||
bool m_bParPauseQueue;
|
||||
bool m_bPostPauseQueue;
|
||||
bool m_bNzbCleanupDisk;
|
||||
bool m_bDeleteCleanupDisk;
|
||||
bool m_bMergeNzb;
|
||||
int m_iParTimeLimit;
|
||||
int m_iKeepHistory;
|
||||
|
||||
// Parsed command-line parameters
|
||||
bool m_bServerMode;
|
||||
@@ -189,22 +154,16 @@ private:
|
||||
int m_iEditQueueOffset;
|
||||
int* m_pEditQueueIDList;
|
||||
int m_iEditQueueIDCount;
|
||||
char* m_szEditQueueText;
|
||||
char* m_szArgFilename;
|
||||
char* m_szCategory;
|
||||
char* m_szLastArg;
|
||||
bool m_bPrintOptions;
|
||||
bool m_bAddTop;
|
||||
float m_fSetRate;
|
||||
int m_iLogLines;
|
||||
int m_iWriteLogKind;
|
||||
bool m_bTestBacktrace;
|
||||
|
||||
// Current state
|
||||
bool m_bPauseDownload;
|
||||
bool m_bPauseDownload2;
|
||||
bool m_bPausePostProcess;
|
||||
bool m_bPauseScan;
|
||||
bool m_bPause;
|
||||
float m_fDownloadRate;
|
||||
EClientOperation m_eClientOperation;
|
||||
|
||||
@@ -214,29 +173,24 @@ private:
|
||||
void InitOptions();
|
||||
void InitFileArg(int argc, char* argv[]);
|
||||
void InitServers();
|
||||
void InitScheduler();
|
||||
void CheckOptions();
|
||||
void PrintUsage(char* com);
|
||||
void Dump();
|
||||
int ParseOptionValue(const char* OptName, int argc, const char* argn[], const int argv[]);
|
||||
OptEntry* FindOption(const char* optname);
|
||||
const char* GetOption(const char* optname);
|
||||
void DelOption(const char* optname);
|
||||
void SetOption(const char* optname, const char* value);
|
||||
bool SetOptionString(const char* option);
|
||||
bool ValidateOptionName(const char* optname);
|
||||
void LoadConfig(const char* configfile);
|
||||
void CheckDir(char** dir, const char* szOptionName, bool bAllowEmpty);
|
||||
void CheckDir(char** dir, const char* szOptionName);
|
||||
void ParseFileIDList(int argc, char* argv[], int optind);
|
||||
bool ParseTime(const char** pTime, int* pHours, int* pMinutes);
|
||||
bool ParseWeekDays(const char* szWeekDays, int* pWeekDaysBits);
|
||||
|
||||
public:
|
||||
Options(int argc, char* argv[]);
|
||||
~Options();
|
||||
|
||||
// Options
|
||||
OptEntries* LockOptEntries();
|
||||
void UnlockOptEntries();
|
||||
const char* GetDestDir() { return m_szDestDir; }
|
||||
const char* GetTempDir() { return m_szTempDir; }
|
||||
const char* GetQueueDir() { return m_szQueueDir; }
|
||||
@@ -252,29 +206,27 @@ public:
|
||||
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* GetServerIP() { return m_szServerIP; }
|
||||
const char* GetServerPassword() { return m_szServerPassword; }
|
||||
char* GetServerIP() { return m_szServerIP; }
|
||||
char* GetServerPassword() { return m_szServerPassword; }
|
||||
int GetServerPort() { return m_szServerPort; }
|
||||
const char* GetLockFile() { return m_szLockFile; }
|
||||
const char* GetDaemonUserName() { return m_szDaemonUserName; }
|
||||
char* GetLockFile() { return m_szLockFile; }
|
||||
char* GetDaemonUserName() { return m_szDaemonUserName; }
|
||||
EOutputMode GetOutputMode() { return m_eOutputMode; }
|
||||
bool GetReloadQueue() { return m_bReloadQueue; }
|
||||
bool GetReloadPostQueue() { return m_bReloadPostQueue; }
|
||||
int GetLogBufferSize() { return m_iLogBufferSize; }
|
||||
bool GetCreateLog() { return m_bCreateLog; }
|
||||
const char* GetLogFile() { return m_szLogFile; }
|
||||
char* GetLogFile() { return m_szLogFile; }
|
||||
ELoadPars GetLoadPars() { return m_eLoadPars; }
|
||||
bool GetParCheck() { return m_bParCheck; }
|
||||
bool GetParRepair() { return m_bParRepair; }
|
||||
const char* GetPostProcess() { return m_szPostProcess; }
|
||||
const char* GetNZBProcess() { return m_szNZBProcess; }
|
||||
bool GetStrictParName() { return m_bStrictParName; }
|
||||
int GetUMask() { return m_iUMask; }
|
||||
int GetUpdateInterval() {return m_iUpdateInterval; }
|
||||
@@ -290,17 +242,8 @@ public:
|
||||
int GetNzbDirFileAge() { return m_iNzbDirFileAge; }
|
||||
bool GetParCleanupQueue() { return m_bParCleanupQueue; }
|
||||
int GetDiskSpace() { return m_iDiskSpace; }
|
||||
EScriptLogKind GetProcessLogKind() { return m_eProcessLogKind; }
|
||||
EPostLogKind GetPostLogKind() { return m_ePostLogKind; }
|
||||
bool GetAllowReProcess() { return m_bAllowReProcess; }
|
||||
bool GetTLS() { return m_bTLS; }
|
||||
bool GetDumpCore() { return m_bDumpCore; }
|
||||
bool GetParPauseQueue() { return m_bParPauseQueue; }
|
||||
bool GetPostPauseQueue() { return m_bPostPauseQueue; }
|
||||
bool GetNzbCleanupDisk() { return m_bNzbCleanupDisk; }
|
||||
bool GetDeleteCleanupDisk() { return m_bDeleteCleanupDisk; }
|
||||
bool GetMergeNzb() { return m_bMergeNzb; }
|
||||
int GetParTimeLimit() { return m_iParTimeLimit; }
|
||||
int GetKeepHistory() { return m_iKeepHistory; }
|
||||
|
||||
// Parsed command-line parameters
|
||||
bool GetServerMode() { return m_bServerMode; }
|
||||
@@ -311,25 +254,16 @@ public:
|
||||
int GetEditQueueOffset() { return m_iEditQueueOffset; }
|
||||
int* GetEditQueueIDList() { return m_pEditQueueIDList; }
|
||||
int GetEditQueueIDCount() { return m_iEditQueueIDCount; }
|
||||
const char* GetEditQueueText() { return m_szEditQueueText; }
|
||||
const char* GetArgFilename() { return m_szArgFilename; }
|
||||
const char* GetCategory() { return m_szCategory; }
|
||||
const char* GetLastArg() { return m_szLastArg; }
|
||||
bool GetAddTop() { return m_bAddTop; }
|
||||
float GetSetRate() { return m_fSetRate; }
|
||||
int GetLogLines() { return m_iLogLines; }
|
||||
int GetWriteLogKind() { return m_iWriteLogKind; }
|
||||
bool GetTestBacktrace() { return m_bTestBacktrace; }
|
||||
|
||||
// Current state
|
||||
void SetPauseDownload(bool bPauseDownload) { m_bPauseDownload = bPauseDownload; }
|
||||
bool GetPauseDownload() const { return m_bPauseDownload; }
|
||||
void SetPauseDownload2(bool bPauseDownload2) { m_bPauseDownload2 = bPauseDownload2; }
|
||||
bool GetPauseDownload2() const { return m_bPauseDownload2; }
|
||||
void SetPausePostProcess(bool bPausePostProcess) { m_bPausePostProcess = bPausePostProcess; }
|
||||
bool GetPausePostProcess() const { return m_bPausePostProcess; }
|
||||
void SetPauseScan(bool bPauseScan) { m_bPauseScan = bPauseScan; }
|
||||
bool GetPauseScan() const { return m_bPauseScan; }
|
||||
void SetPause(bool bOnOff) { m_bPause = bOnOff; }
|
||||
bool GetPause() const { return m_bPause; }
|
||||
void SetDownloadRate(float fRate) { m_fDownloadRate = fRate; }
|
||||
float GetDownloadRate() const { return m_fDownloadRate; }
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2007-2009 Andrei Prygounkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2007 Andrei Prygounkov <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
|
||||
@@ -76,6 +76,7 @@ ParChecker::ParChecker()
|
||||
|
||||
m_eStatus = psUndefined;
|
||||
m_szParFilename = NULL;
|
||||
m_szNZBFilename = NULL;
|
||||
m_szInfoName = NULL;
|
||||
m_szErrMsg = NULL;
|
||||
m_szProgressLabel = (char*)malloc(1024);
|
||||
@@ -83,7 +84,6 @@ ParChecker::ParChecker()
|
||||
m_iStageProgress = 0;
|
||||
m_iExtraFiles = 0;
|
||||
m_bVerifyingExtraFiles = false;
|
||||
m_bCancelled = false;
|
||||
m_eStage = ptLoadingPars;
|
||||
m_QueuedParFiles.clear();
|
||||
}
|
||||
@@ -96,6 +96,10 @@ ParChecker::~ParChecker()
|
||||
{
|
||||
free(m_szParFilename);
|
||||
}
|
||||
if (m_szNZBFilename)
|
||||
{
|
||||
free(m_szNZBFilename);
|
||||
}
|
||||
if (m_szInfoName)
|
||||
{
|
||||
free(m_szInfoName);
|
||||
@@ -131,6 +135,15 @@ void ParChecker::SetInfoName(const char * szInfoName)
|
||||
m_szInfoName = strdup(szInfoName);
|
||||
}
|
||||
|
||||
void ParChecker::SetNZBFilename(const char * szNZBFilename)
|
||||
{
|
||||
if (m_szNZBFilename)
|
||||
{
|
||||
free(m_szNZBFilename);
|
||||
}
|
||||
m_szNZBFilename = strdup(szNZBFilename);
|
||||
}
|
||||
|
||||
void ParChecker::SetStatus(EStatus eStatus)
|
||||
{
|
||||
m_eStatus = eStatus;
|
||||
@@ -144,11 +157,16 @@ void ParChecker::Run()
|
||||
m_iProcessedFiles = 0;
|
||||
m_iExtraFiles = 0;
|
||||
m_bVerifyingExtraFiles = false;
|
||||
m_bCancelled = false;
|
||||
|
||||
info("Verifying %s", m_szInfoName);
|
||||
SetStatus(psWorking);
|
||||
|
||||
snprintf(m_szProgressLabel, 1024, "Verifying %s", m_szInfoName);
|
||||
m_szProgressLabel[1024-1] = '\0';
|
||||
m_iFileProgress = 0;
|
||||
m_iStageProgress = 0;
|
||||
UpdateProgress();
|
||||
|
||||
debug("par: %s", m_szParFilename);
|
||||
CommandLine commandLine;
|
||||
const char* argv[] = { "par2", "r", "-v", "-v", m_szParFilename };
|
||||
@@ -167,13 +185,7 @@ void ParChecker::Run()
|
||||
pRepairer->sig_filename.connect(sigc::mem_fun(*this, &ParChecker::signal_filename));
|
||||
pRepairer->sig_progress.connect(sigc::mem_fun(*this, &ParChecker::signal_progress));
|
||||
pRepairer->sig_done.connect(sigc::mem_fun(*this, &ParChecker::signal_done));
|
||||
|
||||
snprintf(m_szProgressLabel, 1024, "Verifying %s", m_szInfoName);
|
||||
m_szProgressLabel[1024-1] = '\0';
|
||||
m_iFileProgress = 0;
|
||||
m_iStageProgress = 0;
|
||||
UpdateProgress();
|
||||
|
||||
|
||||
res = pRepairer->PreProcess(commandLine);
|
||||
debug("ParChecker: PreProcess-result=%i", res);
|
||||
|
||||
@@ -232,7 +244,6 @@ void ParChecker::Run()
|
||||
|
||||
m_mutexQueuedParFiles.Lock();
|
||||
hasMorePars = !m_QueuedParFiles.empty();
|
||||
m_bQueuedParFilesChanged = false;
|
||||
m_mutexQueuedParFiles.Unlock();
|
||||
|
||||
if (!requested && !hasMorePars)
|
||||
@@ -245,15 +256,7 @@ void ParChecker::Run()
|
||||
|
||||
if (!hasMorePars)
|
||||
{
|
||||
// wait until new files are added by "AddParFile" or a change is signaled by "QueueChanged"
|
||||
bool bQueuedParFilesChanged = false;
|
||||
while (!bQueuedParFilesChanged && !IsStopped())
|
||||
{
|
||||
m_mutexQueuedParFiles.Lock();
|
||||
bQueuedParFilesChanged = m_bQueuedParFilesChanged;
|
||||
m_mutexQueuedParFiles.Unlock();
|
||||
usleep(100 * 1000);
|
||||
}
|
||||
m_semNeedMoreFiles.Wait();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -312,13 +315,7 @@ void ParChecker::Run()
|
||||
}
|
||||
}
|
||||
|
||||
if (m_bCancelled)
|
||||
{
|
||||
warn("Repair cancelled for %s", m_szInfoName);
|
||||
m_szErrMsg = strdup("repair cancelled");
|
||||
SetStatus(psFailed);
|
||||
}
|
||||
else if (res == eSuccess)
|
||||
if (res == eSuccess)
|
||||
{
|
||||
SetStatus(psFinished);
|
||||
}
|
||||
@@ -365,14 +362,14 @@ void ParChecker::AddParFile(const char * szParFilename)
|
||||
{
|
||||
m_mutexQueuedParFiles.Lock();
|
||||
m_QueuedParFiles.push_back(strdup(szParFilename));
|
||||
m_bQueuedParFilesChanged = true;
|
||||
m_semNeedMoreFiles.Post();
|
||||
m_mutexQueuedParFiles.Unlock();
|
||||
}
|
||||
|
||||
void ParChecker::QueueChanged()
|
||||
{
|
||||
m_mutexQueuedParFiles.Lock();
|
||||
m_bQueuedParFilesChanged = true;
|
||||
m_semNeedMoreFiles.Post();
|
||||
m_mutexQueuedParFiles.Unlock();
|
||||
}
|
||||
|
||||
@@ -544,14 +541,4 @@ void ParChecker::signal_done(std::string str, int available, int total)
|
||||
}
|
||||
}
|
||||
|
||||
void ParChecker::Cancel()
|
||||
{
|
||||
#ifdef HAVE_PAR2_CANCEL
|
||||
((Repairer*)m_pRepairer)->cancelled = true;
|
||||
m_bCancelled = true;
|
||||
#else
|
||||
error("Could not cancel par-repair. The used version of libpar2 does not support the cancelling of par-repair. Libpar2 needs to be patched for that feature to work.");
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
11
ParChecker.h
11
ParChecker.h
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2007-2009 Andrei Prygounkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2007 Andrei Prygounkov <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
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
#include "Thread.h"
|
||||
#include "Observer.h"
|
||||
#include "DownloadInfo.h"
|
||||
|
||||
class ParChecker : public Thread, public Subject
|
||||
{
|
||||
@@ -56,6 +57,7 @@ public:
|
||||
|
||||
private:
|
||||
char* m_szInfoName;
|
||||
char* m_szNZBFilename;
|
||||
char* m_szParFilename;
|
||||
EStatus m_eStatus;
|
||||
EStage m_eStage;
|
||||
@@ -64,7 +66,7 @@ private:
|
||||
bool m_bRepairNotNeeded;
|
||||
QueuedParFiles m_QueuedParFiles;
|
||||
Mutex m_mutexQueuedParFiles;
|
||||
bool m_bQueuedParFilesChanged;
|
||||
Semaphore m_semNeedMoreFiles;
|
||||
int m_iProcessedFiles;
|
||||
int m_iFilesToRepair;
|
||||
int m_iExtraFiles;
|
||||
@@ -72,7 +74,6 @@ private:
|
||||
char* m_szProgressLabel;
|
||||
int m_iFileProgress;
|
||||
int m_iStageProgress;
|
||||
bool m_bCancelled;
|
||||
|
||||
bool LoadMorePars();
|
||||
bool CheckSplittedFragments();
|
||||
@@ -100,6 +101,8 @@ public:
|
||||
virtual void Run();
|
||||
const char* GetParFilename() { return m_szParFilename; }
|
||||
void SetParFilename(const char* szParFilename);
|
||||
const char* GetNZBFilename() { return m_szNZBFilename; }
|
||||
void SetNZBFilename(const char* szNZBFilename);
|
||||
const char* GetInfoName() { return m_szInfoName; }
|
||||
void SetInfoName(const char* szInfoName);
|
||||
void SetStatus(EStatus eStatus);
|
||||
@@ -108,8 +111,6 @@ public:
|
||||
bool GetRepairNotNeeded() { return m_bRepairNotNeeded; }
|
||||
void AddParFile(const char* szParFilename);
|
||||
void QueueChanged();
|
||||
void Cancel();
|
||||
bool GetCancelled() { return m_bCancelled; }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
154
PostInfo.cpp
Normal file
154
PostInfo.cpp
Normal file
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2007 Andrei Prygounkov <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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#include "win32.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "nzbget.h"
|
||||
#include "PostInfo.h"
|
||||
#include "Options.h"
|
||||
|
||||
extern Options* g_pOptions;
|
||||
|
||||
int PostInfo::m_iIDGen = 0;
|
||||
|
||||
PostInfo::PostInfo()
|
||||
{
|
||||
debug("Creating PostInfo");
|
||||
|
||||
m_szNZBFilename = NULL;
|
||||
m_szDestDir = NULL;
|
||||
m_szParFilename = NULL;
|
||||
m_szInfoName = NULL;
|
||||
m_bWorking = false;
|
||||
m_bParCheck = false;
|
||||
m_iParStatus = 0;
|
||||
m_bParFailed = false;
|
||||
m_szProgressLabel = strdup("");
|
||||
m_iFileProgress = 0;
|
||||
m_iStageProgress = 0;
|
||||
m_tStartTime = 0;
|
||||
m_tStageTime = 0;
|
||||
m_eStage = ptQueued;
|
||||
m_pScriptThread = NULL;
|
||||
m_Messages.clear();
|
||||
m_iIDGen++;
|
||||
m_iID = m_iIDGen;
|
||||
}
|
||||
|
||||
PostInfo::~ PostInfo()
|
||||
{
|
||||
debug("Destroying PostInfo");
|
||||
|
||||
if (m_szNZBFilename)
|
||||
{
|
||||
free(m_szNZBFilename);
|
||||
}
|
||||
if (m_szDestDir)
|
||||
{
|
||||
free(m_szDestDir);
|
||||
}
|
||||
if (m_szParFilename)
|
||||
{
|
||||
free(m_szParFilename);
|
||||
}
|
||||
if (m_szInfoName)
|
||||
{
|
||||
free(m_szInfoName);
|
||||
}
|
||||
if (m_szProgressLabel)
|
||||
{
|
||||
free(m_szProgressLabel);
|
||||
}
|
||||
for (Messages::iterator it = m_Messages.begin(); it != m_Messages.end(); it++)
|
||||
{
|
||||
delete *it;
|
||||
}
|
||||
m_Messages.clear();
|
||||
}
|
||||
|
||||
void PostInfo::SetNZBFilename(const char* szNZBFilename)
|
||||
{
|
||||
m_szNZBFilename = strdup(szNZBFilename);
|
||||
}
|
||||
|
||||
void PostInfo::SetDestDir(const char* szDestDir)
|
||||
{
|
||||
m_szDestDir = strdup(szDestDir);
|
||||
}
|
||||
|
||||
void PostInfo::SetParFilename(const char* szParFilename)
|
||||
{
|
||||
m_szParFilename = strdup(szParFilename);
|
||||
}
|
||||
|
||||
void PostInfo::SetInfoName(const char* szInfoName)
|
||||
{
|
||||
m_szInfoName = strdup(szInfoName);
|
||||
}
|
||||
|
||||
void PostInfo::SetProgressLabel(const char* szProgressLabel)
|
||||
{
|
||||
if (m_szProgressLabel)
|
||||
{
|
||||
free(m_szProgressLabel);
|
||||
}
|
||||
m_szProgressLabel = strdup(szProgressLabel);
|
||||
}
|
||||
|
||||
PostInfo::Messages* PostInfo::LockMessages()
|
||||
{
|
||||
m_mutexLog.Lock();
|
||||
return &m_Messages;
|
||||
}
|
||||
|
||||
void PostInfo::UnlockMessages()
|
||||
{
|
||||
m_mutexLog.Unlock();
|
||||
}
|
||||
|
||||
void PostInfo::AppendMessage(Message::EKind eKind, const char * szText)
|
||||
{
|
||||
Message* pMessage = new Message(++m_iIDGen, eKind, time(NULL), szText);
|
||||
|
||||
m_mutexLog.Lock();
|
||||
m_Messages.push_back(pMessage);
|
||||
|
||||
while (m_Messages.size() > (unsigned int)g_pOptions->GetLogBufferSize())
|
||||
{
|
||||
Message* pMessage = m_Messages.front();
|
||||
delete pMessage;
|
||||
m_Messages.pop_front();
|
||||
}
|
||||
m_mutexLog.Unlock();
|
||||
}
|
||||
113
PostInfo.h
Normal file
113
PostInfo.h
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2007 Andrei Prygounkov <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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef POSTINFO_H
|
||||
#define POSTINFO_H
|
||||
|
||||
#include <deque>
|
||||
|
||||
#include "Log.h"
|
||||
#include "Thread.h"
|
||||
|
||||
class PostInfo
|
||||
{
|
||||
public:
|
||||
enum EStage
|
||||
{
|
||||
ptQueued,
|
||||
ptLoadingPars,
|
||||
ptVerifyingSources,
|
||||
ptRepairing,
|
||||
ptVerifyingRepaired,
|
||||
ptExecutingScript,
|
||||
ptFinished
|
||||
};
|
||||
|
||||
typedef std::deque<Message*> Messages;
|
||||
|
||||
private:
|
||||
int m_iID;
|
||||
char* m_szNZBFilename;
|
||||
char* m_szDestDir;
|
||||
char* m_szParFilename;
|
||||
char* m_szInfoName;
|
||||
bool m_bWorking;
|
||||
bool m_bParCheck;
|
||||
int m_iParStatus;
|
||||
bool m_bParFailed;
|
||||
EStage m_eStage;
|
||||
char* m_szProgressLabel;
|
||||
int m_iFileProgress;
|
||||
int m_iStageProgress;
|
||||
time_t m_tStartTime;
|
||||
time_t m_tStageTime;
|
||||
Thread* m_pScriptThread;
|
||||
|
||||
Mutex m_mutexLog;
|
||||
Messages m_Messages;
|
||||
static int m_iIDGen;
|
||||
|
||||
public:
|
||||
PostInfo();
|
||||
~PostInfo();
|
||||
int GetID() { return m_iID; }
|
||||
const char* GetNZBFilename() { return m_szNZBFilename; }
|
||||
void SetNZBFilename(const char* szNZBFilename);
|
||||
const char* GetDestDir() { return m_szDestDir; }
|
||||
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);
|
||||
EStage GetStage() { return m_eStage; }
|
||||
void SetStage(EStage eStage) { m_eStage = eStage; }
|
||||
void SetProgressLabel(const char* szProgressLabel);
|
||||
const char* GetProgressLabel() { return m_szProgressLabel; }
|
||||
int GetFileProgress() { return m_iFileProgress; }
|
||||
void SetFileProgress(int iFileProgress) { m_iFileProgress = iFileProgress; }
|
||||
int GetStageProgress() { return m_iStageProgress; }
|
||||
void SetStageProgress(int iStageProgress) { m_iStageProgress = iStageProgress; }
|
||||
time_t GetStartTime() { return m_tStartTime; }
|
||||
void SetStartTime(time_t tStartTime) { m_tStartTime = tStartTime; }
|
||||
time_t GetStageTime() { return m_tStageTime; }
|
||||
void SetStageTime(time_t tStageTime) { m_tStageTime = tStageTime; }
|
||||
bool GetWorking() { return m_bWorking; }
|
||||
void SetWorking(bool bWorking) { m_bWorking = bWorking; }
|
||||
bool GetParCheck() { return m_bParCheck; }
|
||||
void SetParCheck(bool bParCheck) { m_bParCheck = bParCheck; }
|
||||
int GetParStatus() { return m_iParStatus; }
|
||||
void SetParStatus(int iParStatus) { m_iParStatus = iParStatus; }
|
||||
bool GetParFailed() { return m_bParFailed; }
|
||||
void SetParFailed(bool bParFailed) { m_bParFailed = bParFailed; }
|
||||
void AppendMessage(Message::EKind eKind, const char* szText);
|
||||
Thread* GetScriptThread() { return m_pScriptThread; }
|
||||
void SetScriptThread(Thread* pScriptThread) { m_pScriptThread = pScriptThread; }
|
||||
Messages* LockMessages();
|
||||
void UnlockMessages();
|
||||
};
|
||||
|
||||
typedef std::deque<PostInfo*> PostQueue;
|
||||
|
||||
#endif
|
||||
1948
PrePostProcessor.cpp
1948
PrePostProcessor.cpp
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2007-2009 Andrei Prygounkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2007 Andrei Prygounkov <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
|
||||
@@ -31,7 +31,7 @@
|
||||
#include "Thread.h"
|
||||
#include "Observer.h"
|
||||
#include "DownloadInfo.h"
|
||||
#include "Scanner.h"
|
||||
#include "PostInfo.h"
|
||||
|
||||
#ifndef DISABLE_PARCHECK
|
||||
#include "ParChecker.h"
|
||||
@@ -39,18 +39,6 @@
|
||||
|
||||
class PrePostProcessor : public Thread
|
||||
{
|
||||
public:
|
||||
enum EEditAction
|
||||
{
|
||||
eaPostMoveOffset = 51, // move post to m_iOffset relative to the current position in post-queue
|
||||
eaPostMoveTop,
|
||||
eaPostMoveBottom,
|
||||
eaPostDelete,
|
||||
eaHistoryDelete,
|
||||
eaHistoryReturn,
|
||||
eaHistoryProcess
|
||||
};
|
||||
|
||||
private:
|
||||
typedef std::deque<char*> FileList;
|
||||
|
||||
@@ -72,14 +60,10 @@ private:
|
||||
class PostParChecker: public ParChecker
|
||||
{
|
||||
private:
|
||||
PrePostProcessor* m_Owner;
|
||||
PostInfo* m_pPostInfo;
|
||||
PrePostProcessor* m_Owner;
|
||||
protected:
|
||||
virtual bool RequestMorePars(int iBlockNeeded, int* pBlockFound);
|
||||
virtual void UpdateProgress();
|
||||
public:
|
||||
PostInfo* GetPostInfo() { return m_pPostInfo; }
|
||||
void SetPostInfo(PostInfo* pPostInfo) { m_pPostInfo = pPostInfo; }
|
||||
|
||||
friend class PrePostProcessor;
|
||||
};
|
||||
@@ -90,56 +74,47 @@ private:
|
||||
int m_iBlockCount;
|
||||
};
|
||||
|
||||
typedef std::list<BlockInfo*> Blocks;
|
||||
typedef std::deque<BlockInfo*> Blocks;
|
||||
#endif
|
||||
|
||||
private:
|
||||
QueueCoordinatorObserver m_QueueCoordinatorObserver;
|
||||
bool m_bHasMoreJobs;
|
||||
bool m_bPostScript;
|
||||
bool m_bSchedulerPauseChanged;
|
||||
bool m_bSchedulerPause;
|
||||
bool m_bPostPause;
|
||||
Scanner m_Scanner;
|
||||
|
||||
bool IsNZBFileCompleted(DownloadQueue* pDownloadQueue, NZBInfo* pNZBInfo,
|
||||
bool bIgnoreFirstInPostQueue, bool bIgnorePausedPars, bool bCheckPostQueue, bool bAllowOnlyOneDeleted);
|
||||
void PausePars(DownloadQueue* pDownloadQueue, const char* szNZBFilename);
|
||||
void CheckIncomingNZBs();
|
||||
bool IsNZBFileCompleted(DownloadQueue* pDownloadQueue, const char* szNZBFilename,
|
||||
bool bIgnoreFirstInPostQueue, bool bIgnorePaused, bool bCheckPostQueue);
|
||||
bool CheckScript(FileInfo* pFileInfo);
|
||||
bool JobExists(PostQueue* pPostQueue, const char* szNZBFilename);
|
||||
bool ClearCompletedJobs(const char* szNZBFilename);
|
||||
void CheckPostQueue();
|
||||
void JobCompleted(DownloadQueue* pDownloadQueue, PostInfo* pPostInfo);
|
||||
void StartScriptJob(DownloadQueue* pDownloadQueue, PostInfo* pPostInfo);
|
||||
void SaveQueue(DownloadQueue* pDownloadQueue);
|
||||
void SanitisePostQueue(PostQueue* pPostQueue);
|
||||
void SavePostQueue();
|
||||
void SanitisePostQueue();
|
||||
void CheckDiskSpace();
|
||||
void ApplySchedulerState();
|
||||
bool PauseDownload();
|
||||
bool UnpauseDownload();
|
||||
void NZBAdded(DownloadQueue* pDownloadQueue, NZBInfo* pNZBInfo);
|
||||
void NZBDownloaded(DownloadQueue* pDownloadQueue, NZBInfo* pNZBInfo);
|
||||
void NZBDeleted(DownloadQueue* pDownloadQueue, NZBInfo* pNZBInfo);
|
||||
void NZBCompleted(DownloadQueue* pDownloadQueue, NZBInfo* pNZBInfo, bool bSaveQueue);
|
||||
bool FindMainPars(const char* szPath, FileList* pFileList);
|
||||
bool ParseParFilename(const char* szParFilename, int* iBaseNameLen, int* iBlocks);
|
||||
bool SameParCollection(const char* szFilename1, const char* szFilename2);
|
||||
bool CreatePostJobs(DownloadQueue* pDownloadQueue, NZBInfo* pNZBInfo, bool bParCheck, bool bPostScript, bool bAddTop);
|
||||
void DeleteQueuedFile(const char* szQueuedFile);
|
||||
void PausePars(DownloadQueue* pDownloadQueue, NZBInfo* pNZBInfo);
|
||||
NZBInfo* MergeGroups(DownloadQueue* pDownloadQueue, NZBInfo* pNZBInfo);
|
||||
bool PostQueueMove(IDList* pIDList, EEditAction eAction, int iOffset);
|
||||
bool PostQueueDelete(IDList* pIDList);
|
||||
bool HistoryDelete(IDList* pIDList);
|
||||
bool HistoryReturn(IDList* pIDList, bool bReprocess);
|
||||
void Cleanup();
|
||||
FileInfo* GetQueueGroup(DownloadQueue* pDownloadQueue, NZBInfo* pNZBInfo);
|
||||
void CheckHistory();
|
||||
|
||||
Mutex m_mutexQueue;
|
||||
PostQueue m_PostQueue;
|
||||
PostQueue m_CompletedJobs;
|
||||
|
||||
#ifndef DISABLE_PARCHECK
|
||||
PostParChecker m_ParChecker;
|
||||
ParCheckerObserver m_ParCheckerObserver;
|
||||
|
||||
void ParCheckerUpdate(Subject* Caller, void* Aspect);
|
||||
bool CheckPars(DownloadQueue* pDownloadQueue, FileInfo* pFileInfo);
|
||||
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,
|
||||
bool SameParCollection(const char* szFilename1, const char* szFilename2);
|
||||
bool FindMainPars(const char* szPath, FileList* pFileList);
|
||||
int GetParCleanupQueueGroup(DownloadQueue* pDownloadQueue, const char* szNZBFilename);
|
||||
bool HasFailedParJobs(const char* szNZBFilename);
|
||||
bool ParJobExists(PostQueue* pPostQueue, const char* szParFilename);
|
||||
bool ParseParFilename(const char* szParFilename, int* iBaseNameLen, int* iBlocks);
|
||||
bool RequestMorePars(const char* szNZBFilename, const char* szParFilename, int iBlockNeeded, int* pBlockFound);
|
||||
void FindPars(DownloadQueue* pDownloadQueue, const char* szNZBFilename, const char* szParFilename,
|
||||
Blocks* pBlocks, bool bStrictParName, bool bExactParName, int* pBlockFound);
|
||||
void UpdateParProgress();
|
||||
void StartParJob(PostInfo* pPostInfo);
|
||||
@@ -152,8 +127,8 @@ public:
|
||||
virtual void Stop();
|
||||
void QueueCoordinatorUpdate(Subject* Caller, void* Aspect);
|
||||
bool HasMoreJobs() { return m_bHasMoreJobs; }
|
||||
void ScanNZBDir();
|
||||
bool QueueEditList(IDList* pIDList, EEditAction eAction, int iOffset);
|
||||
PostQueue* LockPostQueue();
|
||||
void UnlockPostQueue();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2005 Bo Cordes Petersen <placebodk@users.sourceforge.net>
|
||||
* Copyright (C) 2007-2010 Andrei Prygounkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2005 Bo Cordes Petersen <placebodk@users.sourceforge.net>
|
||||
* Copyright (C) 2007 Andrei Prygounkov <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
|
||||
@@ -60,6 +60,8 @@ QueueCoordinator::QueueCoordinator()
|
||||
debug("Creating QueueCoordinator");
|
||||
|
||||
m_bHasMoreJobs = true;
|
||||
m_DownloadQueue.clear();
|
||||
m_ActiveDownloads.clear();
|
||||
ResetSpeedStat();
|
||||
|
||||
m_iAllBytes = 0;
|
||||
@@ -77,11 +79,11 @@ QueueCoordinator::~QueueCoordinator()
|
||||
// Cleanup
|
||||
|
||||
debug("Deleting DownloadQueue");
|
||||
for (FileQueue::iterator it = m_DownloadQueue.GetFileQueue()->begin(); it != m_DownloadQueue.GetFileQueue()->end(); it++)
|
||||
for (DownloadQueue::iterator it = m_DownloadQueue.begin(); it != m_DownloadQueue.end(); it++)
|
||||
{
|
||||
delete *it;
|
||||
}
|
||||
m_DownloadQueue.GetFileQueue()->clear();
|
||||
m_DownloadQueue.clear();
|
||||
|
||||
debug("Deleting ArticleDownloaders");
|
||||
for (ActiveDownloads::iterator it = m_ActiveDownloads.begin(); it != m_ActiveDownloads.end(); it++)
|
||||
@@ -118,16 +120,15 @@ void QueueCoordinator::Run()
|
||||
m_mutexDownloadQueue.Unlock();
|
||||
|
||||
m_tStartServer = time(NULL);
|
||||
m_tLastCheck = m_tStartServer;
|
||||
bool bWasStandBy = true;
|
||||
bool bArticeDownloadsRunning = false;
|
||||
int iResetCounter = 0;
|
||||
|
||||
while (!IsStopped())
|
||||
{
|
||||
if (!(g_pOptions->GetPauseDownload() || g_pOptions->GetPauseDownload2()))
|
||||
if (!g_pOptions->GetPause())
|
||||
{
|
||||
NNTPConnection* pConnection = g_pServerPool->GetConnection(0);
|
||||
NNTPConnection* pConnection = g_pServerPool->GetConnection(0, false);
|
||||
if (pConnection)
|
||||
{
|
||||
// start download for next article
|
||||
@@ -177,7 +178,6 @@ void QueueCoordinator::Run()
|
||||
g_pServerPool->CloseUnusedConnections();
|
||||
ResetHangingDownloads();
|
||||
iResetCounter = 0;
|
||||
AdjustStartTime();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,9 +203,9 @@ void QueueCoordinator::AddNZBFileToQueue(NZBFile* pNZBFile, bool bAddFirst)
|
||||
|
||||
m_mutexDownloadQueue.Lock();
|
||||
|
||||
FileQueue tmpFileQueue;
|
||||
tmpFileQueue.clear();
|
||||
FileQueue DupeList;
|
||||
DownloadQueue tmpDownloadQueue;
|
||||
tmpDownloadQueue.clear();
|
||||
DownloadQueue DupeList;
|
||||
DupeList.clear();
|
||||
|
||||
int index1 = 0;
|
||||
@@ -246,41 +246,39 @@ void QueueCoordinator::AddNZBFileToQueue(NZBFile* pNZBFile, bool bAddFirst)
|
||||
|
||||
if (bAddFirst)
|
||||
{
|
||||
tmpFileQueue.push_front(pFileInfo);
|
||||
tmpDownloadQueue.push_front(pFileInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
tmpFileQueue.push_back(pFileInfo);
|
||||
tmpDownloadQueue.push_back(pFileInfo);
|
||||
}
|
||||
}
|
||||
|
||||
for (FileQueue::iterator it = tmpFileQueue.begin(); it != tmpFileQueue.end(); it++)
|
||||
for (DownloadQueue::iterator it = tmpDownloadQueue.begin(); it != tmpDownloadQueue.end(); it++)
|
||||
{
|
||||
if (bAddFirst)
|
||||
{
|
||||
m_DownloadQueue.GetFileQueue()->push_front(*it);
|
||||
m_DownloadQueue.push_front(*it);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_DownloadQueue.GetFileQueue()->push_back(*it);
|
||||
m_DownloadQueue.push_back(*it);
|
||||
}
|
||||
}
|
||||
|
||||
for (FileQueue::iterator it = DupeList.begin(); it != DupeList.end(); it++)
|
||||
for (DownloadQueue::iterator it = DupeList.begin(); it != DupeList.end(); it++)
|
||||
{
|
||||
FileInfo* pFileInfo = *it;
|
||||
if (g_pOptions->GetSaveQueue() && g_pOptions->GetServerMode())
|
||||
{
|
||||
g_pDiskState->DiscardFile(pFileInfo);
|
||||
g_pDiskState->DiscardFile(NULL, pFileInfo);
|
||||
}
|
||||
delete pFileInfo;
|
||||
}
|
||||
|
||||
m_DownloadQueue.GetNZBInfoList()->Add(pNZBFile->GetNZBInfo());
|
||||
|
||||
pNZBFile->DetachFileInfos();
|
||||
|
||||
Aspect aspect = { eaNZBFileAdded, &m_DownloadQueue, pNZBFile->GetNZBInfo(), NULL };
|
||||
Aspect aspect = { eaNZBFileAdded, NULL, &m_DownloadQueue, pNZBFile->GetFileName() };
|
||||
Notify(&aspect);
|
||||
|
||||
if (g_pOptions->GetSaveQueue() && g_pOptions->GetServerMode())
|
||||
@@ -291,16 +289,30 @@ void QueueCoordinator::AddNZBFileToQueue(NZBFile* pNZBFile, bool bAddFirst)
|
||||
m_mutexDownloadQueue.Unlock();
|
||||
}
|
||||
|
||||
bool QueueCoordinator::AddFileToQueue(const char* szFileName)
|
||||
{
|
||||
// Parse the buffer and make it into a NZBFile
|
||||
NZBFile* pNZBFile = NZBFile::CreateFromFile(szFileName);
|
||||
|
||||
// Did file parse correctly?
|
||||
if (!pNZBFile)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add NZBFile to Queue
|
||||
AddNZBFileToQueue(pNZBFile, false);
|
||||
|
||||
delete pNZBFile;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE: see note to "AddSpeedReading"
|
||||
*/
|
||||
float QueueCoordinator::CalcCurrentDownloadSpeed()
|
||||
{
|
||||
if (m_bStandBy)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iTimeDiff = (int)time(NULL) - m_iSpeedStartTime * SPEEDMETER_SLOTSIZE;
|
||||
if (iTimeDiff == 0)
|
||||
{
|
||||
@@ -370,7 +382,7 @@ long long QueueCoordinator::CalcRemainingSize()
|
||||
long long lRemainingSize = 0;
|
||||
|
||||
m_mutexDownloadQueue.Lock();
|
||||
for (FileQueue::iterator it = m_DownloadQueue.GetFileQueue()->begin(); it != m_DownloadQueue.GetFileQueue()->end(); it++)
|
||||
for (DownloadQueue::iterator it = m_DownloadQueue.begin(); it != m_DownloadQueue.end(); it++)
|
||||
{
|
||||
FileInfo* pFileInfo = *it;
|
||||
if (!pFileInfo->GetPaused() && !pFileInfo->GetDeleted())
|
||||
@@ -403,7 +415,7 @@ bool QueueCoordinator::DeleteQueueEntry(FileInfo* pFileInfo)
|
||||
}
|
||||
if (!hasDownloads)
|
||||
{
|
||||
Aspect aspect = { eaFileDeleted, &m_DownloadQueue, pFileInfo->GetNZBInfo(), pFileInfo };
|
||||
Aspect aspect = { eaFileDeleted, pFileInfo, &m_DownloadQueue, NULL };
|
||||
Notify(&aspect);
|
||||
|
||||
DeleteFileInfo(pFileInfo, false);
|
||||
@@ -429,7 +441,7 @@ bool QueueCoordinator::GetNextArticle(FileInfo* &pFileInfo, ArticleInfo* &pArtic
|
||||
{
|
||||
//debug("QueueCoordinator::GetNextArticle()");
|
||||
|
||||
for (FileQueue::iterator it = m_DownloadQueue.GetFileQueue()->begin(); it != m_DownloadQueue.GetFileQueue()->end(); it++)
|
||||
for (DownloadQueue::iterator it = m_DownloadQueue.begin(); it != m_DownloadQueue.end(); it++)
|
||||
{
|
||||
pFileInfo = *it;
|
||||
if (!pFileInfo->GetPaused() && !pFileInfo->GetDeleted())
|
||||
@@ -515,8 +527,7 @@ void QueueCoordinator::Update(Subject* Caller, void* Aspect)
|
||||
|
||||
ArticleDownloader* pArticleDownloader = (ArticleDownloader*) Caller;
|
||||
if ((pArticleDownloader->GetStatus() == ArticleDownloader::adFinished) ||
|
||||
(pArticleDownloader->GetStatus() == ArticleDownloader::adFailed) ||
|
||||
(pArticleDownloader->GetStatus() == ArticleDownloader::adRetry))
|
||||
(pArticleDownloader->GetStatus() == ArticleDownloader::adFailed))
|
||||
{
|
||||
ArticleCompleted(pArticleDownloader);
|
||||
}
|
||||
@@ -528,8 +539,6 @@ void QueueCoordinator::ArticleCompleted(ArticleDownloader* pArticleDownloader)
|
||||
|
||||
FileInfo* pFileInfo = pArticleDownloader->GetFileInfo();
|
||||
ArticleInfo* pArticleInfo = pArticleDownloader->GetArticleInfo();
|
||||
bool bPaused = false;
|
||||
bool fileCompleted = false;
|
||||
|
||||
m_mutexDownloadQueue.Lock();
|
||||
|
||||
@@ -541,18 +550,10 @@ void QueueCoordinator::ArticleCompleted(ArticleDownloader* pArticleDownloader)
|
||||
{
|
||||
pArticleInfo->SetStatus(ArticleInfo::aiFailed);
|
||||
}
|
||||
else if (pArticleDownloader->GetStatus() == ArticleDownloader::adRetry)
|
||||
{
|
||||
pArticleInfo->SetStatus(ArticleInfo::aiUndefined);
|
||||
bPaused = true;
|
||||
}
|
||||
|
||||
if (!bPaused)
|
||||
{
|
||||
pFileInfo->SetRemainingSize(pFileInfo->GetRemainingSize() - pArticleInfo->GetSize());
|
||||
pFileInfo->SetCompleted(pFileInfo->GetCompleted() + 1);
|
||||
fileCompleted = (int)pFileInfo->GetArticles()->size() == pFileInfo->GetCompleted();
|
||||
}
|
||||
pFileInfo->SetRemainingSize(pFileInfo->GetRemainingSize() - pArticleInfo->GetSize());
|
||||
pFileInfo->SetCompleted(pFileInfo->GetCompleted() + 1);
|
||||
bool fileCompleted = (int)pFileInfo->GetArticles()->size() == pFileInfo->GetCompleted();
|
||||
|
||||
if (!pFileInfo->GetFilenameConfirmed() &&
|
||||
pArticleDownloader->GetStatus() == ArticleDownloader::adFinished &&
|
||||
@@ -606,21 +607,16 @@ void QueueCoordinator::ArticleCompleted(ArticleDownloader* pArticleDownloader)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (deleteFileObj)
|
||||
{
|
||||
bool fileDeleted = pFileInfo->GetDeleted();
|
||||
// delete File from Queue
|
||||
pFileInfo->SetDeleted(true);
|
||||
|
||||
Aspect aspect = { fileCompleted && !fileDeleted ? eaFileCompleted : eaFileDeleted, &m_DownloadQueue, pFileInfo->GetNZBInfo(), pFileInfo };
|
||||
Aspect aspect = { fileCompleted && !fileDeleted ? eaFileCompleted : eaFileDeleted, pFileInfo, &m_DownloadQueue, NULL };
|
||||
Notify(&aspect);
|
||||
|
||||
DeleteFileInfo(pFileInfo, fileCompleted);
|
||||
if (g_pOptions->GetSaveQueue() && g_pOptions->GetServerMode())
|
||||
{
|
||||
g_pDiskState->SaveDownloadQueue(&m_DownloadQueue);
|
||||
}
|
||||
}
|
||||
|
||||
m_mutexDownloadQueue.Unlock();
|
||||
@@ -628,52 +624,47 @@ void QueueCoordinator::ArticleCompleted(ArticleDownloader* pArticleDownloader)
|
||||
|
||||
void QueueCoordinator::DeleteFileInfo(FileInfo* pFileInfo, bool bCompleted)
|
||||
{
|
||||
for (FileQueue::iterator it = m_DownloadQueue.GetFileQueue()->begin(); it != m_DownloadQueue.GetFileQueue()->end(); it++)
|
||||
for (DownloadQueue::iterator it = m_DownloadQueue.begin(); it != m_DownloadQueue.end(); it++)
|
||||
{
|
||||
FileInfo* pa = *it;
|
||||
if (pa == pFileInfo)
|
||||
{
|
||||
m_DownloadQueue.GetFileQueue()->erase(it);
|
||||
m_DownloadQueue.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (g_pOptions->GetSaveQueue() && g_pOptions->GetServerMode())
|
||||
{
|
||||
g_pDiskState->DiscardFile(pFileInfo);
|
||||
g_pDiskState->DiscardFile(&m_DownloadQueue, pFileInfo);
|
||||
}
|
||||
|
||||
if (!bCompleted)
|
||||
{
|
||||
DiscardDiskFile(pFileInfo);
|
||||
}
|
||||
// deleting temporary files
|
||||
|
||||
delete pFileInfo;
|
||||
}
|
||||
|
||||
void QueueCoordinator::DiscardDiskFile(FileInfo* pFileInfo)
|
||||
{
|
||||
// deleting temporary files
|
||||
|
||||
if (!g_pOptions->GetDirectWrite() || g_pOptions->GetContinuePartial())
|
||||
{
|
||||
for (FileInfo::Articles::iterator it = pFileInfo->GetArticles()->begin(); it != pFileInfo->GetArticles()->end(); it++)
|
||||
if (!g_pOptions->GetDirectWrite() || g_pOptions->GetContinuePartial())
|
||||
{
|
||||
ArticleInfo* pa = *it;
|
||||
if (pa->GetResultFilename())
|
||||
for (FileInfo::Articles::iterator it = pFileInfo->GetArticles()->begin(); it != pFileInfo->GetArticles()->end(); it++)
|
||||
{
|
||||
remove(pa->GetResultFilename());
|
||||
ArticleInfo* pa = *it;
|
||||
if (pa->GetResultFilename())
|
||||
{
|
||||
remove(pa->GetResultFilename());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (g_pOptions->GetDirectWrite())
|
||||
{
|
||||
char name[1024];
|
||||
snprintf(name, 1024, "%s%i.out", g_pOptions->GetTempDir(), pFileInfo->GetID());
|
||||
name[1024-1] = '\0';
|
||||
remove(name);
|
||||
}
|
||||
}
|
||||
|
||||
if (g_pOptions->GetDirectWrite())
|
||||
{
|
||||
char name[1024];
|
||||
snprintf(name, 1024, "%s%i.out", g_pOptions->GetTempDir(), pFileInfo->GetID());
|
||||
name[1024-1] = '\0';
|
||||
remove(name);
|
||||
}
|
||||
delete pFileInfo;
|
||||
}
|
||||
|
||||
bool QueueCoordinator::IsDupe(FileInfo* pFileInfo)
|
||||
@@ -687,7 +678,7 @@ bool QueueCoordinator::IsDupe(FileInfo* pFileInfo)
|
||||
}
|
||||
|
||||
// checking in queue
|
||||
for (FileQueue::iterator it = m_DownloadQueue.GetFileQueue()->begin(); it != m_DownloadQueue.GetFileQueue()->end(); it++)
|
||||
for (DownloadQueue::iterator it = m_DownloadQueue.begin(); it != m_DownloadQueue.end(); it++)
|
||||
{
|
||||
FileInfo* pQueueEntry = *it;
|
||||
if (!strcmp(pFileInfo->GetNZBInfo()->GetDestDir(), pQueueEntry->GetNZBInfo()->GetDestDir()) &&
|
||||
@@ -811,95 +802,3 @@ void QueueCoordinator::CalcStat(int* iUpTimeSec, int* iDnTimeSec, long long* iAl
|
||||
*iAllBytes = m_iAllBytes;
|
||||
m_mutexStat.Unlock();
|
||||
}
|
||||
|
||||
/*
|
||||
* Detects large step changes of system time and adjust statistics.
|
||||
*/
|
||||
void QueueCoordinator::AdjustStartTime()
|
||||
{
|
||||
time_t m_tCurTime = time(NULL);
|
||||
time_t tDiff = m_tCurTime - m_tLastCheck;
|
||||
if (tDiff > 60 || tDiff < 0)
|
||||
{
|
||||
m_tStartServer += tDiff + 1; // "1" because the method is called once per second
|
||||
if (m_tStartDownload != 0)
|
||||
{
|
||||
m_tStartDownload += tDiff + 1;
|
||||
}
|
||||
}
|
||||
m_tLastCheck = m_tCurTime;
|
||||
}
|
||||
|
||||
bool QueueCoordinator::SetQueueEntryNZBCategory(NZBInfo* pNZBInfo, const char* szCategory)
|
||||
{
|
||||
if (pNZBInfo->GetPostProcess())
|
||||
{
|
||||
char szNZBNiceName[1024];
|
||||
pNZBInfo->GetNiceNZBName(szNZBNiceName, 1024);
|
||||
error("Could not change category for %s. File in post-process-stage", szNZBNiceName);
|
||||
return false;
|
||||
}
|
||||
|
||||
char szOldDestDir[1024];
|
||||
strncpy(szOldDestDir, pNZBInfo->GetDestDir(), 1024);
|
||||
szOldDestDir[1024-1] = '\0';
|
||||
|
||||
pNZBInfo->SetCategory(szCategory);
|
||||
pNZBInfo->BuildDestDirName();
|
||||
|
||||
bool bDirUnchanged = !strcmp(pNZBInfo->GetDestDir(), szOldDestDir);
|
||||
bool bOK = bDirUnchanged || ArticleDownloader::MoveCompletedFiles(pNZBInfo, szOldDestDir);
|
||||
|
||||
return bOK;
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE: DownloadQueue must be locked prior to call of this function
|
||||
*/
|
||||
bool QueueCoordinator::MergeQueueEntries(NZBInfo* pDestNZBInfo, NZBInfo* pSrcNZBInfo)
|
||||
{
|
||||
if (pDestNZBInfo->GetPostProcess() || pSrcNZBInfo->GetPostProcess())
|
||||
{
|
||||
char szDestNZBNiceName[1024];
|
||||
pDestNZBInfo->GetNiceNZBName(szDestNZBNiceName, 1024);
|
||||
char szSrcNZBNiceName[1024];
|
||||
pSrcNZBInfo->GetNiceNZBName(szSrcNZBNiceName, 1024);
|
||||
error("Could not merge %s and %s. File in post-process-stage", szDestNZBNiceName, szSrcNZBNiceName);
|
||||
return false;
|
||||
}
|
||||
|
||||
// set new dest directory, new category and move downloaded files to new dest directory
|
||||
pSrcNZBInfo->SetFilename(pSrcNZBInfo->GetFilename());
|
||||
SetQueueEntryNZBCategory(pSrcNZBInfo, pDestNZBInfo->GetCategory());
|
||||
|
||||
// reattach file items to new NZBInfo-object
|
||||
for (FileQueue::iterator it = m_DownloadQueue.GetFileQueue()->begin(); it != m_DownloadQueue.GetFileQueue()->end(); it++)
|
||||
{
|
||||
FileInfo* pFileInfo = *it;
|
||||
if (pFileInfo->GetNZBInfo() == pSrcNZBInfo)
|
||||
{
|
||||
pFileInfo->SetNZBInfo(pDestNZBInfo);
|
||||
}
|
||||
}
|
||||
|
||||
pDestNZBInfo->SetFileCount(pDestNZBInfo->GetFileCount() + pSrcNZBInfo->GetFileCount());
|
||||
pDestNZBInfo->SetSize(pDestNZBInfo->GetSize() + pSrcNZBInfo->GetSize());
|
||||
|
||||
// reattach completed file items to new NZBInfo-object
|
||||
for (NZBInfo::Files::iterator it = pSrcNZBInfo->GetCompletedFiles()->begin(); it != pSrcNZBInfo->GetCompletedFiles()->end(); it++)
|
||||
{
|
||||
char* szFileName = *it;
|
||||
pDestNZBInfo->GetCompletedFiles()->push_back(szFileName);
|
||||
}
|
||||
pSrcNZBInfo->GetCompletedFiles()->clear();
|
||||
|
||||
// concatenate QueuedFilenames using character '|' as separator
|
||||
int iLen = strlen(pDestNZBInfo->GetQueuedFilename()) + strlen(pSrcNZBInfo->GetQueuedFilename()) + 1;
|
||||
char* szQueuedFilename = (char*)malloc(iLen);
|
||||
snprintf(szQueuedFilename, iLen, "%s|%s", pDestNZBInfo->GetQueuedFilename(), pSrcNZBInfo->GetQueuedFilename());
|
||||
szQueuedFilename[iLen - 1] = '\0';
|
||||
pDestNZBInfo->SetQueuedFilename(szQueuedFilename);
|
||||
free(szQueuedFilename);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
* This file if part of nzbget
|
||||
*
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007-2010 Andrei Prygounkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007 Andrei Prygounkov <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
|
||||
@@ -30,6 +30,9 @@
|
||||
#include <deque>
|
||||
#include <list>
|
||||
#include <time.h>
|
||||
#ifdef WIN32
|
||||
#include <sys/timeb.h>
|
||||
#endif
|
||||
|
||||
#include "Thread.h"
|
||||
#include "NZBFile.h"
|
||||
@@ -39,7 +42,7 @@
|
||||
#include "QueueEditor.h"
|
||||
#include "NNTPConnection.h"
|
||||
|
||||
class QueueCoordinator : public Thread, public Observer, public Subject, public DownloadSpeedMeter, public DownloadQueueHolder
|
||||
class QueueCoordinator : public Thread, public Observer, public Subject, public DownloadSpeedMeter
|
||||
{
|
||||
public:
|
||||
typedef std::list<ArticleDownloader*> ActiveDownloads;
|
||||
@@ -52,9 +55,9 @@ public:
|
||||
struct Aspect
|
||||
{
|
||||
EAspectAction eAction;
|
||||
DownloadQueue* pDownloadQueue;
|
||||
NZBInfo* pNZBInfo;
|
||||
FileInfo* pFileInfo;
|
||||
DownloadQueue* pDownloadQueue;
|
||||
const char* szNZBFilename;
|
||||
};
|
||||
|
||||
private:
|
||||
@@ -75,7 +78,6 @@ private:
|
||||
int m_iSpeedBytesIndex;
|
||||
long long m_iAllBytes;
|
||||
time_t m_tStartServer;
|
||||
time_t m_tLastCheck;
|
||||
time_t m_tStartDownload;
|
||||
time_t m_tPausedFrom;
|
||||
bool m_bStandBy;
|
||||
@@ -90,7 +92,6 @@ private:
|
||||
void ResetHangingDownloads();
|
||||
void ResetSpeedStat();
|
||||
void EnterLeaveStandBy(bool bEnter);
|
||||
void AdjustStartTime();
|
||||
|
||||
public:
|
||||
QueueCoordinator();
|
||||
@@ -108,15 +109,13 @@ public:
|
||||
// Editing the queue
|
||||
DownloadQueue* LockQueue();
|
||||
void UnlockQueue() ;
|
||||
void AddNZBFileToQueue(NZBFile* pNZBFile, bool bAddFirst);
|
||||
void AddNZBFileToQueue(NZBFile* pNZBQueue, bool bAddFirst);
|
||||
bool AddFileToQueue(const char* szFileName);
|
||||
bool HasMoreJobs() { return m_bHasMoreJobs; }
|
||||
bool GetStandBy() { return m_bStandBy; }
|
||||
bool DeleteQueueEntry(FileInfo* pFileInfo);
|
||||
bool SetQueueEntryNZBCategory(NZBInfo* pNZBInfo, const char* szCategory);
|
||||
bool MergeQueueEntries(NZBInfo* pDestNZBInfo, NZBInfo* pSrcNZBInfo);
|
||||
void DiscardDiskFile(FileInfo* pFileInfo);
|
||||
QueueEditor* GetQueueEditor() { return &m_QueueEditor; }
|
||||
|
||||
|
||||
void LogDebugInfo();
|
||||
};
|
||||
|
||||
|
||||
176
QueueEditor.cpp
176
QueueEditor.cpp
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2007-2009 Andrei Prygounkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2007 Andrei Prygounkov <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,7 @@ QueueEditor::~QueueEditor()
|
||||
|
||||
FileInfo* QueueEditor::FindFileInfo(DownloadQueue* pDownloadQueue, int iID)
|
||||
{
|
||||
for (FileQueue::iterator it = pDownloadQueue->GetFileQueue()->begin(); it != pDownloadQueue->GetFileQueue()->end(); it++)
|
||||
for (DownloadQueue::iterator it = pDownloadQueue->begin(); it != pDownloadQueue->end(); it++)
|
||||
{
|
||||
FileInfo* pFileInfo = *it;
|
||||
if (pFileInfo->GetID() == iID)
|
||||
@@ -88,7 +88,7 @@ FileInfo* QueueEditor::FindFileInfo(DownloadQueue* pDownloadQueue, int iID)
|
||||
int QueueEditor::FindFileInfoEntry(DownloadQueue* pDownloadQueue, FileInfo* pFileInfo)
|
||||
{
|
||||
int iEntry = 0;
|
||||
for (FileQueue::iterator it = pDownloadQueue->GetFileQueue()->begin(); it != pDownloadQueue->GetFileQueue()->end(); it++)
|
||||
for (DownloadQueue::iterator it = pDownloadQueue->begin(); it != pDownloadQueue->end(); it++)
|
||||
{
|
||||
FileInfo* pFileInfo2 = *it;
|
||||
if (pFileInfo2 == pFileInfo)
|
||||
@@ -134,41 +134,41 @@ void QueueEditor::MoveEntry(DownloadQueue* pDownloadQueue, FileInfo* pFileInfo,
|
||||
{
|
||||
iNewEntry = 0;
|
||||
}
|
||||
if ((unsigned int)iNewEntry > pDownloadQueue->GetFileQueue()->size() - 1)
|
||||
if ((unsigned int)iNewEntry > pDownloadQueue->size() - 1)
|
||||
{
|
||||
iNewEntry = (int)pDownloadQueue->GetFileQueue()->size() - 1;
|
||||
iNewEntry = (int)pDownloadQueue->size() - 1;
|
||||
}
|
||||
|
||||
if (iNewEntry >= 0 && (unsigned int)iNewEntry <= pDownloadQueue->GetFileQueue()->size() - 1)
|
||||
if (iNewEntry >= 0 && (unsigned int)iNewEntry <= pDownloadQueue->size() - 1)
|
||||
{
|
||||
FileInfo* fi = pDownloadQueue->GetFileQueue()->at(iEntry);
|
||||
pDownloadQueue->GetFileQueue()->erase(pDownloadQueue->GetFileQueue()->begin() + iEntry);
|
||||
pDownloadQueue->GetFileQueue()->insert(pDownloadQueue->GetFileQueue()->begin() + iNewEntry, fi);
|
||||
FileInfo* fi = (*pDownloadQueue)[iEntry];
|
||||
pDownloadQueue->erase(pDownloadQueue->begin() + iEntry);
|
||||
pDownloadQueue->insert(pDownloadQueue->begin() + iNewEntry, fi);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool QueueEditor::EditEntry(int ID, bool bSmartOrder, EEditAction eAction, int iOffset, const char* szText)
|
||||
bool QueueEditor::EditEntry(int ID, bool bSmartOrder, EEditAction eAction, int iOffset)
|
||||
{
|
||||
IDList cIDList;
|
||||
cIDList.clear();
|
||||
cIDList.push_back(ID);
|
||||
return EditList(&cIDList, bSmartOrder, eAction, iOffset, szText);
|
||||
return EditList(&cIDList, bSmartOrder, eAction, iOffset);
|
||||
}
|
||||
|
||||
bool QueueEditor::LockedEditEntry(DownloadQueue* pDownloadQueue, int ID, bool bSmartOrder, EEditAction eAction, int iOffset, const char* szText)
|
||||
bool QueueEditor::LockedEditEntry(DownloadQueue* pDownloadQueue, int ID, bool bSmartOrder, EEditAction eAction, int iOffset)
|
||||
{
|
||||
IDList cIDList;
|
||||
cIDList.clear();
|
||||
cIDList.push_back(ID);
|
||||
return InternEditList(pDownloadQueue, &cIDList, bSmartOrder, eAction, iOffset, szText);
|
||||
return InternEditList(pDownloadQueue, &cIDList, bSmartOrder, eAction, iOffset);
|
||||
}
|
||||
|
||||
bool QueueEditor::EditList(IDList* pIDList, bool bSmartOrder, EEditAction eAction, int iOffset, const char* szText)
|
||||
bool QueueEditor::EditList(IDList* pIDList, bool bSmartOrder, EEditAction eAction, int iOffset)
|
||||
{
|
||||
DownloadQueue* pDownloadQueue = g_pQueueCoordinator->LockQueue();
|
||||
|
||||
bool bOK = InternEditList(pDownloadQueue, pIDList, bSmartOrder, eAction, iOffset, szText);
|
||||
bool bOK = InternEditList(pDownloadQueue, pIDList, bSmartOrder, eAction, iOffset);
|
||||
|
||||
if (g_pOptions->GetSaveQueue() && g_pOptions->GetServerMode())
|
||||
{
|
||||
@@ -180,12 +180,7 @@ bool QueueEditor::EditList(IDList* pIDList, bool bSmartOrder, EEditAction eActio
|
||||
return bOK;
|
||||
}
|
||||
|
||||
bool QueueEditor::LockedEditList(DownloadQueue* pDownloadQueue, IDList* pIDList, bool bSmartOrder, EEditAction eAction, int iOffset, const char* szText)
|
||||
{
|
||||
return InternEditList(pDownloadQueue, pIDList, bSmartOrder, eAction, iOffset, szText);
|
||||
}
|
||||
|
||||
bool QueueEditor::InternEditList(DownloadQueue* pDownloadQueue, IDList* pIDList, bool bSmartOrder, EEditAction eAction, int iOffset, const char* szText)
|
||||
bool QueueEditor::InternEditList(DownloadQueue* pDownloadQueue, IDList* pIDList, bool bSmartOrder, EEditAction eAction, int iOffset)
|
||||
{
|
||||
if (eAction == eaGroupMoveOffset)
|
||||
{
|
||||
@@ -199,10 +194,6 @@ bool QueueEditor::InternEditList(DownloadQueue* pDownloadQueue, IDList* pIDList,
|
||||
{
|
||||
PauseParsInGroups(&cItemList, eAction == eaFilePauseExtraPars);
|
||||
}
|
||||
else if (eAction == eaGroupMerge)
|
||||
{
|
||||
MergeGroups(pDownloadQueue, &cItemList);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (ItemList::iterator it = cItemList.begin(); it != cItemList.end(); it++)
|
||||
@@ -228,12 +219,9 @@ bool QueueEditor::InternEditList(DownloadQueue* pDownloadQueue, IDList* pIDList,
|
||||
DeleteEntry(pItem->m_pFileInfo);
|
||||
break;
|
||||
|
||||
case eaGroupSetCategory:
|
||||
SetNZBCategory(pItem->m_pFileInfo->GetNZBInfo(), szText);
|
||||
break;
|
||||
|
||||
case eaGroupSetParameter:
|
||||
SetNZBParameter(pItem->m_pFileInfo->GetNZBInfo(), szText);
|
||||
case eaFilePauseAllPars:
|
||||
case eaFilePauseExtraPars:
|
||||
// remove compiler warning "enumeration not handled in switch"
|
||||
break;
|
||||
|
||||
case eaGroupPause:
|
||||
@@ -246,12 +234,6 @@ bool QueueEditor::InternEditList(DownloadQueue* pDownloadQueue, IDList* pIDList,
|
||||
case eaGroupPauseExtraPars:
|
||||
EditGroup(pDownloadQueue, pItem->m_pFileInfo, eAction, iOffset);
|
||||
break;
|
||||
|
||||
case eaFilePauseAllPars:
|
||||
case eaFilePauseExtraPars:
|
||||
case eaGroupMerge:
|
||||
// remove compiler warning "enumeration not handled in switch"
|
||||
break;
|
||||
}
|
||||
delete pItem;
|
||||
}
|
||||
@@ -282,18 +264,18 @@ void QueueEditor::PrepareList(DownloadQueue* pDownloadQueue, ItemList* pItemList
|
||||
if (iOffset < 0)
|
||||
{
|
||||
iStart = 0;
|
||||
iEnd = pDownloadQueue->GetFileQueue()->size();
|
||||
iEnd = pDownloadQueue->size();
|
||||
iStep = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
iStart = pDownloadQueue->GetFileQueue()->size() - 1;
|
||||
iStart = pDownloadQueue->size() - 1;
|
||||
iEnd = -1;
|
||||
iStep = -1;
|
||||
}
|
||||
for (int iIndex = iStart; iIndex != iEnd; iIndex += iStep)
|
||||
{
|
||||
FileInfo* pFileInfo = pDownloadQueue->GetFileQueue()->at(iIndex);
|
||||
FileInfo* pFileInfo = (*pDownloadQueue)[iIndex];
|
||||
int iID = pFileInfo->GetID();
|
||||
for (IDList::iterator it = pIDList->begin(); it != pIDList->end(); it++)
|
||||
{
|
||||
@@ -307,9 +289,9 @@ void QueueEditor::PrepareList(DownloadQueue* pDownloadQueue, ItemList* pItemList
|
||||
{
|
||||
iWorkOffset = -iIndex;
|
||||
}
|
||||
else if (iDestPos > int(pDownloadQueue->GetFileQueue()->size()) - 1)
|
||||
else if (iDestPos > int(pDownloadQueue->size()) - 1)
|
||||
{
|
||||
iWorkOffset = int(pDownloadQueue->GetFileQueue()->size()) - 1 - iIndex;
|
||||
iWorkOffset = int(pDownloadQueue->size()) - 1 - iIndex;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -335,7 +317,7 @@ void QueueEditor::PrepareList(DownloadQueue* pDownloadQueue, ItemList* pItemList
|
||||
// check ID range
|
||||
int iMaxID = 0;
|
||||
int iMinID = MAX_ID;
|
||||
for (FileQueue::iterator it = pDownloadQueue->GetFileQueue()->begin(); it != pDownloadQueue->GetFileQueue()->end(); it++)
|
||||
for (DownloadQueue::iterator it = pDownloadQueue->begin(); it != pDownloadQueue->end(); it++)
|
||||
{
|
||||
FileInfo* pFileInfo = *it;
|
||||
int ID = pFileInfo->GetID();
|
||||
@@ -371,7 +353,7 @@ bool QueueEditor::EditGroup(DownloadQueue* pDownloadQueue, FileInfo* pFileInfo,
|
||||
cIDList.clear();
|
||||
|
||||
// collecting files belonging to group
|
||||
for (FileQueue::iterator it = pDownloadQueue->GetFileQueue()->begin(); it != pDownloadQueue->GetFileQueue()->end(); it++)
|
||||
for (DownloadQueue::iterator it = pDownloadQueue->begin(); it != pDownloadQueue->end(); it++)
|
||||
{
|
||||
FileInfo* pFileInfo2 = *it;
|
||||
if (pFileInfo2->GetNZBInfo() == pFileInfo->GetNZBInfo())
|
||||
@@ -425,22 +407,17 @@ bool QueueEditor::EditGroup(DownloadQueue* pDownloadQueue, FileInfo* pFileInfo,
|
||||
}
|
||||
iOffset = iFileOffset;
|
||||
}
|
||||
else if (eAction == eaGroupDelete)
|
||||
{
|
||||
pFileInfo->GetNZBInfo()->SetDeleted(true);
|
||||
pFileInfo->GetNZBInfo()->SetCleanupDisk(CanCleanupDisk(pDownloadQueue, pFileInfo->GetNZBInfo()));
|
||||
}
|
||||
|
||||
EEditAction GroupToFileMap[] = { (EEditAction)0, eaFileMoveOffset, eaFileMoveTop, eaFileMoveBottom, eaFilePause, eaFileResume, eaFileDelete, eaFilePauseAllPars, eaFilePauseExtraPars,
|
||||
eaFileMoveOffset, eaFileMoveTop, eaFileMoveBottom, eaFilePause, eaFileResume, eaFileDelete, eaFilePauseAllPars, eaFilePauseExtraPars, (EEditAction)0, (EEditAction)0, (EEditAction)0 };
|
||||
eaFileMoveOffset, eaFileMoveTop, eaFileMoveBottom, eaFilePause, eaFileResume, eaFileDelete, eaFilePauseAllPars, eaFilePauseExtraPars };
|
||||
|
||||
return InternEditList(pDownloadQueue, &cIDList, true, GroupToFileMap[eAction], iOffset, NULL);
|
||||
return InternEditList(pDownloadQueue, &cIDList, true, GroupToFileMap[eAction], iOffset);
|
||||
}
|
||||
|
||||
void QueueEditor::BuildGroupList(DownloadQueue* pDownloadQueue, FileList* pGroupList)
|
||||
{
|
||||
pGroupList->clear();
|
||||
for (FileQueue::iterator it = pDownloadQueue->GetFileQueue()->begin(); it != pDownloadQueue->GetFileQueue()->end(); it++)
|
||||
for (DownloadQueue::iterator it = pDownloadQueue->begin(); it != pDownloadQueue->end(); it++)
|
||||
{
|
||||
FileInfo* pFileInfo = *it;
|
||||
FileInfo* pGroupInfo = NULL;
|
||||
@@ -542,15 +519,15 @@ void QueueEditor::AlignGroup(DownloadQueue* pDownloadQueue, FileInfo* pFirstFile
|
||||
FileInfo* pLastFileInfo = NULL;
|
||||
unsigned int iLastNum = 0;
|
||||
unsigned int iNum = 0;
|
||||
while (iNum < pDownloadQueue->GetFileQueue()->size())
|
||||
while (iNum < pDownloadQueue->size())
|
||||
{
|
||||
FileInfo* pFileInfo = pDownloadQueue->GetFileQueue()->at(iNum);
|
||||
FileInfo* pFileInfo = (*pDownloadQueue)[iNum];
|
||||
if (pFirstFileInfo->GetNZBInfo() == pFileInfo->GetNZBInfo())
|
||||
{
|
||||
if (pLastFileInfo && iNum - iLastNum > 1)
|
||||
{
|
||||
pDownloadQueue->GetFileQueue()->erase(pDownloadQueue->GetFileQueue()->begin() + iNum);
|
||||
pDownloadQueue->GetFileQueue()->insert(pDownloadQueue->GetFileQueue()->begin() + iLastNum + 1, pFileInfo);
|
||||
pDownloadQueue->erase(pDownloadQueue->begin() + iNum);
|
||||
pDownloadQueue->insert(pDownloadQueue->begin() + iLastNum + 1, pFileInfo);
|
||||
iLastNum++;
|
||||
}
|
||||
else
|
||||
@@ -679,90 +656,3 @@ void QueueEditor::PausePars(FileList* pFileList, bool bExtraParsOnly)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QueueEditor::SetNZBCategory(NZBInfo* pNZBInfo, const char* szCategory)
|
||||
{
|
||||
debug("QueueEditor: setting category '%s' for '%s'", szCategory, Util::BaseFileName(pNZBInfo->GetFilename()));
|
||||
|
||||
g_pQueueCoordinator->SetQueueEntryNZBCategory(pNZBInfo, szCategory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if deletion of already downloaded files is possible (when nzb id deleted from queue).
|
||||
* The deletion is most always possible, except the case if all remaining files in queue
|
||||
* (belonging to this nzb-file) are PARS.
|
||||
*/
|
||||
bool QueueEditor::CanCleanupDisk(DownloadQueue* pDownloadQueue, NZBInfo* pNZBInfo)
|
||||
{
|
||||
for (FileQueue::iterator it = pDownloadQueue->GetFileQueue()->begin(); it != pDownloadQueue->GetFileQueue()->end(); it++)
|
||||
{
|
||||
FileInfo* pFileInfo = *it;
|
||||
char szLoFileName[1024];
|
||||
strncpy(szLoFileName, pFileInfo->GetFilename(), 1024);
|
||||
szLoFileName[1024-1] = '\0';
|
||||
for (char* p = szLoFileName; *p; p++) *p = tolower(*p); // convert string to lowercase
|
||||
|
||||
if (!strstr(szLoFileName, ".par2"))
|
||||
{
|
||||
// non-par file found
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void QueueEditor::MergeGroups(DownloadQueue* pDownloadQueue, ItemList* pItemList)
|
||||
{
|
||||
if (pItemList->size() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
EditItem* pDestItem = pItemList->front();
|
||||
|
||||
for (ItemList::iterator it = pItemList->begin() + 1; it != pItemList->end(); it++)
|
||||
{
|
||||
EditItem* pItem = *it;
|
||||
if (pItem->m_pFileInfo->GetNZBInfo() != pDestItem->m_pFileInfo->GetNZBInfo())
|
||||
{
|
||||
debug("merge %s to %s", pItem->m_pFileInfo->GetNZBInfo()->GetFilename(), pDestItem->m_pFileInfo->GetNZBInfo()->GetFilename());
|
||||
g_pQueueCoordinator->MergeQueueEntries(pDestItem->m_pFileInfo->GetNZBInfo(), pItem->m_pFileInfo->GetNZBInfo());
|
||||
}
|
||||
delete pItem;
|
||||
}
|
||||
|
||||
// align group ("AlignGroup" needs the first file item as parameter)
|
||||
for (FileQueue::iterator it = pDownloadQueue->GetFileQueue()->begin(); it != pDownloadQueue->GetFileQueue()->end(); it++)
|
||||
{
|
||||
FileInfo* pFileInfo = *it;
|
||||
if (pFileInfo->GetNZBInfo() == pDestItem->m_pFileInfo->GetNZBInfo())
|
||||
{
|
||||
AlignGroup(pDownloadQueue, pFileInfo);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
delete pDestItem;
|
||||
}
|
||||
|
||||
void QueueEditor::SetNZBParameter(NZBInfo* pNZBInfo, const char* szParamString)
|
||||
{
|
||||
debug("QueueEditor: setting nzb parameter '%s' for '%s'", szParamString, Util::BaseFileName(pNZBInfo->GetFilename()));
|
||||
|
||||
char* szStr = strdup(szParamString);
|
||||
|
||||
char* szValue = strchr(szStr, '=');
|
||||
if (szValue)
|
||||
{
|
||||
*szValue = '\0';
|
||||
szValue++;
|
||||
pNZBInfo->SetParameter(szStr, szValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
error("Could not set nzb parameter for %s: invalid argument: %s", Util::BaseFileName(pNZBInfo->GetFilename()), szParamString);
|
||||
}
|
||||
|
||||
free(szStr);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file if part of nzbget
|
||||
*
|
||||
* Copyright (C) 2007-2009 Andrei Prygounkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2007 Andrei Prygounkov <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,6 +33,8 @@
|
||||
class QueueEditor
|
||||
{
|
||||
public:
|
||||
typedef std::vector<int> IDList;
|
||||
|
||||
enum EEditAction
|
||||
{
|
||||
eaFileMoveOffset = 1, // move to m_iOffset relative to the current position in queue
|
||||
@@ -50,10 +52,7 @@ public:
|
||||
eaGroupResume,
|
||||
eaGroupDelete,
|
||||
eaGroupPauseAllPars,
|
||||
eaGroupPauseExtraPars,
|
||||
eaGroupSetCategory,
|
||||
eaGroupMerge,
|
||||
eaGroupSetParameter
|
||||
eaGroupPauseExtraPars
|
||||
};
|
||||
|
||||
private:
|
||||
@@ -72,7 +71,7 @@ private:
|
||||
private:
|
||||
FileInfo* FindFileInfo(DownloadQueue* pDownloadQueue, int iID);
|
||||
int FindFileInfoEntry(DownloadQueue* pDownloadQueue, FileInfo* pFileInfo);
|
||||
bool InternEditList(DownloadQueue* pDownloadQueue, IDList* pIDList, bool bSmartOrder, EEditAction eAction, int iOffset, const char* szText);
|
||||
bool InternEditList(DownloadQueue* pDownloadQueue, IDList* pIDList, bool bSmartOrder, EEditAction eAction, int iOffset);
|
||||
void PrepareList(DownloadQueue* pDownloadQueue, ItemList* pItemList, IDList* pIDList, bool bSmartOrder, EEditAction eAction, int iOffset);
|
||||
bool EditGroup(DownloadQueue* pDownloadQueue, FileInfo* pFileInfo, EEditAction eAction, int iOffset);
|
||||
void BuildGroupList(DownloadQueue* pDownloadQueue, FileList* pGroupList);
|
||||
@@ -81,10 +80,6 @@ private:
|
||||
void AlignGroup(DownloadQueue* pDownloadQueue, FileInfo* pFirstFileInfo);
|
||||
void PauseParsInGroups(ItemList* pItemList, bool bExtraParsOnly);
|
||||
void PausePars(FileList* pFileList, bool bExtraParsOnly);
|
||||
void SetNZBCategory(NZBInfo* pNZBInfo, const char* szCategory);
|
||||
bool CanCleanupDisk(DownloadQueue* pDownloadQueue, NZBInfo* pNZBInfo);
|
||||
void MergeGroups(DownloadQueue* pDownloadQueue, ItemList* pItemList);
|
||||
void SetNZBParameter(NZBInfo* pNZBInfo, const char* szParamString);
|
||||
|
||||
void PauseUnpauseEntry(FileInfo* pFileInfo, bool bPause);
|
||||
void DeleteEntry(FileInfo* pFileInfo);
|
||||
@@ -94,11 +89,10 @@ public:
|
||||
QueueEditor();
|
||||
~QueueEditor();
|
||||
|
||||
bool EditEntry(int ID, bool bSmartOrder, EEditAction eAction, int iOffset, const char* szText);
|
||||
bool EditList(IDList* pIDList, bool bSmartOrder, EEditAction eAction, int iOffset, const char* szText);
|
||||
bool EditEntry(int ID, bool bSmartOrder, EEditAction eAction, int iOffset);
|
||||
bool EditList(IDList* pIDList, bool bSmartOrder, EEditAction eAction, int iOffset);
|
||||
|
||||
bool LockedEditEntry(DownloadQueue* pDownloadQueue, int ID, bool bSmartOrder, EEditAction eAction, int iOffset, const char* szText);
|
||||
bool LockedEditList(DownloadQueue* pDownloadQueue, IDList* pIDList, bool bSmartOrder, EEditAction eAction, int iOffset, const char* szText);
|
||||
bool LockedEditEntry(DownloadQueue* pDownloadQueue, int ID, bool bSmartOrder, EEditAction eAction, int iOffset);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
142
README
142
README
@@ -41,14 +41,17 @@ NZBGet is written in C++ and was initialy developed on Linux.
|
||||
It was ported to Windows later and tested for compatibility with
|
||||
several POSIX-OS'es.
|
||||
|
||||
The current version (0.7.0) should run at least on:
|
||||
The current version (0.4.1) should run at least on:
|
||||
- Linux Debian 4.0 on x86;
|
||||
- Linux with uClibc and BusyBox on MIPSEL and ARM;
|
||||
- FreeBSD 7.0 on x86;
|
||||
- OpenSolaris 2008.11 on x86;
|
||||
- Mac OS X;
|
||||
- Linux BusyBox with uClibc on MIPSEL;
|
||||
- PC-BSD 1.4 (based on FreeBSD 6.2) on x86;
|
||||
- Windows XP SP2 on x86.
|
||||
|
||||
The previous version (0.3.0) was also tested on:
|
||||
- Linux Debian 3.1 on x86;
|
||||
- Solaris 10 on x86;
|
||||
- Linux Debian 3.1 on SPARC (QEmu).
|
||||
|
||||
Clients and servers running on different OS'es may communicate with
|
||||
each other. For example, you can use NZBGet as client on Windows to
|
||||
control your NZBGet-server running on Linux.
|
||||
@@ -83,11 +86,6 @@ And the following libraries are optional:
|
||||
- for par-check and -repair (enabled by default):
|
||||
- libpar2 (http://parchive.sourceforge.net)
|
||||
- libsigc++ (http://libsigc.sourceforge.net)
|
||||
|
||||
- for encrypted connections (TLS/SSL):
|
||||
- GnuTLS (http://www.gnu.org/software/gnutls)
|
||||
or
|
||||
- OpenSSL (http://www.openssl.org)
|
||||
|
||||
All these libraries are included in modern Linux distributions and
|
||||
should be available as installable packages. Please note that you also
|
||||
@@ -95,6 +93,7 @@ need the developer packages for these libraries too, they package names
|
||||
have often suffix "dev" or "devel". On other systems you may need to
|
||||
download the libraries at the given URLs and compile them (see hints below).
|
||||
|
||||
|
||||
=====================================
|
||||
4. Installation on POSIX
|
||||
=====================================
|
||||
@@ -126,12 +125,6 @@ You may run configure with additional arguments:
|
||||
|
||||
--disable-parcheck - to make without parcheck-support. Use this option
|
||||
if you can not use libpar2 or libsigc++.
|
||||
|
||||
--with-tlslib=(GnuTLS, OpenSSL) - to select which TLS/SSL library
|
||||
should be used for encrypted server connections.
|
||||
|
||||
--disable-tls - to make without TLS/SSL support. Use this option if
|
||||
you can not neither GnuTLS nor OpenSSL.
|
||||
|
||||
--enable-debug - to build in debug-mode, if you want to see and log
|
||||
debug-messages.
|
||||
@@ -143,6 +136,8 @@ it uses library par2 (libpar2), which needs sigc++ on its part.
|
||||
|
||||
The libpar2 and libsigc++ (version 2 or later) must be installed on your
|
||||
system. On most linux distributions these libraries are available as packages.
|
||||
So you only need to install theme and run configure with parameter
|
||||
"--enable-parcheck".
|
||||
If you do not have these packages you can compile them yourself.
|
||||
Following configure-parameters may be usefull:
|
||||
|
||||
@@ -153,26 +148,12 @@ Following configure-parameters may be usefull:
|
||||
|
||||
The library libsigc++ must be installed first, since libpar2 requires it.
|
||||
|
||||
If you use nzbget on a very slow computer like NAS-device, it may be good to
|
||||
limit the time allowed for par-repair (option "ParTimeLimit" in nzbget
|
||||
configuration file). This feature requires a patched version of libpar2.
|
||||
To compile that version download the original source code of libpar2
|
||||
(version 0.2) and apply patches "libpar2-0.2-bugfixes.patch" and
|
||||
"libpar2-0.2-cancel.patch", provided with nzbget:
|
||||
|
||||
cd libpar2-0.2
|
||||
cp ~/nzbget/libpar2-0.2-*.patch .
|
||||
patch < libpar2-0.2-bugfixes.patch
|
||||
patch < libpar2-0.2-cancel.patch
|
||||
./configure
|
||||
make
|
||||
make install
|
||||
|
||||
If you are not able to use libpar2 or libsigc++ or do not want them you can
|
||||
make nzbget without support for par-check using option "--disable-parcheck":
|
||||
make the program without support for par-check using option
|
||||
"--disable-parcheck":
|
||||
|
||||
./configure --disable-parcheck
|
||||
|
||||
|
||||
Optional package: curses
|
||||
-------------------------
|
||||
For curses-outputmode you need ncurses or curses on your system.
|
||||
@@ -187,29 +168,6 @@ make the program without support for curses using option "--disable-curses":
|
||||
|
||||
./configure --disable-curses
|
||||
|
||||
Optional package: TLS
|
||||
-------------------------
|
||||
To enable encrypted server connections (TLS/SSL) you need to build the program
|
||||
with TLS/SSL support. NZBGet can use two libraries: GnuTLS or OpenSSL.
|
||||
Configure-script checks which library is installed and use it. If both are
|
||||
avialable it gives the precedence to GnuTLS. You may override that with
|
||||
the option --with-tlslib=(GnuTLS, OpenSSL). For example to build whith OpenSSL:
|
||||
|
||||
./configure --with-tlslib=OpenSSL
|
||||
|
||||
Following configure-parameters may be usefull:
|
||||
|
||||
--with-libtls-includes
|
||||
--with-libtls-libraries
|
||||
|
||||
--with-openssl-includes
|
||||
--with-openssl-libraries
|
||||
|
||||
If none of these libraries is available you can make the program without
|
||||
TLS/SSL support using option "--disable-tls":
|
||||
|
||||
./configure --disable-tls
|
||||
|
||||
=====================================
|
||||
5. Compiling on Windows
|
||||
=====================================
|
||||
@@ -223,23 +181,15 @@ libraries:
|
||||
|
||||
- libsigc++ (http://libsigc.sourceforge.net)
|
||||
- libpar2 (http://parchive.sourceforge.net)
|
||||
|
||||
|
||||
Download these libaries, then use patch-files provided with NZBGet to create
|
||||
preconfigured project files and solutions for each library.
|
||||
Look at http://gnuwin32.sourceforge.net/packages/patch.htm for info on how
|
||||
to use patch-files, if you do not familiar with this technique.
|
||||
|
||||
To compile the program with TLS/SSL support you also need the library:
|
||||
|
||||
- GnuTLS (http://www.gnu.org/software/gnutls)
|
||||
|
||||
Download a precompiled version of GnuTLS from http://josefsson.org/gnutls4win
|
||||
and create lib-file as described there in section "Using the GnuTLS DLL from
|
||||
your Visual Studio program".
|
||||
|
||||
After libsigc++ and libpar2 are compiled in static libraries (.lib), the
|
||||
library for GnuTLS is created and include- and libraries-paths are configured
|
||||
in MS Visual C++ 2005 you should be able to compile NZBGet.
|
||||
After libsigc++ and libpar2 are compiled in static libraries (.lib)
|
||||
and include- and libraries-paths are configured in MS Visual C++ 2005 you
|
||||
should be able to compile NZBGet.
|
||||
|
||||
=====================================
|
||||
6. Configuration
|
||||
@@ -279,12 +229,6 @@ options via command-line.
|
||||
NZBGet can be used in either standalone mode which downloads a single file
|
||||
or as a server which is able to queue up numerous download requests.
|
||||
|
||||
TIP for Windows users: NZBGet is controlled via various command line
|
||||
parameters. For easier using there is a simple shell script included
|
||||
in "nzbget-shell.bat". Start this script from Windows Explorer and you will
|
||||
be running a command shell with PATH adjusted to find NZBGet executable.
|
||||
Then you can type all commands without full path to nzbget.exe.
|
||||
|
||||
Standalone mode:
|
||||
----------------
|
||||
|
||||
@@ -312,16 +256,10 @@ To stop server use:
|
||||
|
||||
nzbget -Q
|
||||
|
||||
TIP for POSIX users: with included script "nzbgetd" you can use standard
|
||||
commands to control daemon:
|
||||
|
||||
nzbgetd start
|
||||
nzbgetd stop
|
||||
etc.
|
||||
|
||||
When NZBGet is started in console server mode it displays a message that
|
||||
it is ready to receive download requests. In daemon mode it doesn't print any
|
||||
messages to console since it runs in background.
|
||||
Depending on which frontend has been selected in the nzbget.conf file
|
||||
(option "outputmode") the server should display a message that
|
||||
it is ready to receive download requests (this applies only to console
|
||||
mode, not to daemon mode).
|
||||
|
||||
When the server is running it is possible to queue up downloads. This can be
|
||||
done either in terminal with "nzbget -A <nzb-file>" or by uploading
|
||||
@@ -399,58 +337,34 @@ 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.
|
||||
|
||||
Post processing scripts
|
||||
-----------------------
|
||||
|
||||
After the download of nzb-file is completed nzbget can call post-process-script,
|
||||
defined in configuration file. See example configuration file for the
|
||||
description of parameters passed to the script.
|
||||
|
||||
An example script for unraring of downloaded files is provided in file
|
||||
postprocess-example.sh. The usage instructions are included in the file,
|
||||
please open the file in any text editor to read them.
|
||||
NOTE: That example script is for POSIX systems (not for Windows).
|
||||
|
||||
=====================================
|
||||
8. Authors
|
||||
=====================================
|
||||
|
||||
NZBGet was initialiy written by Sven Henkel (sidddy@users.sourceforge.net).
|
||||
|
||||
Up to version 0.2.3 it was developed and maintained by Bo Cordes Petersen
|
||||
(placebodk@users.sourceforge.net).
|
||||
|
||||
Beginning at version 0.3.0 the program is being developed by Andrei Prygounkov
|
||||
(hugbug@users.sourceforge.net).
|
||||
|
||||
Module TLS (TLS.c, TLS.h) is based on work by Martin Lambers (marlam@marlam.de).
|
||||
Up to version 0.2.3 it was been developed and maintained by Bo Cordes Petersen
|
||||
(placebodk@users.sourceforge.net). Beginning at version 0.3.0 the program is
|
||||
being developed by Andrei Prygounkov (hugbug@users.sourceforge.net).
|
||||
|
||||
=====================================
|
||||
9. Copyright
|
||||
=====================================
|
||||
|
||||
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.
|
||||
|
||||
NZBGet is distributed under GNU General Pubic License Version 2.
|
||||
The complete content of license is provided in file COPYING.
|
||||
|
||||
Additional exemption: compiling, linking, and/or using OpenSSL is allowed.
|
||||
|
||||
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)
|
||||
|
||||
libpar2 is distributed under GPL; libsigc++ and GnuTLS - under LGPL.
|
||||
libpar2 is distributed under GPL and libsigc++ under LGPL.
|
||||
|
||||
=====================================
|
||||
10. Contact
|
||||
=====================================
|
||||
|
||||
If you encounter any problem, feel free to use forums on
|
||||
If you encounter any problem, feel free to use tracker/forums on
|
||||
|
||||
sourceforge.net/projects/nzbget
|
||||
|
||||
|
||||
484
RemoteClient.cpp
484
RemoteClient.cpp
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2005 Bo Cordes Petersen <placebodk@sourceforge.net>
|
||||
* Copyright (C) 2007-2010 Andrei Prygounkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2005 Bo Cordes Petersen <placebodk@sourceforge.net>
|
||||
* Copyright (C) 2007 Andrei Prygounkov <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
|
||||
@@ -46,6 +46,7 @@
|
||||
|
||||
#include "nzbget.h"
|
||||
#include "RemoteClient.h"
|
||||
#include "DownloadInfo.h"
|
||||
#include "Options.h"
|
||||
#include "Log.h"
|
||||
#include "Util.h"
|
||||
@@ -63,7 +64,7 @@ RemoteClient::RemoteClient()
|
||||
printf("sizeof(SNZBDownloadRequest)=%i\n", sizeof(SNZBDownloadRequest));
|
||||
printf("sizeof(SNZBListRequest)=%i\n", sizeof(SNZBListRequest));
|
||||
printf("sizeof(SNZBListResponse)=%i\n", sizeof(SNZBListResponse));
|
||||
printf("sizeof(SNZBListResponseFileEntry)=%i\n", sizeof(SNZBListResponseFileEntry));
|
||||
printf("sizeof(SNZBListResponseEntry)=%i\n", sizeof(SNZBListResponseEntry));
|
||||
printf("sizeof(SNZBLogRequest)=%i\n", sizeof(SNZBLogRequest));
|
||||
printf("sizeof(SNZBLogResponse)=%i\n", sizeof(SNZBLogResponse));
|
||||
printf("sizeof(SNZBLogResponseEntry)=%i\n", sizeof(SNZBLogResponseEntry));
|
||||
@@ -112,7 +113,7 @@ bool RemoteClient::InitConnection()
|
||||
m_pNetAddress = new NetAddress(g_pOptions->GetServerIP(), g_pOptions->GetServerPort());
|
||||
m_pConnection = new Connection(m_pNetAddress);
|
||||
|
||||
bool OK = m_pConnection->Connect();
|
||||
bool OK = m_pConnection->Connect() >= 0;
|
||||
if (!OK)
|
||||
{
|
||||
printf("Unable to send request to nzbserver at %s (port %i)\n", g_pOptions->GetServerIP(), g_pOptions->GetServerPort());
|
||||
@@ -177,14 +178,14 @@ bool RemoteClient::ReceiveBoolResponse()
|
||||
/*
|
||||
* Sends a message to the running nzbget process.
|
||||
*/
|
||||
bool RemoteClient::RequestServerDownload(const char* szFilename, const char* szCategory, bool bAddFirst)
|
||||
bool RemoteClient::RequestServerDownload(const char* szName, bool bAddFirst)
|
||||
{
|
||||
// Read the file into the buffer
|
||||
char* szBuffer = NULL;
|
||||
int iLength = 0;
|
||||
if (!Util::LoadFileIntoBuffer(szFilename, &szBuffer, &iLength))
|
||||
if (!Util::LoadFileIntoBuffer(szName, &szBuffer, &iLength))
|
||||
{
|
||||
printf("Could not load file %s\n", szFilename);
|
||||
printf("Could not load file %s\n", szName);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -196,14 +197,8 @@ bool RemoteClient::RequestServerDownload(const char* szFilename, const char* szC
|
||||
DownloadRequest.m_bAddFirst = htonl(bAddFirst);
|
||||
DownloadRequest.m_iTrailingDataLength = htonl(iLength);
|
||||
|
||||
strncpy(DownloadRequest.m_szFilename, szFilename, NZBREQUESTFILENAMESIZE - 1);
|
||||
strncpy(DownloadRequest.m_szFilename, szName, NZBREQUESTFILENAMESIZE - 1);
|
||||
DownloadRequest.m_szFilename[NZBREQUESTFILENAMESIZE-1] = '\0';
|
||||
DownloadRequest.m_szCategory[0] = '\0';
|
||||
if (szCategory)
|
||||
{
|
||||
strncpy(DownloadRequest.m_szCategory, szCategory, NZBREQUESTFILENAMESIZE - 1);
|
||||
}
|
||||
DownloadRequest.m_szCategory[NZBREQUESTFILENAMESIZE-1] = '\0';
|
||||
|
||||
if (m_pConnection->Send((char*)(&DownloadRequest), sizeof(DownloadRequest)) < 0)
|
||||
{
|
||||
@@ -227,84 +222,7 @@ bool RemoteClient::RequestServerDownload(const char* szFilename, const char* szC
|
||||
return OK;
|
||||
}
|
||||
|
||||
void RemoteClient::BuildFileList(SNZBListResponse* pListResponse, const char* pTrailingData, DownloadQueue* pDownloadQueue)
|
||||
{
|
||||
if (ntohl(pListResponse->m_iTrailingDataLength) > 0)
|
||||
{
|
||||
const char* pBufPtr = pTrailingData;
|
||||
|
||||
// read nzb entries
|
||||
for (unsigned int i = 0; i < ntohl(pListResponse->m_iNrTrailingNZBEntries); i++)
|
||||
{
|
||||
SNZBListResponseNZBEntry* pListAnswer = (SNZBListResponseNZBEntry*) pBufPtr;
|
||||
|
||||
const char* szFileName = pBufPtr + sizeof(SNZBListResponseNZBEntry);
|
||||
const char* szDestDir = pBufPtr + sizeof(SNZBListResponseNZBEntry) + ntohl(pListAnswer->m_iFilenameLen);
|
||||
const char* szCategory = pBufPtr + sizeof(SNZBListResponseNZBEntry) + ntohl(pListAnswer->m_iFilenameLen) + ntohl(pListAnswer->m_iDestDirLen);
|
||||
const char* m_szQueuedFilename = pBufPtr + sizeof(SNZBListResponseNZBEntry) + ntohl(pListAnswer->m_iFilenameLen) + ntohl(pListAnswer->m_iDestDirLen) + ntohl(pListAnswer->m_iCategoryLen);
|
||||
|
||||
NZBInfo* pNZBInfo = new NZBInfo();
|
||||
pNZBInfo->SetSize(Util::JoinInt64(ntohl(pListAnswer->m_iSizeHi), ntohl(pListAnswer->m_iSizeLo)));
|
||||
pNZBInfo->SetFilename(szFileName);
|
||||
pNZBInfo->SetDestDir(szDestDir);
|
||||
pNZBInfo->SetCategory(szCategory);
|
||||
pNZBInfo->SetQueuedFilename(m_szQueuedFilename);
|
||||
|
||||
pNZBInfo->AddReference();
|
||||
pDownloadQueue->GetNZBInfoList()->Add(pNZBInfo);
|
||||
|
||||
pBufPtr += sizeof(SNZBListResponseNZBEntry) + ntohl(pListAnswer->m_iFilenameLen) +
|
||||
ntohl(pListAnswer->m_iDestDirLen) + ntohl(pListAnswer->m_iCategoryLen) +
|
||||
ntohl(pListAnswer->m_iQueuedFilenameLen);
|
||||
}
|
||||
|
||||
//read ppp entries
|
||||
for (unsigned int i = 0; i < ntohl(pListResponse->m_iNrTrailingPPPEntries); i++)
|
||||
{
|
||||
SNZBListResponsePPPEntry* pListAnswer = (SNZBListResponsePPPEntry*) pBufPtr;
|
||||
|
||||
const char* szName = pBufPtr + sizeof(SNZBListResponsePPPEntry);
|
||||
const char* szValue = pBufPtr + sizeof(SNZBListResponsePPPEntry) + ntohl(pListAnswer->m_iNameLen);
|
||||
|
||||
NZBInfo* pNZBInfo = pDownloadQueue->GetNZBInfoList()->at(ntohl(pListAnswer->m_iNZBIndex) - 1);
|
||||
pNZBInfo->SetParameter(szName, szValue);
|
||||
|
||||
pBufPtr += sizeof(SNZBListResponsePPPEntry) + ntohl(pListAnswer->m_iNameLen) +
|
||||
ntohl(pListAnswer->m_iValueLen);
|
||||
}
|
||||
|
||||
//read file entries
|
||||
for (unsigned int i = 0; i < ntohl(pListResponse->m_iNrTrailingFileEntries); i++)
|
||||
{
|
||||
SNZBListResponseFileEntry* pListAnswer = (SNZBListResponseFileEntry*) pBufPtr;
|
||||
|
||||
const char* szSubject = pBufPtr + sizeof(SNZBListResponseFileEntry);
|
||||
const char* szFileName = pBufPtr + sizeof(SNZBListResponseFileEntry) + ntohl(pListAnswer->m_iSubjectLen);
|
||||
|
||||
FileInfo* pFileInfo = new FileInfo();
|
||||
pFileInfo->SetID(ntohl(pListAnswer->m_iID));
|
||||
pFileInfo->SetSize(Util::JoinInt64(ntohl(pListAnswer->m_iFileSizeHi), ntohl(pListAnswer->m_iFileSizeLo)));
|
||||
pFileInfo->SetRemainingSize(Util::JoinInt64(ntohl(pListAnswer->m_iRemainingSizeHi), ntohl(pListAnswer->m_iRemainingSizeLo)));
|
||||
pFileInfo->SetPaused(ntohl(pListAnswer->m_bPaused));
|
||||
pFileInfo->SetSubject(szSubject);
|
||||
pFileInfo->SetFilename(szFileName);
|
||||
pFileInfo->SetFilenameConfirmed(ntohl(pListAnswer->m_bFilenameConfirmed));
|
||||
|
||||
NZBInfo* pNZBInfo = pDownloadQueue->GetNZBInfoList()->at(ntohl(pListAnswer->m_iNZBIndex) - 1);
|
||||
|
||||
pFileInfo->SetNZBInfo(pNZBInfo);
|
||||
|
||||
pDownloadQueue->GetFileQueue()->push_back(pFileInfo);
|
||||
|
||||
pBufPtr += sizeof(SNZBListResponseFileEntry) + ntohl(pListAnswer->m_iSubjectLen) +
|
||||
ntohl(pListAnswer->m_iFilenameLen);
|
||||
}
|
||||
}
|
||||
|
||||
pDownloadQueue->GetNZBInfoList()->ReleaseAll();
|
||||
}
|
||||
|
||||
bool RemoteClient::RequestServerList(bool bFiles, bool bGroups)
|
||||
bool RemoteClient::RequestServerList()
|
||||
{
|
||||
if (!InitConnection()) return false;
|
||||
|
||||
@@ -352,190 +270,71 @@ bool RemoteClient::RequestServerList(bool bFiles, bool bGroups)
|
||||
|
||||
m_pConnection->Disconnect();
|
||||
|
||||
if (bFiles)
|
||||
if (ntohl(ListResponse.m_iTrailingDataLength) == 0)
|
||||
{
|
||||
if (ntohl(ListResponse.m_iTrailingDataLength) == 0)
|
||||
printf("Server has no files queued for download\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Queue List\n");
|
||||
printf("-----------------------------------\n");
|
||||
|
||||
long long lRemaining = 0;
|
||||
long long lPaused = 0;
|
||||
char* pBufPtr = (char*)pBuf;
|
||||
for (unsigned int i = 0; i < ntohl(ListResponse.m_iNrTrailingEntries); i++)
|
||||
{
|
||||
printf("Server has no files queued for download\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Queue List\n");
|
||||
printf("-----------------------------------\n");
|
||||
SNZBListResponseEntry* pListAnswer = (SNZBListResponseEntry*) pBufPtr;
|
||||
|
||||
DownloadQueue cRemoteQueue;
|
||||
BuildFileList(&ListResponse, pBuf, &cRemoteQueue);
|
||||
long long lFileSize = Util::JoinInt64(ntohl(pListAnswer->m_iFileSizeHi), ntohl(pListAnswer->m_iFileSizeLo));
|
||||
long long lRemainingSize = Util::JoinInt64(ntohl(pListAnswer->m_iRemainingSizeHi), ntohl(pListAnswer->m_iRemainingSizeLo));
|
||||
|
||||
long long lRemaining = 0;
|
||||
long long lPaused = 0;
|
||||
|
||||
for (FileQueue::iterator it = cRemoteQueue.GetFileQueue()->begin(); it != cRemoteQueue.GetFileQueue()->end(); it++)
|
||||
char szCompleted[100];
|
||||
szCompleted[0] = '\0';
|
||||
if (lRemainingSize < lFileSize)
|
||||
{
|
||||
FileInfo* pFileInfo = *it;
|
||||
|
||||
char szCompleted[100];
|
||||
szCompleted[0] = '\0';
|
||||
if (pFileInfo->GetRemainingSize() < pFileInfo->GetSize())
|
||||
{
|
||||
sprintf(szCompleted, ", %i%s", (int)(100 - Util::Int64ToFloat(pFileInfo->GetRemainingSize()) * 100.0 / Util::Int64ToFloat(pFileInfo->GetSize())), "%");
|
||||
}
|
||||
char szStatus[100];
|
||||
if (pFileInfo->GetPaused())
|
||||
{
|
||||
sprintf(szStatus, " (paused)");
|
||||
lPaused += pFileInfo->GetRemainingSize();
|
||||
}
|
||||
else
|
||||
{
|
||||
szStatus[0] = '\0';
|
||||
lRemaining += pFileInfo->GetRemainingSize();
|
||||
}
|
||||
|
||||
char szNZBNiceName[1024];
|
||||
pFileInfo->GetNZBInfo()->GetNiceNZBName(szNZBNiceName, 1024);
|
||||
|
||||
printf("[%i] %s%c%s (%.2f MB%s)%s\n", pFileInfo->GetID(), szNZBNiceName, (int)PATH_SEPARATOR, pFileInfo->GetFilename(),
|
||||
(float)(Util::Int64ToFloat(pFileInfo->GetSize()) / 1024.0 / 1024.0), szCompleted, szStatus);
|
||||
|
||||
delete pFileInfo;
|
||||
sprintf(szCompleted, ", %i%s", (int)(100 - Util::Int64ToFloat(lRemainingSize) * 100.0 / Util::Int64ToFloat(lFileSize)), "%");
|
||||
}
|
||||
|
||||
printf("-----------------------------------\n");
|
||||
printf("Files: %i\n", cRemoteQueue.GetFileQueue()->size());
|
||||
if (lPaused > 0)
|
||||
char szStatus[100];
|
||||
if (ntohl(pListAnswer->m_bPaused))
|
||||
{
|
||||
printf("Remaining size: %.2f MB (+%.2f MB paused)\n", (float)(Util::Int64ToFloat(lRemaining) / 1024.0 / 1024.0),
|
||||
(float)(Util::Int64ToFloat(lPaused) / 1024.0 / 1024.0));
|
||||
sprintf(szStatus, " (paused)");
|
||||
lPaused += lRemainingSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Remaining size: %.2f MB\n", (float)(Util::Int64ToFloat(lRemaining) / 1024.0 / 1024.0));
|
||||
szStatus[0] = '\0';
|
||||
lRemaining += lRemainingSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
char* szNZBFilename = pBufPtr + sizeof(SNZBListResponseEntry);
|
||||
char* szFilename = pBufPtr + sizeof(SNZBListResponseEntry) + ntohl(pListAnswer->m_iNZBFilenameLen) + ntohl(pListAnswer->m_iSubjectLen);
|
||||
|
||||
char szNZBNiceName[1024];
|
||||
NZBInfo::MakeNiceNZBName(szNZBFilename, szNZBNiceName, 1024);
|
||||
|
||||
printf("[%i] %s%c%s (%.2f MB%s)%s\n", ntohl(pListAnswer->m_iID), szNZBNiceName, (int)PATH_SEPARATOR, szFilename,
|
||||
(float)(Util::Int64ToFloat(lFileSize) / 1024.0 / 1024.0), szCompleted, szStatus);
|
||||
|
||||
if (bGroups)
|
||||
{
|
||||
if (ntohl(ListResponse.m_iTrailingDataLength) == 0)
|
||||
pBufPtr += sizeof(SNZBListResponseEntry) + ntohl(pListAnswer->m_iNZBFilenameLen) +
|
||||
ntohl(pListAnswer->m_iSubjectLen) + ntohl(pListAnswer->m_iFilenameLen) + ntohl(pListAnswer->m_iDestDirLen);
|
||||
}
|
||||
|
||||
printf("-----------------------------------\n");
|
||||
printf("Files: %i\n", ntohl(ListResponse.m_iNrTrailingEntries));
|
||||
if (lPaused > 0)
|
||||
{
|
||||
printf("Server has no files queued for download\n");
|
||||
printf("Remaining size: %.2f MB (+%.2f MB paused)\n", (float)(Util::Int64ToFloat(lRemaining) / 1024.0 / 1024.0),
|
||||
(float)(Util::Int64ToFloat(lPaused) / 1024.0 / 1024.0));
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Queue List\n");
|
||||
printf("-----------------------------------\n");
|
||||
|
||||
DownloadQueue cRemoteQueue;
|
||||
BuildFileList(&ListResponse, pBuf, &cRemoteQueue);
|
||||
|
||||
GroupQueue cGroupQueue;
|
||||
cRemoteQueue.BuildGroups(&cGroupQueue);
|
||||
|
||||
long long lRemaining = 0;
|
||||
long long lPaused = 0;
|
||||
|
||||
for (GroupQueue::iterator it = cGroupQueue.begin(); it != cGroupQueue.end(); it++)
|
||||
{
|
||||
GroupInfo* pGroupInfo = *it;
|
||||
|
||||
long long lUnpausedRemainingSize = pGroupInfo->GetRemainingSize() - pGroupInfo->GetPausedSize();
|
||||
lRemaining += lUnpausedRemainingSize;
|
||||
|
||||
char szRemaining[20];
|
||||
Util::FormatFileSize(szRemaining, sizeof(szRemaining), lUnpausedRemainingSize);
|
||||
|
||||
char szPaused[20];
|
||||
szPaused[0] = '\0';
|
||||
if (pGroupInfo->GetPausedSize() > 0)
|
||||
{
|
||||
char szPausedSize[20];
|
||||
Util::FormatFileSize(szPausedSize, sizeof(szPausedSize), pGroupInfo->GetPausedSize());
|
||||
sprintf(szPaused, " + %s paused", szPausedSize);
|
||||
lPaused += pGroupInfo->GetPausedSize();
|
||||
}
|
||||
|
||||
char szNZBNiceName[1024];
|
||||
pGroupInfo->GetNZBInfo()->GetNiceNZBName(szNZBNiceName, 1023);
|
||||
|
||||
char szCategory[1024];
|
||||
szCategory[0] = '\0';
|
||||
if (pGroupInfo->GetNZBInfo()->GetCategory() && strlen(pGroupInfo->GetNZBInfo()->GetCategory()) > 0)
|
||||
{
|
||||
sprintf(szCategory, " (%s)", pGroupInfo->GetNZBInfo()->GetCategory());
|
||||
}
|
||||
|
||||
char szParameters[1024];
|
||||
szParameters[0] = '\0';
|
||||
for (NZBParameterList::iterator it = pGroupInfo->GetNZBInfo()->GetParameters()->begin(); it != pGroupInfo->GetNZBInfo()->GetParameters()->end(); it++)
|
||||
{
|
||||
if (szParameters[0] == '\0')
|
||||
{
|
||||
strncat(szParameters, " (", 1024);
|
||||
}
|
||||
else
|
||||
{
|
||||
strncat(szParameters, ", ", 1024);
|
||||
}
|
||||
NZBParameter* pNZBParameter = *it;
|
||||
strncat(szParameters, pNZBParameter->GetName(), 1024);
|
||||
strncat(szParameters, "=", 1024);
|
||||
strncat(szParameters, pNZBParameter->GetValue(), 1024);
|
||||
}
|
||||
if (szParameters[0] != '\0')
|
||||
{
|
||||
strncat(szParameters, ")", 1024);
|
||||
}
|
||||
|
||||
printf("[%i-%i] %s (%i file%s, %s%s)%s%s\n", pGroupInfo->GetFirstID(), pGroupInfo->GetLastID(), szNZBNiceName,
|
||||
pGroupInfo->GetRemainingFileCount(), pGroupInfo->GetRemainingFileCount() > 1 ? "s" : "", szRemaining,
|
||||
szPaused, szCategory, szParameters);
|
||||
|
||||
delete pGroupInfo;
|
||||
}
|
||||
|
||||
for (FileQueue::iterator it = cRemoteQueue.GetFileQueue()->begin(); it != cRemoteQueue.GetFileQueue()->end(); it++)
|
||||
{
|
||||
delete *it;
|
||||
}
|
||||
|
||||
printf("-----------------------------------\n");
|
||||
printf("Groups: %i\n", cGroupQueue.size());
|
||||
printf("Files: %i\n", cRemoteQueue.GetFileQueue()->size());
|
||||
if (lPaused > 0)
|
||||
{
|
||||
printf("Remaining size: %.2f MB (+%.2f MB paused)\n", (float)(Util::Int64ToFloat(lRemaining) / 1024.0 / 1024.0),
|
||||
(float)(Util::Int64ToFloat(lPaused) / 1024.0 / 1024.0));
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Remaining size: %.2f MB\n", (float)(Util::Int64ToFloat(lRemaining) / 1024.0 / 1024.0));
|
||||
}
|
||||
printf("Remaining size: %.2f MB\n", (float)(Util::Int64ToFloat(lRemaining) / 1024.0 / 1024.0));
|
||||
}
|
||||
printf("Current download rate: %.1f KB/s\n", (float)(ntohl(ListResponse.m_iDownloadRate) / 1024.0));
|
||||
|
||||
free(pBuf);
|
||||
}
|
||||
|
||||
free(pBuf);
|
||||
|
||||
long long lRemaining = Util::JoinInt64(ntohl(ListResponse.m_iRemainingSizeHi), ntohl(ListResponse.m_iRemainingSizeLo));
|
||||
|
||||
if (!bFiles && !bGroups)
|
||||
{
|
||||
printf("Remaining size: %.2f MB\n", (float)(Util::Int64ToFloat(lRemaining) / 1024.0 / 1024.0));
|
||||
}
|
||||
|
||||
if (ntohl(ListResponse.m_iDownloadRate) > 0 &&
|
||||
!ntohl(ListResponse.m_bDownloadPaused) &&
|
||||
!ntohl(ListResponse.m_bDownload2Paused) &&
|
||||
!ntohl(ListResponse.m_bDownloadStandBy))
|
||||
{
|
||||
long long remain_sec = (long long)(lRemaining / ntohl(ListResponse.m_iDownloadRate));
|
||||
int h = (int)(remain_sec / 3600);
|
||||
int m = (int)((remain_sec % 3600) / 60);
|
||||
int s = (int)(remain_sec % 60);
|
||||
printf("Remaining time: %.2d:%.2d:%.2d\n", h, m, s);
|
||||
}
|
||||
|
||||
printf("Current download rate: %.1f KB/s\n", (float)(ntohl(ListResponse.m_iDownloadRate) / 1024.0));
|
||||
|
||||
long long iAllBytes = Util::JoinInt64(ntohl(ListResponse.m_iDownloadedBytesHi), ntohl(ListResponse.m_iDownloadedBytesLo));
|
||||
float fAverageSpeed = Util::Int64ToFloat(ntohl(ListResponse.m_iDownloadTimeSec) > 0 ? iAllBytes / ntohl(ListResponse.m_iDownloadTimeSec) : 0);
|
||||
printf("Session download rate: %.1f KB/s\n", (float)(fAverageSpeed / 1024.0));
|
||||
@@ -566,41 +365,15 @@ bool RemoteClient::RequestServerList(bool bFiles, bool bGroups)
|
||||
printf("Post-jobs: %i\n", (int)ntohl(ListResponse.m_iPostJobCount));
|
||||
}
|
||||
|
||||
if (ntohl(ListResponse.m_bScanPaused))
|
||||
if (ntohl(ListResponse.m_bServerStandBy))
|
||||
{
|
||||
printf("Scan state: Paused\n");
|
||||
}
|
||||
|
||||
char szServerState[50];
|
||||
|
||||
if (ntohl(ListResponse.m_bDownloadPaused) || ntohl(ListResponse.m_bDownload2Paused))
|
||||
{
|
||||
snprintf(szServerState, sizeof(szServerState), "%s%s",
|
||||
ntohl(ListResponse.m_bDownloadStandBy) ? "Paused" : "Pausing",
|
||||
ntohl(ListResponse.m_bDownloadPaused) && ntohl(ListResponse.m_bDownload2Paused) ?
|
||||
" (+2)" : ntohl(ListResponse.m_bDownload2Paused) ? " (2)" : "");
|
||||
printf("Server state: Stand-By\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(szServerState, sizeof(szServerState), "%s", ntohl(ListResponse.m_bDownloadStandBy) ? "" : "Downloading");
|
||||
printf("Server state: %s\n", ntohl(ListResponse.m_bServerPaused) ? "Paused" : "Downloading");
|
||||
}
|
||||
|
||||
if (ntohl(ListResponse.m_iPostJobCount) > 0 || ntohl(ListResponse.m_bPostPaused))
|
||||
{
|
||||
strncat(szServerState, strlen(szServerState) > 0 ? ", Post-Processing" : "Post-Processing", sizeof(szServerState));
|
||||
if (ntohl(ListResponse.m_bPostPaused))
|
||||
{
|
||||
strncat(szServerState, " paused", sizeof(szServerState));
|
||||
}
|
||||
}
|
||||
|
||||
if (strlen(szServerState) == 0)
|
||||
{
|
||||
strncpy(szServerState, "Stand-By", sizeof(szServerState));
|
||||
}
|
||||
|
||||
printf("Server state: %s\n", szServerState);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -697,14 +470,13 @@ bool RemoteClient::RequestServerLog(int iLines)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RemoteClient::RequestServerPauseUnpause(bool bPause, eRemotePauseUnpauseAction iAction)
|
||||
bool RemoteClient::RequestServerPauseUnpause(bool bPause)
|
||||
{
|
||||
if (!InitConnection()) return false;
|
||||
|
||||
SNZBPauseUnpauseRequest PauseUnpauseRequest;
|
||||
InitMessageBase(&PauseUnpauseRequest.m_MessageBase, eRemoteRequestPauseUnpause, sizeof(PauseUnpauseRequest));
|
||||
PauseUnpauseRequest.m_bPause = htonl(bPause);
|
||||
PauseUnpauseRequest.m_iAction = htonl(iAction);
|
||||
|
||||
if (m_pConnection->Send((char*)(&PauseUnpauseRequest), sizeof(PauseUnpauseRequest)) < 0)
|
||||
{
|
||||
@@ -760,7 +532,7 @@ bool RemoteClient::RequestServerDumpDebug()
|
||||
return OK;
|
||||
}
|
||||
|
||||
bool RemoteClient::RequestServerEditQueue(eRemoteEditAction iAction, int iOffset, const char* szText, int* pIDList, int iIDCount, bool bSmartOrder)
|
||||
bool RemoteClient::RequestServerEditQueue(int iAction, int iOffset, int* pIDList, int iIDCount, bool bSmartOrder)
|
||||
{
|
||||
if (iIDCount <= 0 || pIDList == NULL)
|
||||
{
|
||||
@@ -770,28 +542,17 @@ bool RemoteClient::RequestServerEditQueue(eRemoteEditAction iAction, int iOffset
|
||||
|
||||
if (!InitConnection()) return false;
|
||||
|
||||
int iTextLen = szText ? strlen(szText) + 1 : 0;
|
||||
// align size to 4-bytes, needed by ARM-processor (and may be others)
|
||||
iTextLen += iTextLen % 4 > 0 ? 4 - iTextLen % 4 : 0;
|
||||
int iLength = sizeof(int32_t) * iIDCount + iTextLen;
|
||||
int iLength = sizeof(int32_t) * iIDCount;
|
||||
|
||||
SNZBEditQueueRequest EditQueueRequest;
|
||||
InitMessageBase(&EditQueueRequest.m_MessageBase, eRemoteRequestEditQueue, sizeof(EditQueueRequest));
|
||||
EditQueueRequest.m_iAction = htonl(iAction);
|
||||
EditQueueRequest.m_iOffset = htonl((int)iOffset);
|
||||
EditQueueRequest.m_bSmartOrder = htonl(bSmartOrder);
|
||||
EditQueueRequest.m_iTextLen = htonl(iTextLen);
|
||||
EditQueueRequest.m_iNrTrailingEntries = htonl(iIDCount);
|
||||
EditQueueRequest.m_iTrailingDataLength = htonl(iLength);
|
||||
|
||||
char* pTrailingData = (char*)malloc(iLength);
|
||||
|
||||
if (iTextLen > 0)
|
||||
{
|
||||
strcpy(pTrailingData, szText);
|
||||
}
|
||||
|
||||
int32_t* pIDs = (int32_t*)(pTrailingData + iTextLen);
|
||||
int32_t* pIDs = (int32_t*)malloc(iLength);
|
||||
|
||||
for (int i = 0; i < iIDCount; i++)
|
||||
{
|
||||
@@ -805,12 +566,12 @@ bool RemoteClient::RequestServerEditQueue(eRemoteEditAction iAction, int iOffset
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pConnection->Send(pTrailingData, iLength);
|
||||
m_pConnection->Send((char*)pIDs, iLength);
|
||||
OK = ReceiveBoolResponse();
|
||||
m_pConnection->Disconnect();
|
||||
}
|
||||
|
||||
free(pTrailingData);
|
||||
free(pIDs);
|
||||
|
||||
m_pConnection->Disconnect();
|
||||
return OK;
|
||||
@@ -906,7 +667,7 @@ bool RemoteClient::RequestPostQueue()
|
||||
|
||||
if (ntohl(PostQueueResponse.m_iTrailingDataLength) == 0)
|
||||
{
|
||||
printf("Server has no jobs queued for post-processing\n");
|
||||
printf("Server has no files queued for post-processing\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -967,116 +728,3 @@ bool RemoteClient::RequestWriteLog(int iKind, const char* szText)
|
||||
m_pConnection->Disconnect();
|
||||
return OK;
|
||||
}
|
||||
|
||||
bool RemoteClient::RequestScan()
|
||||
{
|
||||
if (!InitConnection()) return false;
|
||||
|
||||
SNZBScanRequest ScanRequest;
|
||||
InitMessageBase(&ScanRequest.m_MessageBase, eRemoteRequestScan, sizeof(ScanRequest));
|
||||
|
||||
bool OK = m_pConnection->Send((char*)(&ScanRequest), sizeof(ScanRequest)) >= 0;
|
||||
if (OK)
|
||||
{
|
||||
OK = ReceiveBoolResponse();
|
||||
}
|
||||
else
|
||||
{
|
||||
perror("m_pConnection->Send");
|
||||
}
|
||||
|
||||
m_pConnection->Disconnect();
|
||||
return OK;
|
||||
}
|
||||
|
||||
bool RemoteClient::RequestHistory()
|
||||
{
|
||||
if (!InitConnection()) return false;
|
||||
|
||||
SNZBHistoryRequest HistoryRequest;
|
||||
InitMessageBase(&HistoryRequest.m_MessageBase, eRemoteRequestHistory, sizeof(HistoryRequest));
|
||||
|
||||
if (m_pConnection->Send((char*)(&HistoryRequest), sizeof(HistoryRequest)) < 0)
|
||||
{
|
||||
perror("m_pConnection->Send");
|
||||
return false;
|
||||
}
|
||||
|
||||
printf("Request sent\n");
|
||||
|
||||
// Now listen for the returned list
|
||||
SNZBHistoryResponse HistoryResponse;
|
||||
int iResponseLen = m_pConnection->Recv((char*) &HistoryResponse, sizeof(HistoryResponse));
|
||||
if (iResponseLen != sizeof(HistoryResponse) ||
|
||||
(int)ntohl(HistoryResponse.m_MessageBase.m_iSignature) != (int)NZBMESSAGE_SIGNATURE ||
|
||||
ntohl(HistoryResponse.m_MessageBase.m_iStructSize) != sizeof(HistoryResponse))
|
||||
{
|
||||
if (iResponseLen < 0)
|
||||
{
|
||||
printf("No response received (timeout)\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Invalid response received: either not nzbget-server or wrong server version\n");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
char* pBuf = NULL;
|
||||
if (ntohl(HistoryResponse.m_iTrailingDataLength) > 0)
|
||||
{
|
||||
pBuf = (char*)malloc(ntohl(HistoryResponse.m_iTrailingDataLength));
|
||||
if (!m_pConnection->RecvAll(pBuf, ntohl(HistoryResponse.m_iTrailingDataLength)))
|
||||
{
|
||||
free(pBuf);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
m_pConnection->Disconnect();
|
||||
|
||||
if (ntohl(HistoryResponse.m_iTrailingDataLength) == 0)
|
||||
{
|
||||
printf("Server has no files in history\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("History (most recent first)\n");
|
||||
printf("-----------------------------------\n");
|
||||
|
||||
char* pBufPtr = (char*)pBuf;
|
||||
for (unsigned int i = 0; i < ntohl(HistoryResponse.m_iNrTrailingEntries); i++)
|
||||
{
|
||||
SNZBHistoryResponseEntry* pListAnswer = (SNZBHistoryResponseEntry*) pBufPtr;
|
||||
|
||||
const char* szFileName = pBufPtr + sizeof(SNZBHistoryResponseEntry);
|
||||
|
||||
long long lSize = Util::JoinInt64(ntohl(pListAnswer->m_iSizeHi), ntohl(pListAnswer->m_iSizeLo));
|
||||
|
||||
char szNZBNiceName[1024];
|
||||
NZBInfo::MakeNiceNZBName(szFileName, szNZBNiceName, 1024);
|
||||
|
||||
char szSize[20];
|
||||
Util::FormatFileSize(szSize, sizeof(szSize), lSize);
|
||||
|
||||
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), szNZBNiceName,
|
||||
ntohl(pListAnswer->m_iFileCount), szSize,
|
||||
szParStatusText[ntohl(pListAnswer->m_iParStatus)],
|
||||
szScriptStatusText[ntohl(pListAnswer->m_iScriptStatus)]);
|
||||
|
||||
pBufPtr += sizeof(SNZBHistoryResponseEntry) + ntohl(pListAnswer->m_iFilenameLen) +
|
||||
ntohl(pListAnswer->m_iDestDirLen) + ntohl(pListAnswer->m_iCategoryLen) +
|
||||
ntohl(pListAnswer->m_iQueuedFilenameLen);
|
||||
}
|
||||
|
||||
printf("-----------------------------------\n");
|
||||
printf("Items: %i\n", ntohl(HistoryResponse.m_iNrTrailingEntries));
|
||||
}
|
||||
|
||||
free(pBuf);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
* This file if part of nzbget
|
||||
*
|
||||
* Copyright (C) 2005 Bo Cordes Petersen <placebodk@users.sourceforge.net>
|
||||
* Copyright (C) 2007-2009 Andrei Prygounkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2005 Bo Cordes Petersen <placebodk@users.sourceforge.net>
|
||||
* Copyright (C) 2007 Andrei Prygounkov <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
|
||||
@@ -30,7 +30,6 @@
|
||||
#include "Options.h"
|
||||
#include "MessageBase.h"
|
||||
#include "Connection.h"
|
||||
#include "DownloadInfo.h"
|
||||
|
||||
class RemoteClient
|
||||
{
|
||||
@@ -46,23 +45,20 @@ private:
|
||||
void perror(const char* msg);
|
||||
|
||||
public:
|
||||
RemoteClient();
|
||||
~RemoteClient();
|
||||
RemoteClient();
|
||||
~RemoteClient();
|
||||
void SetVerbose(bool bVerbose) { m_bVerbose = bVerbose; };
|
||||
bool RequestServerDownload(const char* szFilename, const char* szCategory, bool bAddFirst);
|
||||
bool RequestServerList(bool bFiles, bool bGroups);
|
||||
bool RequestServerPauseUnpause(bool bPause, eRemotePauseUnpauseAction iAction);
|
||||
bool RequestServerDownload(const char* szName, bool bAddFirst);
|
||||
bool RequestServerList();
|
||||
bool RequestServerPauseUnpause(bool bPause);
|
||||
bool RequestServerSetDownloadRate(float fRate);
|
||||
bool RequestServerDumpDebug();
|
||||
bool RequestServerEditQueue(eRemoteEditAction iAction, int iOffset, const char* szText, int* pIDList, int iIDCount, bool bSmartOrder);
|
||||
bool RequestServerEditQueue(int iAction, int iOffset, int* pIDList, int iIDCount, bool bSmartOrder);
|
||||
bool RequestServerLog(int iLines);
|
||||
bool RequestServerShutdown();
|
||||
bool RequestServerVersion();
|
||||
bool RequestPostQueue();
|
||||
bool RequestWriteLog(int iKind, const char* szText);
|
||||
bool RequestScan();
|
||||
bool RequestHistory();
|
||||
void BuildFileList(SNZBListResponse* pListResponse, const char* pTrailingData, DownloadQueue* pDownloadQueue);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2005 Bo Cordes Petersen <placebodk@sourceforge.net>
|
||||
* Copyright (C) 2007-2009 Andrei Prygounkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2005 Bo Cordes Petersen <placebodk@sourceforge.net>
|
||||
* Copyright (C) 2007 Andrei Prygounkov <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
|
||||
@@ -155,7 +155,7 @@ void RequestProcessor::Run()
|
||||
#endif
|
||||
struct sockaddr_in PeerName;
|
||||
int iPeerNameLength = sizeof(PeerName);
|
||||
if (getpeername(m_iSocket, (struct sockaddr*)&PeerName, (SOCKLEN_T*) &iPeerNameLength) >= 0)
|
||||
if (getpeername(m_iSocket, (struct sockaddr*)&PeerName, (socklen_t*) &iPeerNameLength) >= 0)
|
||||
{
|
||||
#ifdef WIN32
|
||||
ip = inet_ntoa(PeerName.sin_addr);
|
||||
@@ -202,10 +202,6 @@ void RequestProcessor::Run()
|
||||
{
|
||||
eProtocol = XmlRpcProcessor::rpJsonRpc;
|
||||
}
|
||||
else if (!strcmp(szUrl, "/jsonprpc") || !strncmp(szUrl, "/jsonprpc/", 10))
|
||||
{
|
||||
eProtocol = XmlRpcProcessor::rpJsonPRpc;
|
||||
}
|
||||
|
||||
if (eProtocol != XmlRpcProcessor::rpUndefined)
|
||||
{
|
||||
|
||||
363
Scanner.cpp
363
Scanner.cpp
@@ -1,363 +0,0 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2007-2010 Andrei Prygounkov <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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#include "win32.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fstream>
|
||||
#ifdef WIN32
|
||||
#include <direct.h>
|
||||
#endif
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "nzbget.h"
|
||||
#include "Scanner.h"
|
||||
#include "Options.h"
|
||||
#include "Log.h"
|
||||
#include "QueueCoordinator.h"
|
||||
#include "ScriptController.h"
|
||||
#include "DiskState.h"
|
||||
#include "Util.h"
|
||||
|
||||
extern QueueCoordinator* g_pQueueCoordinator;
|
||||
extern Options* g_pOptions;
|
||||
extern DiskState* g_pDiskState;
|
||||
|
||||
Scanner::FileData::FileData(const char* szFilename)
|
||||
{
|
||||
m_szFilename = strdup(szFilename);
|
||||
m_iSize = 0;
|
||||
m_tLastChange = 0;
|
||||
}
|
||||
|
||||
Scanner::FileData::~FileData()
|
||||
{
|
||||
free(m_szFilename);
|
||||
}
|
||||
|
||||
Scanner::Scanner()
|
||||
{
|
||||
debug("Creating Scanner");
|
||||
|
||||
m_bRequestedNZBDirScan = 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;
|
||||
}
|
||||
|
||||
Scanner::~Scanner()
|
||||
{
|
||||
debug("Destroying Scanner");
|
||||
|
||||
for (FileList::iterator it = m_FileList.begin(); it != m_FileList.end(); it++)
|
||||
{
|
||||
delete *it;
|
||||
}
|
||||
m_FileList.clear();
|
||||
}
|
||||
|
||||
void Scanner::Check()
|
||||
{
|
||||
if (g_pOptions->GetNzbDir() && (m_bRequestedNZBDirScan ||
|
||||
(!g_pOptions->GetPauseScan() && g_pOptions->GetNzbDirInterval() > 0 &&
|
||||
m_iNZBDirInterval >= g_pOptions->GetNzbDirInterval() * 1000)))
|
||||
{
|
||||
// check nzbdir every g_pOptions->GetNzbDirInterval() seconds or if requested
|
||||
bool bCheckStat = !m_bRequestedNZBDirScan;
|
||||
m_bRequestedNZBDirScan = false;
|
||||
CheckIncomingNZBs(g_pOptions->GetNzbDir(), "", bCheckStat);
|
||||
m_iNZBDirInterval = 0;
|
||||
|
||||
// if NzbDirFileAge is less than NzbDirInterval (that can happen if NzbDirInterval
|
||||
// is set for rare scans like once per hour) we make 4 scans:
|
||||
// - 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->GetNzbDirFileAge() < g_pOptions->GetNzbDirInterval())
|
||||
{
|
||||
int iMaxPass = m_bNZBScript ? 3 : 1;
|
||||
if (m_iPass < iMaxPass)
|
||||
{
|
||||
// scheduling another scan of incoming directory in NzbDirFileAge seconds.
|
||||
m_iNZBDirInterval = (g_pOptions->GetNzbDirInterval() - g_pOptions->GetNzbDirFileAge()) * 1000;
|
||||
m_iPass++;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_iPass = 0;
|
||||
}
|
||||
}
|
||||
|
||||
DropOldFiles();
|
||||
}
|
||||
m_iNZBDirInterval += m_iStepMSec;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if there are files in directory for incoming nzb-files
|
||||
* and add them to download queue
|
||||
*/
|
||||
void Scanner::CheckIncomingNZBs(const char* szDirectory, const char* szCategory, bool bCheckStat)
|
||||
{
|
||||
DirBrowser dir(szDirectory);
|
||||
while (const char* filename = dir.Next())
|
||||
{
|
||||
struct stat buffer;
|
||||
char fullfilename[1023 + 1]; // one char reserved for the trailing slash (if needed)
|
||||
snprintf(fullfilename, 1023, "%s%s", szDirectory, filename);
|
||||
fullfilename[1023 - 1] = '\0';
|
||||
if (!stat(fullfilename, &buffer))
|
||||
{
|
||||
// check subfolders
|
||||
if ((buffer.st_mode & S_IFDIR) != 0 && strcmp(filename, ".") && strcmp(filename, ".."))
|
||||
{
|
||||
fullfilename[strlen(fullfilename) + 1] = '\0';
|
||||
fullfilename[strlen(fullfilename)] = PATH_SEPARATOR;
|
||||
const char* szUseCategory = filename;
|
||||
char szSubCategory[1024];
|
||||
if (strlen(szCategory) > 0)
|
||||
{
|
||||
snprintf(szSubCategory, 1023, "%s%c%s", szCategory, PATH_SEPARATOR, filename);
|
||||
szSubCategory[1024 - 1] = '\0';
|
||||
szUseCategory = szSubCategory;
|
||||
}
|
||||
CheckIncomingNZBs(fullfilename, szUseCategory, bCheckStat);
|
||||
}
|
||||
else if ((buffer.st_mode & S_IFDIR) == 0 && CanProcessFile(fullfilename, bCheckStat))
|
||||
{
|
||||
ProcessIncomingFile(szDirectory, filename, fullfilename, szCategory);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Only files which were not changed during last g_pOptions->GetNzbDirFileAge() seconds
|
||||
* can be processed. That prevents the processing of files, which are currently being
|
||||
* copied into nzb-directory (eg. being downloaded in web-browser).
|
||||
*/
|
||||
bool Scanner::CanProcessFile(const char* szFullFilename, bool bCheckStat)
|
||||
{
|
||||
const char* szExtension = strrchr(szFullFilename, '.');
|
||||
if (!szExtension ||
|
||||
!strcasecmp(szExtension, ".queued") ||
|
||||
!strcasecmp(szExtension, ".error") ||
|
||||
!strcasecmp(szExtension, ".processed"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!bCheckStat)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
long long lSize = Util::FileSize(szFullFilename);
|
||||
time_t tCurrent = time(NULL);
|
||||
bool bCanProcess = false;
|
||||
bool bInList = false;
|
||||
|
||||
for (FileList::iterator it = m_FileList.begin(); it != m_FileList.end(); it++)
|
||||
{
|
||||
FileData* pFileData = *it;
|
||||
if (!strcmp(pFileData->GetFilename(), szFullFilename))
|
||||
{
|
||||
bInList = true;
|
||||
if (pFileData->GetSize() == lSize &&
|
||||
tCurrent - pFileData->GetLastChange() >= g_pOptions->GetNzbDirFileAge())
|
||||
{
|
||||
bCanProcess = true;
|
||||
delete pFileData;
|
||||
m_FileList.erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
pFileData->SetSize(lSize);
|
||||
if (pFileData->GetSize() != lSize)
|
||||
{
|
||||
pFileData->SetLastChange(tCurrent);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!bInList)
|
||||
{
|
||||
FileData* pFileData = new FileData(szFullFilename);
|
||||
pFileData->SetSize(lSize);
|
||||
pFileData->SetLastChange(tCurrent);
|
||||
m_FileList.push_back(pFileData);
|
||||
}
|
||||
|
||||
return bCanProcess;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove old files from the list of monitored files.
|
||||
* Normally these files are deleted from the list when they are processed.
|
||||
* However if a file was detected by function "CanProcessFile" once but wasn't
|
||||
* processed later (for example if the user deleted it), it will stay in the list,
|
||||
* until we remove it here.
|
||||
*/
|
||||
void Scanner::DropOldFiles()
|
||||
{
|
||||
time_t tCurrent = time(NULL);
|
||||
|
||||
int i = 0;
|
||||
for (FileList::iterator it = m_FileList.begin(); it != m_FileList.end(); )
|
||||
{
|
||||
FileData* pFileData = *it;
|
||||
if ((tCurrent - pFileData->GetLastChange() >=
|
||||
(g_pOptions->GetNzbDirInterval() + g_pOptions->GetNzbDirFileAge()) * 2) ||
|
||||
// can occur if the system clock was adjusted
|
||||
tCurrent < pFileData->GetLastChange())
|
||||
{
|
||||
debug("Removing file %s from scan file list", pFileData->GetFilename());
|
||||
|
||||
delete pFileData;
|
||||
m_FileList.erase(it);
|
||||
it = m_FileList.begin() + i;
|
||||
}
|
||||
else
|
||||
{
|
||||
it++;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Scanner::ProcessIncomingFile(const char* szDirectory, const char* szBaseFilename, const char* szFullFilename, const char* szCategory)
|
||||
{
|
||||
const char* szExtension = strrchr(szBaseFilename, '.');
|
||||
if (!szExtension)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
char* szNZBCategory = strdup(szCategory);
|
||||
NZBParameterList* pParameterList = new NZBParameterList;
|
||||
|
||||
bool bExists = true;
|
||||
|
||||
if (m_bNZBScript && strcasecmp(szExtension, ".nzb_processed"))
|
||||
{
|
||||
NZBScriptController::ExecuteScript(g_pOptions->GetNZBProcess(), szFullFilename, szDirectory, &szNZBCategory, pParameterList);
|
||||
bExists = Util::FileExists(szFullFilename);
|
||||
if (bExists && strcasecmp(szExtension, ".nzb"))
|
||||
{
|
||||
char bakname2[1024];
|
||||
bool bRenameOK = Util::RenameBak(szFullFilename, "processed", false, bakname2, 1024);
|
||||
if (!bRenameOK)
|
||||
{
|
||||
error("Could not rename file %s to %s! Errcode: %i", szFullFilename, bakname2, errno);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!strcasecmp(szExtension, ".nzb_processed"))
|
||||
{
|
||||
char szRenamedName[1024];
|
||||
bool bRenameOK = Util::RenameBak(szFullFilename, "nzb", true, szRenamedName, 1024);
|
||||
if (bRenameOK)
|
||||
{
|
||||
AddFileToQueue(szRenamedName, szNZBCategory, pParameterList);
|
||||
}
|
||||
else
|
||||
{
|
||||
error("Could not rename file %s to %s! Errcode: %i", szFullFilename, szRenamedName, errno);
|
||||
}
|
||||
}
|
||||
else if (bExists && !strcasecmp(szExtension, ".nzb"))
|
||||
{
|
||||
AddFileToQueue(szFullFilename, szNZBCategory, pParameterList);
|
||||
}
|
||||
|
||||
for (NZBParameterList::iterator it = pParameterList->begin(); it != pParameterList->end(); it++)
|
||||
{
|
||||
delete *it;
|
||||
}
|
||||
pParameterList->clear();
|
||||
delete pParameterList;
|
||||
|
||||
free(szNZBCategory);
|
||||
}
|
||||
|
||||
void Scanner::AddFileToQueue(const char* szFilename, const char* szCategory, NZBParameterList* pParameterList)
|
||||
{
|
||||
const char* szBasename = Util::BaseFileName(szFilename);
|
||||
|
||||
info("Collection %s found", szBasename);
|
||||
|
||||
NZBFile* pNZBFile = NZBFile::CreateFromFile(szFilename, szCategory);
|
||||
if (!pNZBFile)
|
||||
{
|
||||
error("Could not add collection %s to queue", szBasename);
|
||||
}
|
||||
|
||||
char bakname2[1024];
|
||||
bool bRenameOK = Util::RenameBak(szFilename, pNZBFile ? "queued" : "error", false, bakname2, 1024);
|
||||
if (!bRenameOK)
|
||||
{
|
||||
error("Could not rename file %s to %s! Errcode: %i", szFilename, bakname2, errno);
|
||||
}
|
||||
|
||||
if (pNZBFile && bRenameOK)
|
||||
{
|
||||
pNZBFile->GetNZBInfo()->SetQueuedFilename(bakname2);
|
||||
|
||||
for (NZBParameterList::iterator it = pParameterList->begin(); it != pParameterList->end(); it++)
|
||||
{
|
||||
NZBParameter* pParameter = *it;
|
||||
pNZBFile->GetNZBInfo()->SetParameter(pParameter->GetName(), pParameter->GetValue());
|
||||
}
|
||||
|
||||
g_pQueueCoordinator->AddNZBFileToQueue(pNZBFile, false);
|
||||
info("Collection %s added to queue", szBasename);
|
||||
}
|
||||
|
||||
if (pNZBFile)
|
||||
{
|
||||
delete pNZBFile;
|
||||
}
|
||||
}
|
||||
|
||||
void Scanner::ScanNZBDir()
|
||||
{
|
||||
// ideally we should use mutex to access "m_bRequestedNZBDirScan",
|
||||
// but it's not critical here.
|
||||
m_bRequestedNZBDirScan = true;
|
||||
}
|
||||
76
Scanner.h
76
Scanner.h
@@ -1,76 +0,0 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2007-2010 Andrei Prygounkov <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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef SCANNER_H
|
||||
#define SCANNER_H
|
||||
|
||||
#include <deque>
|
||||
#include <time.h>
|
||||
#include "DownloadInfo.h"
|
||||
|
||||
class Scanner
|
||||
{
|
||||
private:
|
||||
class FileData
|
||||
{
|
||||
private:
|
||||
char* m_szFilename;
|
||||
long long m_iSize;
|
||||
time_t m_tLastChange;
|
||||
|
||||
public:
|
||||
FileData(const char* szFilename);
|
||||
~FileData();
|
||||
const char* GetFilename() { return m_szFilename; }
|
||||
long long GetSize() { return m_iSize; }
|
||||
void SetSize(long long lSize) { m_iSize = lSize; }
|
||||
time_t GetLastChange() { return m_tLastChange; }
|
||||
void SetLastChange(time_t tLastChange) { m_tLastChange = tLastChange; }
|
||||
};
|
||||
|
||||
typedef std::deque<FileData*> FileList;
|
||||
|
||||
bool m_bRequestedNZBDirScan;
|
||||
int m_iNZBDirInterval;
|
||||
bool m_bNZBScript;
|
||||
int m_iPass;
|
||||
int m_iStepMSec;
|
||||
FileList m_FileList;
|
||||
|
||||
void CheckIncomingNZBs(const char* szDirectory, const char* szCategory, bool bCheckStat);
|
||||
void AddFileToQueue(const char* szFilename, const char* szCategory, 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();
|
||||
|
||||
public:
|
||||
Scanner();
|
||||
~Scanner();
|
||||
void SetStepInterval(int iStepMSec) { m_iStepMSec = iStepMSec; }
|
||||
void ScanNZBDir();
|
||||
void Check();
|
||||
};
|
||||
|
||||
#endif
|
||||
246
Scheduler.cpp
246
Scheduler.cpp
@@ -1,246 +0,0 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2008-2009 Andrei Prygounkov <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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#include "win32.h"
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "nzbget.h"
|
||||
#include "Scheduler.h"
|
||||
#include "ScriptController.h"
|
||||
#include "Options.h"
|
||||
#include "Log.h"
|
||||
|
||||
extern Options* g_pOptions;
|
||||
|
||||
Scheduler::Task::Task(int iHours, int iMinutes, int iWeekDaysBits, ECommand eCommand,
|
||||
int iDownloadRate, const char* szProcess)
|
||||
{
|
||||
m_iHours = iHours;
|
||||
m_iMinutes = iMinutes;
|
||||
m_iWeekDaysBits = iWeekDaysBits;
|
||||
m_eCommand = eCommand;
|
||||
m_iDownloadRate = iDownloadRate;
|
||||
m_szProcess = NULL;
|
||||
if (szProcess)
|
||||
{
|
||||
m_szProcess = strdup(szProcess);
|
||||
}
|
||||
m_tLastExecuted = 0;
|
||||
}
|
||||
|
||||
Scheduler::Task::~Task()
|
||||
{
|
||||
if (m_szProcess)
|
||||
{
|
||||
free(m_szProcess);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Scheduler::Scheduler()
|
||||
{
|
||||
debug("Creating Scheduler");
|
||||
|
||||
m_tLastCheck = 0;
|
||||
m_TaskList.clear();
|
||||
}
|
||||
|
||||
Scheduler::~Scheduler()
|
||||
{
|
||||
debug("Destroying Scheduler");
|
||||
|
||||
for (TaskList::iterator it = m_TaskList.begin(); it != m_TaskList.end(); it++)
|
||||
{
|
||||
delete *it;
|
||||
}
|
||||
}
|
||||
|
||||
void Scheduler::AddTask(Task* pTask)
|
||||
{
|
||||
m_mutexTaskList.Lock();
|
||||
m_TaskList.push_back(pTask);
|
||||
m_mutexTaskList.Unlock();
|
||||
}
|
||||
|
||||
bool Scheduler::CompareTasks(Scheduler::Task* pTask1, Scheduler::Task* pTask2)
|
||||
{
|
||||
return (pTask1->m_iHours < pTask2->m_iHours) ||
|
||||
((pTask1->m_iHours == pTask2->m_iHours) && (pTask1->m_iMinutes < pTask2->m_iMinutes));
|
||||
}
|
||||
|
||||
void Scheduler::FirstCheck()
|
||||
{
|
||||
m_mutexTaskList.Lock();
|
||||
m_TaskList.sort(CompareTasks);
|
||||
m_mutexTaskList.Unlock();
|
||||
|
||||
// check all tasks for the last week
|
||||
time_t tCurrent = time(NULL);
|
||||
m_tLastCheck = tCurrent - 60*60*24*7;
|
||||
m_bDetectClockChanges = false;
|
||||
m_bExecuteProcess = false;
|
||||
m_bDownloadRateChanged = false;
|
||||
m_bPauseDownloadChanged = false;
|
||||
m_bPauseScanChanged = false;
|
||||
CheckTasks();
|
||||
}
|
||||
|
||||
void Scheduler::IntervalCheck()
|
||||
{
|
||||
m_bDetectClockChanges = true;
|
||||
m_bExecuteProcess = true;
|
||||
m_bDownloadRateChanged = false;
|
||||
m_bPauseDownloadChanged = false;
|
||||
m_bPauseScanChanged = false;
|
||||
CheckTasks();
|
||||
}
|
||||
|
||||
void Scheduler::CheckTasks()
|
||||
{
|
||||
m_mutexTaskList.Lock();
|
||||
|
||||
time_t tCurrent = time(NULL);
|
||||
struct tm tmCurrent;
|
||||
localtime_r(&tCurrent, &tmCurrent);
|
||||
|
||||
struct tm tmLastCheck;
|
||||
|
||||
if (m_bDetectClockChanges)
|
||||
{
|
||||
// Detect large step changes of system time
|
||||
time_t tDiff = tCurrent - m_tLastCheck;
|
||||
if (tDiff > 60*90 || tDiff < -60*90)
|
||||
{
|
||||
debug("Reset scheduled tasks (detected clock adjustment greater than 90 minutes)");
|
||||
m_bExecuteProcess = false;
|
||||
m_tLastCheck = tCurrent;
|
||||
|
||||
for (TaskList::iterator it = m_TaskList.begin(); it != m_TaskList.end(); it++)
|
||||
{
|
||||
Task* pTask = *it;
|
||||
pTask->m_tLastExecuted = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
localtime_r(&m_tLastCheck, &tmLastCheck);
|
||||
|
||||
struct tm tmLoop;
|
||||
memcpy(&tmLoop, &tmLastCheck, sizeof(tmLastCheck));
|
||||
tmLoop.tm_hour = tmCurrent.tm_hour;
|
||||
tmLoop.tm_min = tmCurrent.tm_min;
|
||||
tmLoop.tm_sec = tmCurrent.tm_sec;
|
||||
time_t tLoop = mktime(&tmLoop);
|
||||
|
||||
while (tLoop <= tCurrent)
|
||||
{
|
||||
for (TaskList::iterator it = m_TaskList.begin(); it != m_TaskList.end(); it++)
|
||||
{
|
||||
Task* pTask = *it;
|
||||
if (pTask->m_tLastExecuted != tLoop)
|
||||
{
|
||||
struct tm tmAppoint;
|
||||
memcpy(&tmAppoint, &tmLoop, sizeof(tmLoop));
|
||||
tmAppoint.tm_hour = pTask->m_iHours;
|
||||
tmAppoint.tm_min = pTask->m_iMinutes;
|
||||
tmAppoint.tm_sec = 0;
|
||||
|
||||
time_t tAppoint = mktime(&tmAppoint);
|
||||
int iWeekDay = tmAppoint.tm_wday;
|
||||
if (iWeekDay == 0)
|
||||
{
|
||||
iWeekDay = 7;
|
||||
}
|
||||
|
||||
bool bWeekDayOK = pTask->m_iWeekDaysBits == 0 || (pTask->m_iWeekDaysBits & (1 << (iWeekDay - 1)));
|
||||
bool bDoTask = bWeekDayOK && m_tLastCheck < tAppoint && tAppoint <= tCurrent;
|
||||
|
||||
//debug("TEMP: 1) m_tLastCheck=%i, tCurrent=%i, tLoop=%i, tAppoint=%i, bWeekDayOK=%i, bDoTask=%i", m_tLastCheck, tCurrent, tLoop, tAppoint, (int)bWeekDayOK, (int)bDoTask);
|
||||
|
||||
if (bDoTask)
|
||||
{
|
||||
ExecuteTask(pTask);
|
||||
pTask->m_tLastExecuted = tLoop;
|
||||
}
|
||||
}
|
||||
}
|
||||
tLoop += 60*60*24; // inc day
|
||||
localtime_r(&tLoop, &tmLoop);
|
||||
}
|
||||
|
||||
m_tLastCheck = tCurrent;
|
||||
|
||||
m_mutexTaskList.Unlock();
|
||||
}
|
||||
|
||||
void Scheduler::ExecuteTask(Task* pTask)
|
||||
{
|
||||
if (pTask->m_eCommand == scDownloadRate)
|
||||
{
|
||||
debug("Executing scheduled command: Set download rate to %i", pTask->m_iDownloadRate);
|
||||
}
|
||||
else
|
||||
{
|
||||
const char* szCommandName[] = { "Pause", "Unpause", "Set download rate", "Execute program", "Pause Scan", "Unpause Scan" };
|
||||
debug("Executing scheduled command: %s", szCommandName[pTask->m_eCommand]);
|
||||
}
|
||||
|
||||
switch (pTask->m_eCommand)
|
||||
{
|
||||
case scDownloadRate:
|
||||
m_iDownloadRate = pTask->m_iDownloadRate;
|
||||
m_bDownloadRateChanged = true;
|
||||
break;
|
||||
|
||||
case scPauseDownload:
|
||||
case scUnpauseDownload:
|
||||
m_bPauseDownload = pTask->m_eCommand == scPauseDownload;
|
||||
m_bPauseDownloadChanged = true;
|
||||
break;
|
||||
|
||||
case scProcess:
|
||||
if (m_bExecuteProcess)
|
||||
{
|
||||
SchedulerScriptController::StartScript(pTask->m_szProcess);
|
||||
}
|
||||
break;
|
||||
|
||||
case scPauseScan:
|
||||
case scUnpauseScan:
|
||||
m_bPauseScan = pTask->m_eCommand == scPauseScan;
|
||||
m_bPauseScanChanged = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
98
Scheduler.h
98
Scheduler.h
@@ -1,98 +0,0 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2008-2009 Andrei Prygounkov <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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef SCHEDULER_H
|
||||
#define SCHEDULER_H
|
||||
|
||||
#include <list>
|
||||
#include <time.h>
|
||||
|
||||
#include "Thread.h"
|
||||
|
||||
class Scheduler
|
||||
{
|
||||
public:
|
||||
enum ECommand
|
||||
{
|
||||
scPauseDownload,
|
||||
scUnpauseDownload,
|
||||
scDownloadRate,
|
||||
scProcess,
|
||||
scPauseScan,
|
||||
scUnpauseScan
|
||||
};
|
||||
|
||||
class Task
|
||||
{
|
||||
private:
|
||||
int m_iHours;
|
||||
int m_iMinutes;
|
||||
int m_iWeekDaysBits;
|
||||
ECommand m_eCommand;
|
||||
int m_iDownloadRate;
|
||||
char* m_szProcess;
|
||||
time_t m_tLastExecuted;
|
||||
|
||||
public:
|
||||
Task(int iHours, int iMinutes, int iWeekDaysBits, ECommand eCommand,
|
||||
int iDownloadRate, const char* szProcess);
|
||||
~Task();
|
||||
friend class Scheduler;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
typedef std::list<Task*> TaskList;
|
||||
|
||||
TaskList m_TaskList;
|
||||
Mutex m_mutexTaskList;
|
||||
time_t m_tLastCheck;
|
||||
bool m_bDetectClockChanges;
|
||||
bool m_bDownloadRateChanged;
|
||||
bool m_bExecuteProcess;
|
||||
int m_iDownloadRate;
|
||||
bool m_bPauseDownloadChanged;
|
||||
bool m_bPauseDownload;
|
||||
bool m_bPauseScanChanged;
|
||||
bool m_bPauseScan;
|
||||
void ExecuteTask(Task* pTask);
|
||||
void CheckTasks();
|
||||
static bool CompareTasks(Scheduler::Task* pTask1, Scheduler::Task* pTask2);
|
||||
|
||||
public:
|
||||
Scheduler();
|
||||
~Scheduler();
|
||||
void AddTask(Task* pTask);
|
||||
void FirstCheck();
|
||||
void IntervalCheck();
|
||||
bool GetDownloadRateChanged() { return m_bDownloadRateChanged; }
|
||||
int GetDownloadRate() { return m_iDownloadRate; }
|
||||
bool GetPauseDownloadChanged() { return m_bPauseDownloadChanged; }
|
||||
bool GetPauseDownload() { return m_bPauseDownload; }
|
||||
bool GetPauseScanChanged() { return m_bPauseScanChanged; }
|
||||
bool GetPauseScan() { return m_bPauseScan; }
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2007-2010 Andrei Prygounkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2007 Andrei Prygounkov <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
|
||||
@@ -48,228 +48,55 @@
|
||||
#include "ScriptController.h"
|
||||
#include "Log.h"
|
||||
#include "Util.h"
|
||||
#include "Options.h"
|
||||
|
||||
extern Options* g_pOptions;
|
||||
extern char* (*szEnvironmentVariables)[];
|
||||
extern DownloadQueueHolder* g_pDownloadQueueHolder;
|
||||
|
||||
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;
|
||||
|
||||
#ifndef WIN32
|
||||
#define CHILD_WATCHDOG 1
|
||||
#endif
|
||||
|
||||
#ifdef CHILD_WATCHDOG
|
||||
/**
|
||||
* Sometimes the forked child process doesn't start properly and hangs
|
||||
* just during the starting. I didn't find any explanation about what
|
||||
* could cause that problem except of a general advice, that
|
||||
* "a forking in a multithread application is not recommended".
|
||||
*
|
||||
* Workaround:
|
||||
* 1) child process prints a line into stdout directly after the start;
|
||||
* 2) parent process waits for a line for 60 seconds. If it didn't receive it
|
||||
* the cild process assumed to hang and will be killed. Another attempt
|
||||
* will be made.
|
||||
*/
|
||||
|
||||
class ChildWatchDog : public Thread
|
||||
void ScriptController::StartScriptJob(PostInfo* pPostInfo, const char* szScript, bool bNZBFileCompleted, bool bHasFailedParJobs)
|
||||
{
|
||||
private:
|
||||
pid_t m_hProcessID;
|
||||
protected:
|
||||
virtual void Run();
|
||||
public:
|
||||
void SetProcessID(pid_t hProcessID) { m_hProcessID = hProcessID; }
|
||||
};
|
||||
|
||||
void ChildWatchDog::Run()
|
||||
{
|
||||
static const int WAIT_SECONDS = 60;
|
||||
time_t tStart = time(NULL);
|
||||
while (!IsStopped() && (time(NULL) - tStart) < WAIT_SECONDS)
|
||||
if (!Util::FileExists(szScript))
|
||||
{
|
||||
usleep(10 * 1000);
|
||||
error("Could not start post-process-script: could not find file %s", szScript);
|
||||
pPostInfo->SetStage(PostInfo::ptFinished);
|
||||
pPostInfo->SetWorking(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsStopped())
|
||||
{
|
||||
info("Restarting hanging child process");
|
||||
kill(m_hProcessID, SIGKILL);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
info("Executing post-process-script for %s", pPostInfo->GetInfoName());
|
||||
|
||||
ScriptController* pScriptController = new ScriptController();
|
||||
pScriptController->m_pPostInfo = pPostInfo;
|
||||
pScriptController->m_szScript = szScript;
|
||||
pScriptController->m_bNZBFileCompleted = bNZBFileCompleted;
|
||||
pScriptController->m_bHasFailedParJobs = bHasFailedParJobs;
|
||||
pScriptController->SetAutoDestroy(false);
|
||||
|
||||
EnvironmentStrings::EnvironmentStrings()
|
||||
{
|
||||
pPostInfo->SetScriptThread(pScriptController);
|
||||
|
||||
pScriptController->Start();
|
||||
}
|
||||
|
||||
EnvironmentStrings::~EnvironmentStrings()
|
||||
void ScriptController::Run()
|
||||
{
|
||||
for (Strings::iterator it = m_strings.begin(); it != m_strings.end(); it++)
|
||||
{
|
||||
free(*it);
|
||||
}
|
||||
m_strings.clear();
|
||||
}
|
||||
char szParStatus[10];
|
||||
snprintf(szParStatus, 10, "%i", m_pPostInfo->GetParStatus());
|
||||
szParStatus[10-1] = '\0';
|
||||
|
||||
void EnvironmentStrings::InitFromCurrentProcess()
|
||||
{
|
||||
for (int i = 0; (*szEnvironmentVariables)[i]; i++)
|
||||
{
|
||||
char* szVar = (*szEnvironmentVariables)[i];
|
||||
Append(strdup(szVar));
|
||||
}
|
||||
}
|
||||
char szCollectionCompleted[10];
|
||||
snprintf(szCollectionCompleted, 10, "%i", (int)m_bNZBFileCompleted);
|
||||
szCollectionCompleted[10-1] = '\0';
|
||||
|
||||
void EnvironmentStrings::Append(char* szString)
|
||||
{
|
||||
m_strings.push_back(szString);
|
||||
}
|
||||
char szHasFailedParJobs[10];
|
||||
snprintf(szHasFailedParJobs, 10, "%i", (int)m_bHasFailedParJobs);
|
||||
szHasFailedParJobs[10-1] = '\0';
|
||||
|
||||
#ifdef WIN32
|
||||
/*
|
||||
* Returns environment block in format suitable for using with CreateProcess.
|
||||
* The allocated memory must be freed by caller using "free()".
|
||||
*/
|
||||
char* EnvironmentStrings::GetStrings()
|
||||
{
|
||||
int iSize = 1;
|
||||
for (Strings::iterator it = m_strings.begin(); it != m_strings.end(); it++)
|
||||
{
|
||||
char* szVar = *it;
|
||||
iSize += strlen(szVar) + 1;
|
||||
}
|
||||
|
||||
char* szStrings = (char*)malloc(iSize);
|
||||
char* szPtr = szStrings;
|
||||
for (Strings::iterator it = m_strings.begin(); it != m_strings.end(); it++)
|
||||
{
|
||||
char* szVar = *it;
|
||||
strcpy(szPtr, szVar);
|
||||
szPtr += strlen(szVar) + 1;
|
||||
}
|
||||
*szPtr = '\0';
|
||||
|
||||
return szStrings;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* Returns environment block in format suitable for using with execve
|
||||
* The allocated memory must be freed by caller using "free()".
|
||||
*/
|
||||
char** EnvironmentStrings::GetStrings()
|
||||
{
|
||||
char** pStrings = (char**)malloc((m_strings.size() + 1) * sizeof(char*));
|
||||
char** pPtr = pStrings;
|
||||
for (Strings::iterator it = m_strings.begin(); it != m_strings.end(); it++)
|
||||
{
|
||||
char* szVar = *it;
|
||||
*pPtr = szVar;
|
||||
pPtr++;
|
||||
}
|
||||
*pPtr = NULL;
|
||||
|
||||
return pStrings;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
ScriptController::ScriptController()
|
||||
{
|
||||
m_szScript = NULL;
|
||||
m_szWorkingDir = NULL;
|
||||
m_szArgs = NULL;
|
||||
m_bFreeArgs = false;
|
||||
m_szInfoName = NULL;
|
||||
m_szDefaultKindPrefix = NULL;
|
||||
m_bTerminated = false;
|
||||
m_environmentStrings.InitFromCurrentProcess();
|
||||
}
|
||||
|
||||
ScriptController::~ScriptController()
|
||||
{
|
||||
if (m_bFreeArgs)
|
||||
{
|
||||
for (const char** szArgPtr = m_szArgs; *szArgPtr; szArgPtr++)
|
||||
{
|
||||
free((char*)*szArgPtr);
|
||||
}
|
||||
free(m_szArgs);
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptController::SetEnvVar(const char* szName, const char* szValue)
|
||||
{
|
||||
int iLen = strlen(szName) + strlen(szValue) + 2;
|
||||
char* szVar = (char*)malloc(iLen);
|
||||
snprintf(szVar, iLen, "%s=%s", szName, szValue);
|
||||
m_environmentStrings.Append(szVar);
|
||||
}
|
||||
|
||||
void ScriptController::PrepareEnvironmentStrings()
|
||||
{
|
||||
Options::OptEntries* pOptEntries = g_pOptions->LockOptEntries();
|
||||
|
||||
for (Options::OptEntries::iterator it = pOptEntries->begin(); it != pOptEntries->end(); it++)
|
||||
{
|
||||
Options::OptEntry* pOptEntry = *it;
|
||||
char szVarname[1024];
|
||||
snprintf(szVarname, sizeof(szVarname), "NZBOP_%s", pOptEntry->GetName());
|
||||
|
||||
// convert to upper case; replace "." with "_".
|
||||
for (char* szPtr = szVarname; *szPtr; szPtr++)
|
||||
{
|
||||
if (*szPtr == '.')
|
||||
{
|
||||
*szPtr = '_';
|
||||
}
|
||||
*szPtr = toupper(*szPtr);
|
||||
}
|
||||
|
||||
szVarname[1024-1] = '\0';
|
||||
SetEnvVar(szVarname, pOptEntry->GetValue());
|
||||
}
|
||||
|
||||
g_pOptions->UnlockOptEntries();
|
||||
}
|
||||
|
||||
int ScriptController::Execute()
|
||||
{
|
||||
if (!Util::FileExists(m_szScript))
|
||||
{
|
||||
error("Could not start %s: could not find file %s", m_szInfoName, m_szScript);
|
||||
return -1;
|
||||
}
|
||||
|
||||
PrepareEnvironmentStrings();
|
||||
|
||||
int iExitCode = 0;
|
||||
int pipein;
|
||||
|
||||
#ifdef CHILD_WATCHDOG
|
||||
bool bChildConfirmed = false;
|
||||
while (!bChildConfirmed && !m_bTerminated)
|
||||
{
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
// build command line
|
||||
char szCmdLine[2048];
|
||||
int iUsedLen = 0;
|
||||
for (const char** szArgPtr = m_szArgs; *szArgPtr; szArgPtr++)
|
||||
{
|
||||
snprintf(szCmdLine + iUsedLen, 2048 - iUsedLen, "\"%s\" ", *szArgPtr);
|
||||
iUsedLen += strlen(*szArgPtr) + 3;
|
||||
}
|
||||
szCmdLine[iUsedLen < 2048 ? iUsedLen - 1 : 2048 - 1] = '\0';
|
||||
snprintf(szCmdLine, 2048, "\"%s\" \"%s\" \"%s\" \"%s\" %s %s %s", m_szScript, m_pPostInfo->GetDestDir(),
|
||||
m_pPostInfo->GetNZBFilename(), m_pPostInfo->GetParFilename(), szParStatus, szCollectionCompleted, szHasFailedParJobs);
|
||||
szCmdLine[2048-1] = '\0';
|
||||
|
||||
// create pipes to write and read data
|
||||
HANDLE hReadPipe, hWritePipe;
|
||||
@@ -291,9 +118,7 @@ int ScriptController::Execute()
|
||||
PROCESS_INFORMATION ProcessInfo;
|
||||
memset(&ProcessInfo, 0, sizeof(ProcessInfo));
|
||||
|
||||
char* szEnvironmentStrings = m_environmentStrings.GetStrings();
|
||||
|
||||
BOOL bOK = CreateProcess(NULL, szCmdLine, NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW, szEnvironmentStrings, m_szWorkingDir, &StartupInfo, &ProcessInfo);
|
||||
BOOL bOK = CreateProcess(NULL, szCmdLine, NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW, NULL, m_pPostInfo->GetDestDir(), &StartupInfo, &ProcessInfo);
|
||||
if (!bOK)
|
||||
{
|
||||
DWORD dwErrCode = GetLastError();
|
||||
@@ -302,18 +127,17 @@ int ScriptController::Execute()
|
||||
if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM || FORMAT_MESSAGE_IGNORE_INSERTS || FORMAT_MESSAGE_ARGUMENT_ARRAY,
|
||||
NULL, dwErrCode, 0, szErrMsg, 255, NULL))
|
||||
{
|
||||
error("Could not start %s: %s", m_szInfoName, szErrMsg);
|
||||
error("Could not start post-process-script: %s", szErrMsg);
|
||||
}
|
||||
else
|
||||
{
|
||||
error("Could not start %s: error %i", m_szInfoName, dwErrCode);
|
||||
error("Could not start post-process-script: error %i", dwErrCode);
|
||||
}
|
||||
free(szEnvironmentStrings);
|
||||
return -1;
|
||||
m_pPostInfo->SetStage(PostInfo::ptFinished);
|
||||
m_pPostInfo->SetWorking(false);
|
||||
return;
|
||||
}
|
||||
|
||||
free(szEnvironmentStrings);
|
||||
|
||||
debug("Child Process-ID: %i", (int)ProcessInfo.dwProcessId);
|
||||
|
||||
m_hProcess = ProcessInfo.hProcess;
|
||||
@@ -325,6 +149,18 @@ int ScriptController::Execute()
|
||||
|
||||
#else
|
||||
|
||||
char szDestDir[1024];
|
||||
strncpy(szDestDir, m_pPostInfo->GetDestDir(), 1024);
|
||||
szDestDir[1024-1] = '\0';
|
||||
|
||||
char szNZBFilename[1024];
|
||||
strncpy(szNZBFilename, m_pPostInfo->GetNZBFilename(), 1024);
|
||||
szNZBFilename[1024-1] = '\0';
|
||||
|
||||
char szParFilename[1024];
|
||||
strncpy(szParFilename, m_pPostInfo->GetParFilename(), 1024);
|
||||
szParFilename[1024-1] = '\0';
|
||||
|
||||
int p[2];
|
||||
int pipeout;
|
||||
|
||||
@@ -332,11 +168,11 @@ int ScriptController::Execute()
|
||||
if (pipe(p))
|
||||
{
|
||||
error("Could not open pipe: errno %i", errno);
|
||||
return -1;
|
||||
m_pPostInfo->SetStage(PostInfo::ptFinished);
|
||||
m_pPostInfo->SetWorking(false);
|
||||
return;
|
||||
}
|
||||
|
||||
char** pEnvironmentStrings = m_environmentStrings.GetStrings();
|
||||
|
||||
pipein = p[0];
|
||||
pipeout = p[1];
|
||||
|
||||
@@ -345,16 +181,14 @@ int ScriptController::Execute()
|
||||
|
||||
if (pid == -1)
|
||||
{
|
||||
error("Could not start %s: errno %i", m_szInfoName, errno);
|
||||
free(pEnvironmentStrings);
|
||||
return -1;
|
||||
error("Could not start post-process-script: errno %i", errno);
|
||||
m_pPostInfo->SetStage(PostInfo::ptFinished);
|
||||
m_pPostInfo->SetWorking(false);
|
||||
return;
|
||||
}
|
||||
else if (pid == 0)
|
||||
{
|
||||
// here goes the second instance
|
||||
|
||||
// create new process group (see Terminate() where it is used)
|
||||
setsid();
|
||||
|
||||
// close up the "read" end
|
||||
close(pipein);
|
||||
@@ -365,13 +199,9 @@ int ScriptController::Execute()
|
||||
|
||||
close(pipeout);
|
||||
|
||||
#ifdef CHILD_WATCHDOG
|
||||
fwrite("\n", 1, 1, stdout);
|
||||
fflush(stdout);
|
||||
#endif
|
||||
|
||||
execve(m_szScript, (char* const*)m_szArgs, (char* const*)pEnvironmentStrings);
|
||||
fprintf(stdout, "[ERROR] Could not start script: %s", strerror(errno));
|
||||
execlp(m_szScript, m_szScript, szDestDir, szNZBFilename, szParFilename,
|
||||
szParStatus, szCollectionCompleted, szHasFailedParJobs, NULL);
|
||||
fprintf(stdout, "[ERROR] Could not start post-process-script: %s", strerror(errno));
|
||||
fflush(stdout);
|
||||
_exit(-1);
|
||||
}
|
||||
@@ -380,8 +210,6 @@ int ScriptController::Execute()
|
||||
debug("forked");
|
||||
debug("Child Process-ID: %i", (int)pid);
|
||||
|
||||
free(pEnvironmentStrings);
|
||||
|
||||
m_hProcess = pid;
|
||||
|
||||
// close unused "write" end
|
||||
@@ -392,120 +220,50 @@ int ScriptController::Execute()
|
||||
FILE* readpipe = fdopen(pipein, "r");
|
||||
if (!readpipe)
|
||||
{
|
||||
error("Could not open pipe to %s", m_szInfoName);
|
||||
return -1;
|
||||
error("Could not open pipe to post-process-script");
|
||||
m_pPostInfo->SetStage(PostInfo::ptFinished);
|
||||
m_pPostInfo->SetWorking(false);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef CHILD_WATCHDOG
|
||||
debug("Creating child watchdog");
|
||||
ChildWatchDog* pWatchDog = new ChildWatchDog();
|
||||
pWatchDog->SetAutoDestroy(false);
|
||||
pWatchDog->SetProcessID(pid);
|
||||
pWatchDog->Start();
|
||||
#endif
|
||||
|
||||
char* buf = (char*)malloc(10240);
|
||||
|
||||
debug("Entering pipe-loop");
|
||||
while (!feof(readpipe) && !m_bTerminated)
|
||||
while (!feof(readpipe) && !IsStopped())
|
||||
{
|
||||
if (fgets(buf, 10240, readpipe))
|
||||
{
|
||||
#ifdef CHILD_WATCHDOG
|
||||
if (!bChildConfirmed)
|
||||
{
|
||||
bChildConfirmed = true;
|
||||
pWatchDog->Stop();
|
||||
debug("Child confirmed");
|
||||
}
|
||||
#endif
|
||||
ProcessOutput(buf);
|
||||
AddMessage(buf);
|
||||
}
|
||||
}
|
||||
debug("Exited pipe-loop");
|
||||
|
||||
#ifdef CHILD_WATCHDOG
|
||||
debug("Destroying WatchDog");
|
||||
if (!bChildConfirmed)
|
||||
{
|
||||
pWatchDog->Stop();
|
||||
}
|
||||
while (pWatchDog->IsRunning())
|
||||
{
|
||||
usleep(1 * 1000);
|
||||
}
|
||||
delete pWatchDog;
|
||||
#endif
|
||||
|
||||
free(buf);
|
||||
fclose(readpipe);
|
||||
|
||||
if (m_bTerminated)
|
||||
if (IsStopped())
|
||||
{
|
||||
warn("Interrupted %s", m_szInfoName);
|
||||
warn("Interrupted post-process-script for %s", m_pPostInfo->GetInfoName());
|
||||
}
|
||||
|
||||
iExitCode = 0;
|
||||
|
||||
#ifdef WIN32
|
||||
WaitForSingleObject(m_hProcess, INFINITE);
|
||||
DWORD dExitCode = 0;
|
||||
GetExitCodeProcess(m_hProcess, &dExitCode);
|
||||
iExitCode = dExitCode;
|
||||
#else
|
||||
int iStatus = 0;
|
||||
waitpid(m_hProcess, &iStatus, 0);
|
||||
if (WIFEXITED(iStatus))
|
||||
{
|
||||
iExitCode = WEXITSTATUS(iStatus);
|
||||
}
|
||||
waitpid(m_hProcess, NULL, 0);
|
||||
#endif
|
||||
|
||||
#ifdef CHILD_WATCHDOG
|
||||
} // while (!bChildConfirmed && !m_bTerminated)
|
||||
#endif
|
||||
|
||||
if (!m_bTerminated)
|
||||
|
||||
if (!IsStopped())
|
||||
{
|
||||
info("Completed %s", m_szInfoName);
|
||||
debug("Exit code %i", iExitCode);
|
||||
info("Completed post-process-script for %s", m_pPostInfo->GetInfoName());
|
||||
}
|
||||
|
||||
return iExitCode;
|
||||
m_pPostInfo->SetStage(PostInfo::ptFinished);
|
||||
m_pPostInfo->SetWorking(false);
|
||||
}
|
||||
|
||||
void ScriptController::Terminate()
|
||||
void ScriptController::AddMessage(char* szText)
|
||||
{
|
||||
debug("Stopping %s", m_szInfoName);
|
||||
m_bTerminated = true;
|
||||
|
||||
#ifdef WIN32
|
||||
BOOL bOK = TerminateProcess(m_hProcess, -1);
|
||||
#else
|
||||
pid_t hKillProcess = m_hProcess;
|
||||
if (getpgid(hKillProcess) == hKillProcess)
|
||||
{
|
||||
// if the child process has its own group (setsid() was successful), kill the whole group
|
||||
hKillProcess = -hKillProcess;
|
||||
}
|
||||
bool bOK = kill(hKillProcess, SIGKILL) == 0;
|
||||
#endif
|
||||
|
||||
if (bOK)
|
||||
{
|
||||
debug("Terminated %s", m_szInfoName);
|
||||
}
|
||||
else
|
||||
{
|
||||
error("Could not terminate %s", m_szInfoName);
|
||||
}
|
||||
|
||||
debug("Stopped %s", m_szInfoName);
|
||||
}
|
||||
|
||||
void ScriptController::ProcessOutput(char* szText)
|
||||
{
|
||||
debug("Processing output received from script");
|
||||
debug("Adding message received from post-process-script");
|
||||
|
||||
for (char* pend = szText + strlen(szText) - 1; pend >= szText && (*pend == '\n' || *pend == '\r' || *pend == ' '); pend--) *pend = '\0';
|
||||
|
||||
@@ -517,401 +275,116 @@ void ScriptController::ProcessOutput(char* szText)
|
||||
|
||||
if (!strncmp(szText, "[INFO] ", 7))
|
||||
{
|
||||
AddMessage(Message::mkInfo, false, g_pOptions->GetInfoTarget(), szText + 7);
|
||||
info(szText + 7);
|
||||
Options::EMessageTarget eMessageTarget = g_pOptions->GetInfoTarget();
|
||||
if (eMessageTarget == Options::mtScreen || eMessageTarget == Options::mtBoth)
|
||||
{
|
||||
m_pPostInfo->AppendMessage(Message::mkInfo, szText + 7);
|
||||
}
|
||||
}
|
||||
else if (!strncmp(szText, "[WARNING] ", 10))
|
||||
{
|
||||
AddMessage(Message::mkWarning, false, g_pOptions->GetWarningTarget(), szText + 10);
|
||||
warn(szText + 10);
|
||||
Options::EMessageTarget eMessageTarget = g_pOptions->GetWarningTarget();
|
||||
if (eMessageTarget == Options::mtScreen || eMessageTarget == Options::mtBoth)
|
||||
{
|
||||
m_pPostInfo->AppendMessage(Message::mkWarning, szText + 10);
|
||||
}
|
||||
}
|
||||
else if (!strncmp(szText, "[ERROR] ", 8))
|
||||
{
|
||||
AddMessage(Message::mkError, false, g_pOptions->GetErrorTarget(), szText + 8);
|
||||
error(szText + 8);
|
||||
Options::EMessageTarget eMessageTarget = g_pOptions->GetErrorTarget();
|
||||
if (eMessageTarget == Options::mtScreen || eMessageTarget == Options::mtBoth)
|
||||
{
|
||||
m_pPostInfo->AppendMessage(Message::mkError, szText + 8);
|
||||
}
|
||||
}
|
||||
else if (!strncmp(szText, "[DETAIL] ", 9))
|
||||
{
|
||||
AddMessage(Message::mkDetail, false, g_pOptions->GetDetailTarget(), szText + 9);
|
||||
detail(szText + 9);
|
||||
Options::EMessageTarget eMessageTarget = g_pOptions->GetDetailTarget();
|
||||
if (eMessageTarget == Options::mtScreen || eMessageTarget == Options::mtBoth)
|
||||
{
|
||||
m_pPostInfo->AppendMessage(Message::mkDetail, szText + 9);
|
||||
}
|
||||
}
|
||||
else if (!strncmp(szText, "[DEBUG] ", 8))
|
||||
{
|
||||
AddMessage(Message::mkDebug, false, g_pOptions->GetDebugTarget(), szText + 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (m_eDefaultLogKind)
|
||||
{
|
||||
case Options::slNone:
|
||||
break;
|
||||
|
||||
case Options::slDetail:
|
||||
AddMessage(Message::mkDetail, true, g_pOptions->GetDetailTarget(), szText);
|
||||
break;
|
||||
|
||||
case Options::slInfo:
|
||||
AddMessage(Message::mkInfo, true, g_pOptions->GetInfoTarget(), szText);
|
||||
break;
|
||||
|
||||
case Options::slWarning:
|
||||
AddMessage(Message::mkWarning, true, g_pOptions->GetWarningTarget(), szText);
|
||||
break;
|
||||
|
||||
case Options::slError:
|
||||
AddMessage(Message::mkError, true, g_pOptions->GetErrorTarget(), szText);
|
||||
break;
|
||||
|
||||
case Options::slDebug:
|
||||
AddMessage(Message::mkDebug, true, g_pOptions->GetDebugTarget(), szText);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
debug("Processing output received from script - completed");
|
||||
}
|
||||
|
||||
void ScriptController::AddMessage(Message::EKind eKind, bool bDefaultKind, Options::EMessageTarget eMessageTarget, const char* szText)
|
||||
{
|
||||
switch (eKind)
|
||||
{
|
||||
case Message::mkDetail:
|
||||
detail("%s%s", (bDefaultKind && m_szDefaultKindPrefix ? m_szDefaultKindPrefix : ""), szText);
|
||||
break;
|
||||
|
||||
case Message::mkInfo:
|
||||
info("%s%s", (bDefaultKind && m_szDefaultKindPrefix ? m_szDefaultKindPrefix : ""), szText);
|
||||
break;
|
||||
|
||||
case Message::mkWarning:
|
||||
warn("%s%s", (bDefaultKind && m_szDefaultKindPrefix ? m_szDefaultKindPrefix : ""), szText);
|
||||
break;
|
||||
|
||||
case Message::mkError:
|
||||
error("%s%s", (bDefaultKind && m_szDefaultKindPrefix ? m_szDefaultKindPrefix : ""), szText);
|
||||
break;
|
||||
|
||||
case Message::mkDebug:
|
||||
debug("%s%s", (bDefaultKind && m_szDefaultKindPrefix ? m_szDefaultKindPrefix : ""), szText);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void PostScriptController::StartScriptJob(PostInfo* pPostInfo, const char* szScript, bool bNZBFileCompleted, bool bHasFailedParJobs)
|
||||
{
|
||||
info("Executing post-process-script for %s", pPostInfo->GetInfoName());
|
||||
|
||||
PostScriptController* pScriptController = new PostScriptController();
|
||||
pScriptController->m_pPostInfo = pPostInfo;
|
||||
pScriptController->SetScript(szScript);
|
||||
pScriptController->SetWorkingDir(g_pOptions->GetDestDir());
|
||||
pScriptController->m_bNZBFileCompleted = bNZBFileCompleted;
|
||||
pScriptController->m_bHasFailedParJobs = bHasFailedParJobs;
|
||||
pScriptController->SetAutoDestroy(false);
|
||||
|
||||
pPostInfo->SetScriptThread(pScriptController);
|
||||
|
||||
pScriptController->Start();
|
||||
}
|
||||
|
||||
void PostScriptController::Run()
|
||||
{
|
||||
// the locking is needed for accessing the memebers of NZBInfo
|
||||
g_pDownloadQueueHolder->LockQueue();
|
||||
|
||||
char szParStatus[10];
|
||||
snprintf(szParStatus, 10, "%i", m_pPostInfo->GetParStatus());
|
||||
szParStatus[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 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';
|
||||
|
||||
char szInfoName[1024];
|
||||
snprintf(szInfoName, 1024, "post-process-script for %s", m_pPostInfo->GetInfoName());
|
||||
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_DIRECTORY", szDestDir);
|
||||
SetEnvVar("NZBPP_NZBFILENAME", szNZBFilename);
|
||||
SetEnvVar("NZBPP_PARFILENAME", szParFilename);
|
||||
SetEnvVar("NZBPP_PARSTATUS", szParStatus);
|
||||
SetEnvVar("NZBPP_NZBCOMPLETED", szCollectionCompleted);
|
||||
SetEnvVar("NZBPP_PARFAILED", szHasFailedParJobs);
|
||||
SetEnvVar("NZBPP_CATEGORY", szCategory);
|
||||
|
||||
for (NZBParameterList::iterator it = m_pPostInfo->GetNZBInfo()->GetParameters()->begin(); it != m_pPostInfo->GetNZBInfo()->GetParameters()->end(); it++)
|
||||
{
|
||||
NZBParameter* pParameter = *it;
|
||||
char szVarname[1024];
|
||||
snprintf(szVarname, sizeof(szVarname), "NZBPR_%s", pParameter->GetName());
|
||||
szVarname[1024-1] = '\0';
|
||||
SetEnvVar(szVarname, pParameter->GetValue());
|
||||
}
|
||||
|
||||
g_pDownloadQueueHolder->UnlockQueue();
|
||||
|
||||
int iResult = Execute();
|
||||
|
||||
switch (iResult)
|
||||
{
|
||||
case POSTPROCESS_SUCCESS:
|
||||
info("%s sucessful", szInfoName);
|
||||
m_pPostInfo->SetScriptStatus(PostInfo::srSuccess);
|
||||
break;
|
||||
|
||||
case POSTPROCESS_ERROR:
|
||||
info("%s failed", szInfoName);
|
||||
m_pPostInfo->SetScriptStatus(PostInfo::srFailure);
|
||||
break;
|
||||
|
||||
case POSTPROCESS_NONE:
|
||||
info("%s skipped", szInfoName);
|
||||
m_pPostInfo->SetScriptStatus(PostInfo::srNone);
|
||||
break;
|
||||
|
||||
#ifndef DISABLE_PARCHECK
|
||||
case POSTPROCESS_PARCHECK_ALL:
|
||||
if (m_pPostInfo->GetParCheck())
|
||||
{
|
||||
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
|
||||
{
|
||||
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->GetParCheck())
|
||||
{
|
||||
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:
|
||||
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, bool bDefaultKind, Options::EMessageTarget eMessageTarget, const char* szText)
|
||||
{
|
||||
if (!strncmp(szText, "[HISTORY] ", 10))
|
||||
{
|
||||
debug(szText + 8);
|
||||
Options::EMessageTarget eMessageTarget = g_pOptions->GetDebugTarget();
|
||||
if (eMessageTarget == Options::mtScreen || eMessageTarget == Options::mtBoth)
|
||||
{
|
||||
m_pPostInfo->GetNZBInfo()->AppendMessage(eKind, 0, szText + 10);
|
||||
m_pPostInfo->AppendMessage(Message::mkDebug, szText + 8);
|
||||
}
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
ScriptController::AddMessage(eKind, bDefaultKind, eMessageTarget, szText);
|
||||
Options::EMessageTarget eMessageTarget = Options::mtNone;
|
||||
Message::EKind eKind = Message::mkDebug;
|
||||
switch (g_pOptions->GetPostLogKind())
|
||||
{
|
||||
case Options::plNone:
|
||||
break;
|
||||
|
||||
case Options::plDetail:
|
||||
detail("Post-Process: %s", szText);
|
||||
eMessageTarget = g_pOptions->GetDetailTarget();
|
||||
eKind = Message::mkDetail;
|
||||
break;
|
||||
|
||||
case Options::plInfo:
|
||||
info("Post-Process: %s", szText);
|
||||
eMessageTarget = g_pOptions->GetInfoTarget();
|
||||
eKind = Message::mkInfo;
|
||||
break;
|
||||
|
||||
case Options::plWarning:
|
||||
warn("Post-Process: %s", szText);
|
||||
eMessageTarget = g_pOptions->GetWarningTarget();
|
||||
eKind = Message::mkWarning;
|
||||
break;
|
||||
|
||||
case Options::plError:
|
||||
error("Post-Process: %s", szText);
|
||||
eMessageTarget = g_pOptions->GetErrorTarget();
|
||||
eKind = Message::mkError;
|
||||
break;
|
||||
|
||||
case Options::plDebug:
|
||||
debug("Post-Process: %s", szText);
|
||||
eMessageTarget = g_pOptions->GetDebugTarget();
|
||||
eKind = Message::mkDebug;
|
||||
break;
|
||||
}
|
||||
if (eMessageTarget == Options::mtScreen || eMessageTarget == Options::mtBoth)
|
||||
{
|
||||
m_pPostInfo->AppendMessage(eKind, szText);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (g_pOptions->GetPausePostProcess())
|
||||
{
|
||||
time_t tStageTime = m_pPostInfo->GetStageTime();
|
||||
time_t tStartTime = m_pPostInfo->GetStartTime();
|
||||
time_t tWaitTime = time(NULL);
|
||||
|
||||
// wait until Post-processor is unpaused
|
||||
while (g_pOptions->GetPausePostProcess() && !IsStopped())
|
||||
{
|
||||
usleep(100 * 1000);
|
||||
|
||||
// update time stamps
|
||||
|
||||
time_t tDelta = time(NULL) - tWaitTime;
|
||||
|
||||
if (tStageTime > 0)
|
||||
{
|
||||
m_pPostInfo->SetStageTime(tStageTime + tDelta);
|
||||
}
|
||||
|
||||
if (tStartTime > 0)
|
||||
{
|
||||
m_pPostInfo->SetStartTime(tStartTime + tDelta);
|
||||
}
|
||||
}
|
||||
}
|
||||
debug("Adding message received from post-process-script - completed");
|
||||
}
|
||||
|
||||
void PostScriptController::Stop()
|
||||
void ScriptController::Stop()
|
||||
{
|
||||
debug("Stopping post-process-script");
|
||||
Thread::Stop();
|
||||
Terminate();
|
||||
}
|
||||
|
||||
void NZBScriptController::ExecuteScript(const char* szScript, const char* szNZBFilename,
|
||||
const char* szDirectory, char** pCategory, NZBParameterList* pParameterList)
|
||||
{
|
||||
info("Executing nzb-process-script for %s", Util::BaseFileName(szNZBFilename));
|
||||
#ifdef WIN32
|
||||
BOOL bOK = TerminateProcess(m_hProcess, -1);
|
||||
#else
|
||||
bool bOK = kill(m_hProcess, 9) == 0;
|
||||
#endif
|
||||
|
||||
NZBScriptController* pScriptController = new NZBScriptController();
|
||||
pScriptController->SetScript(szScript);
|
||||
pScriptController->m_pCategory = pCategory;
|
||||
pScriptController->m_pParameterList = pParameterList;
|
||||
|
||||
char szInfoName[1024];
|
||||
snprintf(szInfoName, 1024, "nzb-process-script for %s", Util::BaseFileName(szNZBFilename));
|
||||
szInfoName[1024-1] = '\0';
|
||||
pScriptController->SetInfoName(szInfoName);
|
||||
|
||||
// remove trailing slash
|
||||
char szDir[1024];
|
||||
strncpy(szDir, szDirectory, 1024);
|
||||
szDir[1024-1] = '\0';
|
||||
int iLen = strlen(szDir);
|
||||
if (szDir[iLen-1] == PATH_SEPARATOR)
|
||||
if (bOK)
|
||||
{
|
||||
szDir[iLen-1] = '\0';
|
||||
}
|
||||
|
||||
pScriptController->SetDefaultKindPrefix("NZB-Process: ");
|
||||
pScriptController->SetDefaultLogKind(g_pOptions->GetProcessLogKind());
|
||||
|
||||
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->Execute();
|
||||
|
||||
delete pScriptController;
|
||||
}
|
||||
|
||||
void NZBScriptController::AddMessage(Message::EKind eKind, bool bDefaultKind, Options::EMessageTarget eMessageTarget, const char* szText)
|
||||
{
|
||||
if (!strncmp(szText, "[NZB] ", 6))
|
||||
{
|
||||
debug("Command %s detected", szText + 6);
|
||||
if (!strncmp(szText + 6, "CATEGORY=", 9))
|
||||
{
|
||||
free(*m_pCategory);
|
||||
*m_pCategory = strdup(szText + 6 + 9);
|
||||
}
|
||||
else if (!strncmp(szText + 6, "NZBPR_", 6))
|
||||
{
|
||||
char* szParam = strdup(szText + 6 + 6);
|
||||
char* szValue = strchr(szParam, '=');
|
||||
if (szValue)
|
||||
{
|
||||
*szValue = '\0';
|
||||
m_pParameterList->SetParameter(szParam, szValue + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
error("Invalid command \"%s\" received from %s", szText, GetInfoName());
|
||||
}
|
||||
free(szParam);
|
||||
}
|
||||
else
|
||||
{
|
||||
error("Invalid command \"%s\" received from %s", szText, GetInfoName());
|
||||
}
|
||||
debug("Terminated post-process-script");
|
||||
}
|
||||
else
|
||||
{
|
||||
ScriptController::AddMessage(eKind, bDefaultKind, eMessageTarget, szText);
|
||||
}
|
||||
}
|
||||
|
||||
void SchedulerScriptController::StartScript(const char* szCommandLine)
|
||||
{
|
||||
char** argv = NULL;
|
||||
if (!Util::SplitCommandLine(szCommandLine, &argv))
|
||||
{
|
||||
error("Could not execute scheduled process-script, failed to parse command line: %s", szCommandLine);
|
||||
return;
|
||||
error("Could not terminate post-process-script");
|
||||
}
|
||||
|
||||
info("Executing scheduled process-script %s", Util::BaseFileName(argv[0]));
|
||||
|
||||
SchedulerScriptController* pScriptController = new SchedulerScriptController();
|
||||
pScriptController->SetScript(argv[0]);
|
||||
pScriptController->SetArgs((const char**)argv, true);
|
||||
pScriptController->SetAutoDestroy(true);
|
||||
|
||||
pScriptController->Start();
|
||||
}
|
||||
|
||||
void SchedulerScriptController::Run()
|
||||
{
|
||||
char szInfoName[1024];
|
||||
snprintf(szInfoName, 1024, "scheduled process-script %s", Util::BaseFileName(GetScript()));
|
||||
szInfoName[1024-1] = '\0';
|
||||
SetInfoName(szInfoName);
|
||||
|
||||
SetDefaultKindPrefix("Scheduled Process: ");
|
||||
SetDefaultLogKind(g_pOptions->GetProcessLogKind());
|
||||
|
||||
Execute();
|
||||
debug("Post-process-script stopped");
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2007-2010 Andrei Prygounkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2007 Andrei Prygounkov <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
|
||||
@@ -26,82 +26,23 @@
|
||||
#ifndef SCRIPTCONTROLLER_H
|
||||
#define SCRIPTCONTROLLER_H
|
||||
|
||||
#include <list>
|
||||
|
||||
#include "Log.h"
|
||||
#include "Thread.h"
|
||||
#include "DownloadInfo.h"
|
||||
#include "Options.h"
|
||||
#include "PostInfo.h"
|
||||
|
||||
class EnvironmentStrings
|
||||
{
|
||||
private:
|
||||
typedef std::vector<char*> Strings;
|
||||
|
||||
Strings m_strings;
|
||||
|
||||
public:
|
||||
EnvironmentStrings();
|
||||
~EnvironmentStrings();
|
||||
void InitFromCurrentProcess();
|
||||
void Append(char* szString);
|
||||
#ifdef WIN32
|
||||
char* GetStrings();
|
||||
#else
|
||||
char** GetStrings();
|
||||
#endif
|
||||
};
|
||||
|
||||
class ScriptController
|
||||
class ScriptController : public Thread
|
||||
{
|
||||
private:
|
||||
PostInfo* m_pPostInfo;
|
||||
const char* m_szScript;
|
||||
const char* m_szWorkingDir;
|
||||
const char** m_szArgs;
|
||||
bool m_bFreeArgs;
|
||||
const char* m_szInfoName;
|
||||
const char* m_szDefaultKindPrefix;
|
||||
EnvironmentStrings m_environmentStrings;
|
||||
Options::EScriptLogKind m_eDefaultLogKind;
|
||||
bool m_bTerminated;
|
||||
bool m_bNZBFileCompleted;
|
||||
bool m_bHasFailedParJobs;
|
||||
#ifdef WIN32
|
||||
HANDLE m_hProcess;
|
||||
#else
|
||||
pid_t m_hProcess;
|
||||
#endif
|
||||
|
||||
void ProcessOutput(char* szText);
|
||||
void PrepareEnvironmentStrings();
|
||||
|
||||
protected:
|
||||
virtual void AddMessage(Message::EKind eKind, bool bDefaultKind, Options::EMessageTarget eMessageTarget, const char* szText);
|
||||
|
||||
public:
|
||||
ScriptController();
|
||||
virtual ~ScriptController();
|
||||
int Execute();
|
||||
void Terminate();
|
||||
|
||||
void SetScript(const char* szScript) { m_szScript = szScript; }
|
||||
const char* GetScript() { return m_szScript; }
|
||||
void SetWorkingDir(const char* szWorkingDir) { m_szWorkingDir = szWorkingDir; }
|
||||
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 SetDefaultKindPrefix(const char* szDefaultKindPrefix) { m_szDefaultKindPrefix = szDefaultKindPrefix; }
|
||||
void SetDefaultLogKind(Options::EScriptLogKind eDefaultLogKind) { m_eDefaultLogKind = eDefaultLogKind; }
|
||||
void SetEnvVar(const char* szName, const char* szValue);
|
||||
};
|
||||
|
||||
class PostScriptController : public Thread, ScriptController
|
||||
{
|
||||
private:
|
||||
PostInfo* m_pPostInfo;
|
||||
bool m_bNZBFileCompleted;
|
||||
bool m_bHasFailedParJobs;
|
||||
|
||||
protected:
|
||||
virtual void AddMessage(Message::EKind eKind, bool bDefaultKind, Options::EMessageTarget eMessageTarget, const char* szText);
|
||||
void AddMessage(char* szText);
|
||||
|
||||
public:
|
||||
virtual void Run();
|
||||
@@ -110,24 +51,4 @@ public:
|
||||
bool bNZBFileCompleted, bool bHasFailedParJobs);
|
||||
};
|
||||
|
||||
class NZBScriptController : public ScriptController
|
||||
{
|
||||
private:
|
||||
char** m_pCategory;
|
||||
NZBParameterList* m_pParameterList;
|
||||
|
||||
protected:
|
||||
virtual void AddMessage(Message::EKind eKind, bool bDefaultKind, Options::EMessageTarget eMessageTarget, const char* szText);
|
||||
|
||||
public:
|
||||
static void ExecuteScript(const char* szScript, const char* szNZBFilename, const char* szDirectory, char** pCategory, NZBParameterList* pParameterList);
|
||||
};
|
||||
|
||||
class SchedulerScriptController : public Thread, ScriptController
|
||||
{
|
||||
public:
|
||||
virtual void Run();
|
||||
static void StartScript(const char* szCommandLine);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
* This file if part of nzbget
|
||||
*
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007-2009 Andrei Prygounkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007 Andrei Prygounkov <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
|
||||
@@ -23,6 +23,14 @@
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
* m_Semaphore Patch by Florian Penzkofer <f.penzkofer@sent.com>
|
||||
* The queue of mutexes that was used did not work for every
|
||||
* implementation of POSIX threads. Now a m_Semaphore is used.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
@@ -57,13 +65,20 @@ ServerPool::ServerPool()
|
||||
|
||||
m_iMaxLevel = 0;
|
||||
m_iTimeout = 60;
|
||||
m_Servers.clear();
|
||||
m_Connections.clear();
|
||||
m_Semaphores.clear();
|
||||
}
|
||||
|
||||
ServerPool::~ ServerPool()
|
||||
{
|
||||
debug("Destroying ServerPool");
|
||||
|
||||
m_Levels.clear();
|
||||
for (Semaphores::iterator it = m_Semaphores.begin(); it != m_Semaphores.end(); it++)
|
||||
{
|
||||
delete *it;
|
||||
}
|
||||
m_Semaphores.clear();
|
||||
|
||||
for (Servers::iterator it = m_Servers.begin(); it != m_Servers.end(); it++)
|
||||
{
|
||||
@@ -117,40 +132,52 @@ void ServerPool::InitConnections()
|
||||
}
|
||||
}
|
||||
|
||||
m_Levels.push_back(iMaxConnectionsForLevel);
|
||||
Semaphore* sem = new Semaphore(iMaxConnectionsForLevel);
|
||||
m_Semaphores.push_back(sem);
|
||||
}
|
||||
}
|
||||
|
||||
NNTPConnection* ServerPool::GetConnection(int iLevel)
|
||||
NNTPConnection* ServerPool::GetConnection(int iLevel, bool bWait)
|
||||
{
|
||||
PooledConnection* pConnection = NULL;
|
||||
bool bWaitVal = false;
|
||||
if (bWait)
|
||||
{
|
||||
debug("Getting connection (wait)");
|
||||
bWaitVal = m_Semaphores[iLevel]->Wait();
|
||||
}
|
||||
else
|
||||
{
|
||||
bWaitVal = m_Semaphores[iLevel]->TryWait();
|
||||
}
|
||||
|
||||
if (!bWaitVal)
|
||||
{
|
||||
// signal received or wait timeout
|
||||
return NULL;
|
||||
}
|
||||
|
||||
m_mutexConnections.Lock();
|
||||
|
||||
if (m_Levels[iLevel] > 0)
|
||||
PooledConnection* pConnection = NULL;
|
||||
for (Connections::iterator it = m_Connections.begin(); it != m_Connections.end(); it++)
|
||||
{
|
||||
for (Connections::iterator it = m_Connections.begin(); it != m_Connections.end(); it++)
|
||||
PooledConnection* pConnection1 = *it;
|
||||
if (!pConnection1->GetInUse() && pConnection1->GetNewsServer()->GetLevel() == iLevel)
|
||||
{
|
||||
PooledConnection* pConnection1 = *it;
|
||||
if (!pConnection1->GetInUse() && pConnection1->GetNewsServer()->GetLevel() == iLevel)
|
||||
{
|
||||
// free connection found, take it!
|
||||
pConnection = pConnection1;
|
||||
pConnection->SetInUse(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_Levels[iLevel]--;
|
||||
|
||||
if (!pConnection)
|
||||
{
|
||||
error("ServerPool: internal error, no free connection found, but there should be one");
|
||||
// free connection found, take it!
|
||||
pConnection = pConnection1;
|
||||
pConnection->SetInUse(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_mutexConnections.Unlock();
|
||||
|
||||
if (!pConnection)
|
||||
{
|
||||
error("ServerPool: serious error, no free connection found, but there should be one.");
|
||||
}
|
||||
|
||||
return pConnection;
|
||||
}
|
||||
|
||||
@@ -168,7 +195,7 @@ void ServerPool::FreeConnection(NNTPConnection* pConnection, bool bUsed)
|
||||
{
|
||||
((PooledConnection*)pConnection)->SetFreeTimeNow();
|
||||
}
|
||||
m_Levels[pConnection->GetNewsServer()->GetLevel()]++;
|
||||
m_Semaphores[pConnection->GetNewsServer()->GetLevel()]->Post();
|
||||
|
||||
m_mutexConnections.Unlock();
|
||||
}
|
||||
@@ -210,6 +237,15 @@ void ServerPool::LogDebugInfo()
|
||||
{
|
||||
debug(" Connection: Level=%i, InUse:%i", (*it)->GetNewsServer()->GetLevel(), (int)(*it)->GetInUse());
|
||||
}
|
||||
|
||||
/*
|
||||
debug(" Semaphores: %i", m_Semaphores.size());
|
||||
for (int iLevel = 0; iLevel <= m_iMaxLevel; iLevel++)
|
||||
{
|
||||
sem_t* sem = m_Semaphores[iLevel];
|
||||
int iSemValue;
|
||||
sem_getvalue(sem, &iSemValue);
|
||||
debug(" Semaphore: level=%i, value=%i", iLevel, iSemValue);
|
||||
}
|
||||
*/
|
||||
m_mutexConnections.Unlock();
|
||||
}
|
||||
|
||||
19
ServerPool.h
19
ServerPool.h
@@ -1,8 +1,9 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
* This file if part of nzbget
|
||||
*
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007-2009 Andrei Prygounkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2005 Florian Penzkofer <f.penzkofer@sent.com>
|
||||
* Copyright (C) 2007 Andrei Prygounkov <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
|
||||
@@ -51,24 +52,24 @@ private:
|
||||
};
|
||||
|
||||
typedef std::vector<NewsServer*> Servers;
|
||||
typedef std::vector<int> Levels;
|
||||
typedef std::vector<Semaphore*> Semaphores;
|
||||
typedef std::vector<PooledConnection*> Connections;
|
||||
|
||||
Servers m_Servers;
|
||||
Connections m_Connections;
|
||||
Levels m_Levels;
|
||||
Semaphores m_Semaphores;
|
||||
int m_iMaxLevel;
|
||||
Mutex m_mutexConnections;
|
||||
int m_iTimeout;
|
||||
|
||||
public:
|
||||
ServerPool();
|
||||
~ServerPool();
|
||||
ServerPool();
|
||||
~ServerPool();
|
||||
void SetTimeout(int iTimeout) { m_iTimeout = iTimeout; }
|
||||
void AddServer(NewsServer* pNewsServer);
|
||||
void AddServer(NewsServer *s);
|
||||
void InitConnections();
|
||||
int GetMaxLevel() { return m_iMaxLevel; }
|
||||
NNTPConnection* GetConnection(int iLevel);
|
||||
NNTPConnection* GetConnection(int iLevel, bool bWait);
|
||||
void FreeConnection(NNTPConnection* pConnection, bool bUsed);
|
||||
void CloseUnusedConnections();
|
||||
|
||||
|
||||
212
TLS.h
212
TLS.h
@@ -1,212 +0,0 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Based on "tls.h" from project "mpop" by Martin Lambers
|
||||
* Original source code available on http://sourceforge.net/projects/mpop/
|
||||
*
|
||||
* Copyright (C) 2000, 2003, 2004, 2005, 2006, 2007
|
||||
* Martin Lambers <marlam@marlam.de>
|
||||
*
|
||||
* Copyright (C) 2008-2009 Andrei Prygounkov <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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TLS_H
|
||||
#define TLS_H
|
||||
|
||||
#ifndef DISABLE_TLS
|
||||
|
||||
#include <time.h>
|
||||
#ifdef HAVE_LIBGNUTLS
|
||||
# include <gnutls/gnutls.h>
|
||||
#endif /* HAVE_LIBGNUTLS */
|
||||
#ifdef HAVE_OPENSSL
|
||||
# include <openssl/ssl.h>
|
||||
#endif /* HAVE_OPENSSL */
|
||||
|
||||
|
||||
/*
|
||||
* If a function with an 'errstr' argument returns a value != TLS_EOK,
|
||||
* '*errstr' either points to an allocates string containing an error
|
||||
* description or is NULL.
|
||||
* If such a function returns TLS_EOK, 'errstr' will not be changed.
|
||||
*/
|
||||
#define TLS_EOK 0 /* no error */
|
||||
#define TLS_ELIBFAILED 1 /* The underlying library failed */
|
||||
#define TLS_ESEED 2 /* Cannot seed pseudo random number generator */
|
||||
#define TLS_ECERT 3 /* Certificate check or verification failed */
|
||||
#define TLS_EIO 4 /* Input/output error */
|
||||
#define TLS_EFILE 5 /* A file does not exist/cannot be read */
|
||||
#define TLS_EHANDSHAKE 6 /* TLS handshake failed */
|
||||
|
||||
|
||||
/*
|
||||
* Always use tls_clear() before using a tls_t!
|
||||
* Never call a tls_*() function with tls_t NULL!
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int have_trust_file;
|
||||
int is_active;
|
||||
#ifdef HAVE_LIBGNUTLS
|
||||
gnutls_session_t session;
|
||||
gnutls_certificate_credentials_t cred;
|
||||
#endif /* HAVE_LIBGNUTLS */
|
||||
#ifdef HAVE_OPENSSL
|
||||
SSL_CTX *ssl_ctx;
|
||||
SSL *ssl;
|
||||
#endif /* HAVE_OPENSSL */
|
||||
} tls_t;
|
||||
|
||||
/*
|
||||
* Information about a X509 certificate.
|
||||
* The 6 owner_info and issuer_info fields are:
|
||||
* Common Name
|
||||
* Organization
|
||||
* Organizational unit
|
||||
* Locality
|
||||
* State/Province
|
||||
* Country
|
||||
* Each of these entries may be NULL if it was not provided.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
unsigned char sha1_fingerprint[20];
|
||||
unsigned char md5_fingerprint[16];
|
||||
time_t activation_time;
|
||||
time_t expiration_time;
|
||||
char *owner_info[6];
|
||||
char *issuer_info[6];
|
||||
} tls_cert_info_t;
|
||||
|
||||
/*
|
||||
* tls_lib_init()
|
||||
*
|
||||
* Initialize underlying TLS library. If this function returns TLS_ELIBFAILED,
|
||||
* *errstr will always point to an error string.
|
||||
* Used error codes: TLS_ELIBFAILED
|
||||
*/
|
||||
int tls_lib_init(char **errstr);
|
||||
|
||||
/*
|
||||
* tls_clear()
|
||||
*
|
||||
* Clears a tls_t type (marks it inactive).
|
||||
*/
|
||||
void tls_clear(tls_t *tls);
|
||||
|
||||
/*
|
||||
* tls_init()
|
||||
*
|
||||
* Initializes a tls_t. If both 'key_file' and 'ca_file' are not NULL, they are
|
||||
* set to be used when the peer request a certificate. If 'trust_file' is not
|
||||
* NULL, it will be used to verify the peer certificate.
|
||||
* All files must be in PEM format.
|
||||
* If 'force_sslv3' is set, then only the SSLv3 protocol will be accepted. This
|
||||
* option might be needed to talk to some obsolete broken servers. Only use this
|
||||
* if you have to.
|
||||
* Used error codes: TLS_ELIBFAILED, TLS_EFILE
|
||||
*/
|
||||
int tls_init(tls_t *tls,
|
||||
const char *key_file, const char *ca_file, const char *trust_file,
|
||||
int force_sslv3, char **errstr);
|
||||
|
||||
/*
|
||||
* tls_start()
|
||||
*
|
||||
* Starts TLS encryption on a socket.
|
||||
* 'tls' must be initialized using tls_init().
|
||||
* If 'no_certcheck' is true, then no checks will be performed on the peer
|
||||
* certificate. If it is false and no trust file was set with tls_init(),
|
||||
* only sanity checks are performed on the peer certificate. If it is false
|
||||
* and a trust file was set, real verification of the peer certificate is
|
||||
* performed.
|
||||
* 'hostname' is the host to start TLS with. It is needed for sanity checks/
|
||||
* verification.
|
||||
* 'tci' must be allocated with tls_cert_info_new(). Information about the
|
||||
* peer's certificata will be stored in it. It can later be freed with
|
||||
* tls_cert_info_free(). 'tci' is allowed to be NULL; no certificate
|
||||
* information will be passed in this case.
|
||||
* Used error codes: TLS_ELIBFAILED, TLS_ECERT, TLS_EHANDSHAKE
|
||||
*/
|
||||
int tls_start(tls_t *tls, int fd, const char *hostname, int no_certcheck,
|
||||
tls_cert_info_t *tci, char **errstr);
|
||||
|
||||
/*
|
||||
* tls_is_active()
|
||||
*
|
||||
* Returns whether 'tls' is an active TLS connection.
|
||||
*/
|
||||
int tls_is_active(tls_t *tls);
|
||||
|
||||
/*
|
||||
* tls_cert_info_new()
|
||||
* Returns a new tls_cert_info_t
|
||||
*/
|
||||
tls_cert_info_t *tls_cert_info_new(void);
|
||||
|
||||
/*
|
||||
* tls_cert_info_free()
|
||||
* Frees a tls_cert_info_t
|
||||
*/
|
||||
void tls_cert_info_free(tls_cert_info_t *tci);
|
||||
|
||||
/*
|
||||
* tls_cert_info_get()
|
||||
*
|
||||
* Extracts certificate information from the TLS connection 'tls' and stores
|
||||
* it in 'tci'. See the description of tls_cert_info_t above.
|
||||
* Used error codes: TLS_ECERT
|
||||
*/
|
||||
int tls_cert_info_get(tls_t *tls, tls_cert_info_t *tci, char **errstr);
|
||||
|
||||
/*
|
||||
* tls_getbuf()
|
||||
*
|
||||
* Reads a buffer using TLS and stores it in 's'.
|
||||
* Used error codes: TLS_EIO
|
||||
*/
|
||||
int tls_getbuf(tls_t *tls, char* s, size_t len, size_t* readlen, char **errstr);
|
||||
|
||||
/*
|
||||
* tls_putbuf()
|
||||
*
|
||||
* Writes 'len' characters from the string 's' using TLS.
|
||||
* Used error codes: TLS_EIO
|
||||
*/
|
||||
int tls_putbuf(tls_t *tls, const char *s, size_t len, char **errstr);
|
||||
|
||||
/*
|
||||
* tls_close()
|
||||
*
|
||||
* Close a TLS connection and mark it inactive
|
||||
*/
|
||||
void tls_close(tls_t *tls);
|
||||
|
||||
/*
|
||||
* tls_lib_deinit()
|
||||
*
|
||||
* Deinit underlying TLS library.
|
||||
*/
|
||||
void tls_lib_deinit(void);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
168
Thread.cpp
168
Thread.cpp
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
* This file if part of nzbget
|
||||
*
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007-2009 Andrei Prygounkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007 Andrei Prygounkov <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,66 +34,141 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <process.h>
|
||||
#else
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#include "Log.h"
|
||||
#include "Thread.h"
|
||||
|
||||
int Thread::m_iThreadCount = 1; // take the main program thread into account
|
||||
Mutex* Thread::m_pMutexThread;
|
||||
|
||||
Mutex Thread::m_mutexThread;
|
||||
|
||||
Mutex::Mutex()
|
||||
{
|
||||
#ifdef WIN32
|
||||
m_pMutexObj = (CRITICAL_SECTION*)malloc(sizeof(CRITICAL_SECTION));
|
||||
InitializeCriticalSection((CRITICAL_SECTION*)m_pMutexObj);
|
||||
InitializeCriticalSection(&m_mutexObj);
|
||||
#else
|
||||
m_pMutexObj = (pthread_mutex_t*)malloc(sizeof(pthread_mutex_t));
|
||||
pthread_mutex_init((pthread_mutex_t*)m_pMutexObj, NULL);
|
||||
pthread_mutex_init(&m_mutexObj, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
Mutex::~ Mutex()
|
||||
{
|
||||
#ifdef WIN32
|
||||
DeleteCriticalSection((CRITICAL_SECTION*)m_pMutexObj);
|
||||
DeleteCriticalSection(&m_mutexObj);
|
||||
#else
|
||||
pthread_mutex_destroy((pthread_mutex_t*)m_pMutexObj);
|
||||
pthread_mutex_destroy(&m_mutexObj);
|
||||
#endif
|
||||
free(m_pMutexObj);
|
||||
}
|
||||
|
||||
void Mutex::Lock()
|
||||
{
|
||||
#ifdef WIN32
|
||||
EnterCriticalSection((CRITICAL_SECTION*)m_pMutexObj);
|
||||
EnterCriticalSection(&m_mutexObj);
|
||||
#ifdef DEBUG
|
||||
// CriticalSections on Windows can be locked many times from the same thread,
|
||||
// but we do not want this and must treat such situations as errors and detect them.
|
||||
if (((CRITICAL_SECTION*)m_pMutexObj)->RecursionCount > 1)
|
||||
if (m_mutexObj.RecursionCount > 1)
|
||||
{
|
||||
error("Internal program error: inconsistent thread-lock detected");
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
pthread_mutex_lock((pthread_mutex_t*)m_pMutexObj);
|
||||
pthread_mutex_lock(&m_mutexObj);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Mutex::Unlock()
|
||||
{
|
||||
#ifdef WIN32
|
||||
LeaveCriticalSection((CRITICAL_SECTION*)m_pMutexObj);
|
||||
LeaveCriticalSection(&m_mutexObj);
|
||||
#else
|
||||
pthread_mutex_unlock((pthread_mutex_t*)m_pMutexObj);
|
||||
pthread_mutex_unlock(&m_mutexObj);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
Semaphore::Semaphore()
|
||||
{
|
||||
#ifdef WIN32
|
||||
m_semObj = CreateSemaphore(NULL, 0, 1, NULL);
|
||||
#else
|
||||
sem_init(&m_semObj, 0, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
Semaphore::Semaphore(int iValue)
|
||||
{
|
||||
#ifdef WIN32
|
||||
m_semObj = CreateSemaphore(NULL, iValue, iValue, NULL);
|
||||
#else
|
||||
sem_init(&m_semObj, 0, iValue);
|
||||
#endif
|
||||
}
|
||||
|
||||
Semaphore::~ Semaphore()
|
||||
{
|
||||
#ifdef WIN32
|
||||
CloseHandle(m_semObj);
|
||||
#else
|
||||
sem_destroy(&m_semObj);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Semaphore::Post()
|
||||
{
|
||||
#ifdef WIN32
|
||||
ReleaseSemaphore(m_semObj, 1, NULL);
|
||||
#else
|
||||
sem_post(&m_semObj);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Semaphore::Wait()
|
||||
{
|
||||
#ifdef WIN32
|
||||
return WaitForSingleObject(m_semObj, INFINITE) == WAIT_OBJECT_0;
|
||||
#else
|
||||
return sem_wait(&m_semObj) == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Semaphore::TryWait()
|
||||
{
|
||||
#ifdef WIN32
|
||||
return WaitForSingleObject(m_semObj, 0) == WAIT_OBJECT_0;
|
||||
#else
|
||||
return sem_trywait(&m_semObj) == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Semaphore::TimedWait(int iMSec)
|
||||
{
|
||||
#ifdef WIN32
|
||||
return WaitForSingleObject(m_semObj, iMSec) == WAIT_OBJECT_0;
|
||||
#else
|
||||
struct timespec alarm;
|
||||
alarm.tv_sec = ::time(NULL) + iMSec / 1000;
|
||||
alarm.tv_nsec = (iMSec % 1000) * 1000;
|
||||
return sem_timedwait(&m_semObj, &alarm) == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Semaphore::IsLocked()
|
||||
{
|
||||
#ifdef WIN32
|
||||
bool bCanLock = WaitForSingleObject(m_semObj, 0) == WAIT_OBJECT_0;
|
||||
if (bCanLock)
|
||||
{
|
||||
ReleaseSemaphore(m_semObj, 1, NULL);
|
||||
}
|
||||
return !bCanLock;
|
||||
#else
|
||||
int iSemValue;
|
||||
sem_getvalue(&m_semObj, &iSemValue);
|
||||
return iSemValue <= 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -101,27 +176,18 @@ void Mutex::Unlock()
|
||||
void Thread::Init()
|
||||
{
|
||||
debug("Initializing global thread data");
|
||||
|
||||
m_pMutexThread = new Mutex();
|
||||
}
|
||||
|
||||
void Thread::Final()
|
||||
{
|
||||
debug("Finalizing global thread data");
|
||||
|
||||
delete m_pMutexThread;
|
||||
}
|
||||
|
||||
Thread::Thread()
|
||||
{
|
||||
debug("Creating Thread");
|
||||
|
||||
#ifdef WIN32
|
||||
m_pThreadObj = NULL;
|
||||
#else
|
||||
m_pThreadObj = (pthread_t*)malloc(sizeof(pthread_t));
|
||||
*((pthread_t*)m_pThreadObj) = 0;
|
||||
#endif
|
||||
m_Thread = 0;
|
||||
m_bRunning = false;
|
||||
m_bStopped = false;
|
||||
m_bAutoDestroy = false;
|
||||
@@ -130,9 +196,6 @@ Thread::Thread()
|
||||
Thread::~Thread()
|
||||
{
|
||||
debug("Destroying Thread");
|
||||
#ifndef WIN32
|
||||
free(m_pThreadObj);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Thread::Start()
|
||||
@@ -141,29 +204,30 @@ void Thread::Start()
|
||||
|
||||
m_bRunning = true;
|
||||
|
||||
// NOTE: we must guarantee, that in a time we set m_bRunning
|
||||
// NOTE: we must garantee, that in a time we setting m_bRunning
|
||||
// to value returned from pthread_create, the thread-object still exists.
|
||||
// This is not obviously!
|
||||
// pthread_create could wait long enough before returning result
|
||||
// back to allow the started thread to complete its job and terminate.
|
||||
// We lock mutex m_pMutexThread on calling pthread_create; the started thread
|
||||
// back to allow the started thread to complete it job
|
||||
// and terminate.
|
||||
// We lock mutex m_mutexThread on calling pthread_create; the started thread
|
||||
// then also try to lock the mutex (see thread_handler) and therefore
|
||||
// must wait until we unlock it
|
||||
m_pMutexThread->Lock();
|
||||
m_mutexThread.Lock();
|
||||
|
||||
#ifdef WIN32
|
||||
m_pThreadObj = (HANDLE)_beginthread(Thread::thread_handler, 0, (void *)this);
|
||||
m_bRunning = m_pThreadObj != NULL;
|
||||
m_Thread = (HANDLE)_beginthread(Thread::thread_handler, 0, (void *)this);
|
||||
m_bRunning = m_Thread != NULL;
|
||||
#else
|
||||
pthread_attr_t m_Attr;
|
||||
pthread_attr_init(&m_Attr);
|
||||
pthread_attr_setdetachstate(&m_Attr, PTHREAD_CREATE_DETACHED);
|
||||
pthread_attr_setinheritsched(&m_Attr , PTHREAD_INHERIT_SCHED);
|
||||
m_bRunning = !pthread_create((pthread_t*)m_pThreadObj, &m_Attr, Thread::thread_handler, (void *) this);
|
||||
m_bRunning = !pthread_create(&m_Thread, &m_Attr, Thread::thread_handler, (void *) this);
|
||||
pthread_attr_destroy(&m_Attr);
|
||||
#endif
|
||||
|
||||
m_pMutexThread->Unlock();
|
||||
m_mutexThread.Unlock();
|
||||
}
|
||||
|
||||
void Thread::Stop()
|
||||
@@ -177,19 +241,19 @@ bool Thread::Kill()
|
||||
{
|
||||
debug("Killing Thread");
|
||||
|
||||
m_pMutexThread->Lock();
|
||||
m_mutexThread.Lock();
|
||||
|
||||
#ifdef WIN32
|
||||
bool terminated = TerminateThread((HANDLE)m_pThreadObj, 0) != 0;
|
||||
bool terminated = TerminateThread(m_Thread, 0) != 0;
|
||||
#else
|
||||
bool terminated = pthread_cancel(*(pthread_t*)m_pThreadObj) == 0;
|
||||
bool terminated = pthread_cancel(m_Thread) == 0;
|
||||
#endif
|
||||
|
||||
if (terminated)
|
||||
{
|
||||
m_iThreadCount--;
|
||||
}
|
||||
m_pMutexThread->Unlock();
|
||||
m_mutexThread.Unlock();
|
||||
return terminated;
|
||||
}
|
||||
|
||||
@@ -199,9 +263,9 @@ void __cdecl Thread::thread_handler(void* pObject)
|
||||
void* Thread::thread_handler(void* pObject)
|
||||
#endif
|
||||
{
|
||||
m_pMutexThread->Lock();
|
||||
m_mutexThread.Lock();
|
||||
m_iThreadCount++;
|
||||
m_pMutexThread->Unlock();
|
||||
m_mutexThread.Unlock();
|
||||
|
||||
debug("Entering Thread-func");
|
||||
|
||||
@@ -219,9 +283,9 @@ void* Thread::thread_handler(void* pObject)
|
||||
delete pThread;
|
||||
}
|
||||
|
||||
m_pMutexThread->Lock();
|
||||
m_mutexThread.Lock();
|
||||
m_iThreadCount--;
|
||||
m_pMutexThread->Unlock();
|
||||
m_mutexThread.Unlock();
|
||||
|
||||
#ifndef WIN32
|
||||
return NULL;
|
||||
@@ -230,8 +294,8 @@ void* Thread::thread_handler(void* pObject)
|
||||
|
||||
int Thread::GetThreadCount()
|
||||
{
|
||||
m_pMutexThread->Lock();
|
||||
m_mutexThread.Lock();
|
||||
int iThreadCount = m_iThreadCount;
|
||||
m_pMutexThread->Unlock();
|
||||
m_mutexThread.Unlock();
|
||||
return iThreadCount;
|
||||
}
|
||||
|
||||
53
Thread.h
53
Thread.h
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
* This file if part of nzbget
|
||||
*
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007-2009 Andrei Prygounkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007 Andrei Prygounkov <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,10 +27,19 @@
|
||||
#ifndef THREAD_H
|
||||
#define THREAD_H
|
||||
|
||||
#ifndef WIN32
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
#endif
|
||||
|
||||
class Mutex
|
||||
{
|
||||
private:
|
||||
void* m_pMutexObj;
|
||||
#ifdef WIN32
|
||||
CRITICAL_SECTION m_mutexObj;
|
||||
#else
|
||||
pthread_mutex_t m_mutexObj;
|
||||
#endif
|
||||
|
||||
public:
|
||||
Mutex();
|
||||
@@ -40,12 +49,37 @@ public:
|
||||
};
|
||||
|
||||
|
||||
class Semaphore
|
||||
{
|
||||
private:
|
||||
#ifdef WIN32
|
||||
HANDLE m_semObj;
|
||||
#else
|
||||
sem_t m_semObj;
|
||||
#endif
|
||||
|
||||
public:
|
||||
Semaphore();
|
||||
Semaphore(int iValue);
|
||||
~Semaphore();
|
||||
void Post();
|
||||
bool Wait();
|
||||
bool TryWait();
|
||||
bool TimedWait(int iMSec);
|
||||
bool IsLocked();
|
||||
};
|
||||
|
||||
|
||||
class Thread
|
||||
{
|
||||
private:
|
||||
static Mutex* m_pMutexThread;
|
||||
static Mutex m_mutexThread;
|
||||
static int m_iThreadCount;
|
||||
void* m_pThreadObj;
|
||||
#ifdef WIN32
|
||||
HANDLE m_Thread;
|
||||
#else
|
||||
pthread_t m_Thread;
|
||||
#endif
|
||||
bool m_bRunning;
|
||||
bool m_bStopped;
|
||||
bool m_bAutoDestroy;
|
||||
@@ -57,10 +91,8 @@ private:
|
||||
#endif
|
||||
|
||||
public:
|
||||
Thread();
|
||||
Thread();
|
||||
virtual ~Thread();
|
||||
static void Init();
|
||||
static void Final();
|
||||
|
||||
virtual void Start();
|
||||
virtual void Stop();
|
||||
@@ -73,6 +105,9 @@ public:
|
||||
void SetAutoDestroy(bool bAutoDestroy) { m_bAutoDestroy = bAutoDestroy; }
|
||||
static int GetThreadCount();
|
||||
|
||||
static void Init();
|
||||
static void Final();
|
||||
|
||||
protected:
|
||||
virtual void Run() {}; // Virtual function - override in derivatives
|
||||
};
|
||||
|
||||
333
Util.cpp
333
Util.cpp
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2007-2009 Andrei Prygounkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2007 Andrei Prygounkov <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
|
||||
@@ -41,17 +41,11 @@
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include <sys/statvfs.h>
|
||||
#include <pwd.h>
|
||||
#endif
|
||||
|
||||
#include "nzbget.h"
|
||||
#include "Util.h"
|
||||
|
||||
#ifndef WIN32
|
||||
// function "svn_version" is automatically generated in file "svn_version.cpp" on each build
|
||||
const char* svn_version(void);
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
// getopt for WIN32:
|
||||
@@ -204,8 +198,6 @@ const char* DirBrowser::Next()
|
||||
|
||||
#endif
|
||||
|
||||
char Util::VersionRevisionBuf[40];
|
||||
|
||||
char* Util::BaseFileName(const char* filename)
|
||||
{
|
||||
char* p = (char*)strrchr(filename, PATH_SEPARATOR);
|
||||
@@ -291,22 +283,9 @@ bool Util::ForceDirectories(const char* szPath)
|
||||
return bOK;
|
||||
}
|
||||
|
||||
bool Util::DirEmpty(const char* szDirFilename)
|
||||
{
|
||||
DirBrowser dir(szDirFilename);
|
||||
while (const char* filename = dir.Next())
|
||||
{
|
||||
if (strcmp(filename, ".") && strcmp(filename, ".."))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Util::LoadFileIntoBuffer(const char* szFileName, char** pBuffer, int* pBufferLength)
|
||||
{
|
||||
FILE* pFile = fopen(szFileName, "rb");
|
||||
FILE* pFile = fopen(szFileName, "r");
|
||||
if (!pFile)
|
||||
{
|
||||
return false;
|
||||
@@ -340,7 +319,7 @@ bool Util::SetFileSize(const char* szFilename, int iSize)
|
||||
{
|
||||
bool bOK = false;
|
||||
#ifdef WIN32
|
||||
FILE* pFile = fopen(szFilename, "ab");
|
||||
FILE* pFile = fopen(szFilename, "a");
|
||||
if (pFile)
|
||||
{
|
||||
bOK = _chsize_s(pFile->_file, iSize) == 0;
|
||||
@@ -348,7 +327,7 @@ bool Util::SetFileSize(const char* szFilename, int iSize)
|
||||
}
|
||||
#else
|
||||
// create file
|
||||
FILE* pFile = fopen(szFilename, "ab");
|
||||
FILE* pFile = fopen(szFilename, "a");
|
||||
if (pFile)
|
||||
{
|
||||
fclose(pFile);
|
||||
@@ -358,7 +337,7 @@ bool Util::SetFileSize(const char* szFilename, int iSize)
|
||||
// 1) set file size using function "truncate" (it is fast, if works)
|
||||
truncate(szFilename, iSize);
|
||||
// check if it worked
|
||||
pFile = fopen(szFilename, "ab");
|
||||
pFile = fopen(szFilename, "a");
|
||||
if (pFile)
|
||||
{
|
||||
fseek(pFile, 0, SEEK_END);
|
||||
@@ -368,7 +347,7 @@ bool Util::SetFileSize(const char* szFilename, int iSize)
|
||||
// 2) truncate did not work, expanding the file by writing in it (it is slow)
|
||||
fclose(pFile);
|
||||
truncate(szFilename, 0);
|
||||
pFile = fopen(szFilename, "ab");
|
||||
pFile = fopen(szFilename, "a");
|
||||
char c = '0';
|
||||
fwrite(&c, 1, iSize, pFile);
|
||||
bOK = ftell(pFile) == iSize;
|
||||
@@ -380,20 +359,15 @@ bool Util::SetFileSize(const char* szFilename, int iSize)
|
||||
}
|
||||
|
||||
//replace bad chars in filename
|
||||
void Util::MakeValidFilename(char* szFilename, char cReplaceChar, bool bAllowSlashes)
|
||||
void Util::MakeValidFilename(char* szFilename, char cReplaceChar)
|
||||
{
|
||||
const char* szReplaceChars = bAllowSlashes ? ":*?\"><'\n\r\t" : "\\/:*?\"><'\n\r\t";
|
||||
char* p = szFilename;
|
||||
while (*p)
|
||||
{
|
||||
if (strchr(szReplaceChars, *p))
|
||||
if (strchr("\\/:*?\"><'\n\r\t", *p))
|
||||
{
|
||||
*p = cReplaceChar;
|
||||
}
|
||||
if (bAllowSlashes && *p == ALT_PATH_SEPARATOR)
|
||||
{
|
||||
*p = PATH_SEPARATOR;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
|
||||
@@ -423,6 +397,33 @@ float Util::Int64ToFloat(long long Int64)
|
||||
return ((unsigned long)(1 << 30)) * 4.0f * Hi + Lo;
|
||||
}
|
||||
|
||||
float Util::EqualTime(_timeval* t1, _timeval* t2)
|
||||
{
|
||||
#ifdef WIN32
|
||||
return t1->time == t2->time && t1->millitm == t2->millitm;
|
||||
#else
|
||||
return t1->tv_sec == t2->tv_sec && t1->tv_usec == t2->tv_usec;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Util::EmptyTime(_timeval* t)
|
||||
{
|
||||
#ifdef WIN32
|
||||
return t->time == 0 && t->millitm == 0;
|
||||
#else
|
||||
return t->tv_sec == 0 && t->tv_usec == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
float Util::DiffTime(_timeval* t1, _timeval* t2)
|
||||
{
|
||||
#ifdef WIN32
|
||||
return ((t1->time - t2->time) + (t1->millitm - t2->millitm) / 1000.0f);
|
||||
#else
|
||||
return (float)((t1->tv_sec - t2->tv_sec) + (t1->tv_usec - t2->tv_usec) / 1000000.0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Base64 decryption is taken from
|
||||
* Article "BASE 64 Decoding and Encoding Class 2003" by Jan Raddatz
|
||||
* http://www.codeguru.com/cpp/cpp/algorithms/article.php/c5099/
|
||||
@@ -499,27 +500,27 @@ unsigned int Util::DecodeBase64(char* szInputBuffer, int iInputBufferLength, cha
|
||||
unsigned int InputBufferLength = iInputBufferLength > 0 ? iInputBufferLength : strlen(szInputBuffer);
|
||||
|
||||
char ByteQuartet [4];
|
||||
int i = 0;
|
||||
|
||||
while (InputBufferIndex < InputBufferLength)
|
||||
{
|
||||
// Ignore all characters except the ones in BASE64_ALPHABET
|
||||
if ((szInputBuffer [InputBufferIndex] >= 48 && szInputBuffer [InputBufferIndex] <= 57) ||
|
||||
(szInputBuffer [InputBufferIndex] >= 65 && szInputBuffer [InputBufferIndex] <= 90) ||
|
||||
(szInputBuffer [InputBufferIndex] >= 97 && szInputBuffer [InputBufferIndex] <= 122) ||
|
||||
szInputBuffer [InputBufferIndex] == '+' ||
|
||||
szInputBuffer [InputBufferIndex] == '/' ||
|
||||
szInputBuffer [InputBufferIndex] == '=')
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
ByteQuartet [i] = szInputBuffer [InputBufferIndex];
|
||||
i++;
|
||||
}
|
||||
|
||||
InputBufferIndex++;
|
||||
|
||||
if (i == 4) {
|
||||
OutputBufferIndex += DecodeByteQuartet(ByteQuartet, szOutputBuffer + OutputBufferIndex);
|
||||
i = 0;
|
||||
ByteQuartet [i] = szInputBuffer[InputBufferIndex];
|
||||
|
||||
// Ignore all characters except the ones in BASE64_ALPHABET
|
||||
if (!((ByteQuartet [i] >= 48 && ByteQuartet [i] <= 57) ||
|
||||
(ByteQuartet [i] >= 65 && ByteQuartet [i] <= 90) ||
|
||||
(ByteQuartet [i] >= 97 && ByteQuartet [i] <= 122) ||
|
||||
ByteQuartet [i] == '+' || ByteQuartet [i] == '/' || ByteQuartet [i] == '='))
|
||||
{
|
||||
// Invalid character
|
||||
i--;
|
||||
}
|
||||
|
||||
InputBufferIndex++;
|
||||
}
|
||||
|
||||
OutputBufferIndex += DecodeByteQuartet(ByteQuartet, szOutputBuffer + OutputBufferIndex);
|
||||
}
|
||||
|
||||
// OutputBufferIndex gives us the next position of the next decoded character
|
||||
@@ -676,19 +677,8 @@ const char* Util::XmlFindTag(const char* szXml, const char* szTag, int* pValueLe
|
||||
snprintf(szCloseTag, 100, "</%s>", szTag);
|
||||
szCloseTag[100-1] = '\0';
|
||||
|
||||
char szOpenCloseTag[100];
|
||||
snprintf(szOpenCloseTag, 100, "<%s/>", szTag);
|
||||
szOpenCloseTag[100-1] = '\0';
|
||||
|
||||
const char* pstart = strstr(szXml, szOpenTag);
|
||||
const char* pstartend = strstr(szXml, szOpenCloseTag);
|
||||
if (!pstart && !pstartend) return NULL;
|
||||
|
||||
if (pstartend && (!pstart || pstartend < pstart))
|
||||
{
|
||||
*pValueLength = 0;
|
||||
return pstartend;
|
||||
}
|
||||
if (!pstart) return NULL;
|
||||
|
||||
const char* pend = strstr(pstart, szCloseTag);
|
||||
if (!pend) return NULL;
|
||||
@@ -724,13 +714,13 @@ bool Util::MoveFile(const char* szSrcFilename, const char* szDstFilename)
|
||||
#ifndef WIN32
|
||||
if (!bOK && (errno == EXDEV))
|
||||
{
|
||||
FILE* infile = fopen(szSrcFilename, "rb");
|
||||
FILE* infile = fopen(szSrcFilename, "r");
|
||||
if (!infile)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
FILE* outfile = fopen(szDstFilename, "wb+");
|
||||
FILE* outfile = fopen(szDstFilename, "w+");
|
||||
if (!outfile)
|
||||
{
|
||||
fclose(infile);
|
||||
@@ -1013,216 +1003,3 @@ long long Util::FreeDiskSize(const char* szPath)
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool Util::RenameBak(const char* szFilename, const char* szBakPart, bool bRemoveOldExtension, char* szNewNameBuf, int iNewNameBufSize)
|
||||
{
|
||||
char szChangedFilename[1024];
|
||||
|
||||
if (bRemoveOldExtension)
|
||||
{
|
||||
strncpy(szChangedFilename, szFilename, 1024);
|
||||
szChangedFilename[1024-1] = '\0';
|
||||
char* szExtension = strrchr(szChangedFilename, '.');
|
||||
if (szExtension)
|
||||
{
|
||||
*szExtension = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
char bakname[1024];
|
||||
snprintf(bakname, 1024, "%s.%s", bRemoveOldExtension ? szChangedFilename : szFilename, szBakPart);
|
||||
bakname[1024-1] = '\0';
|
||||
|
||||
int i = 2;
|
||||
struct stat buffer;
|
||||
while (!stat(bakname, &buffer))
|
||||
{
|
||||
snprintf(bakname, 1024, "%s.%i.%s", bRemoveOldExtension ? szChangedFilename : szFilename, i++, szBakPart);
|
||||
bakname[1024-1] = '\0';
|
||||
}
|
||||
|
||||
if (szNewNameBuf)
|
||||
{
|
||||
strncpy(szNewNameBuf, bakname, iNewNameBufSize);
|
||||
}
|
||||
|
||||
bool bOK = !rename(szFilename, bakname);
|
||||
return bOK;
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
bool Util::ExpandHomePath(const char* szFilename, char* szBuffer, int iBufSize)
|
||||
{
|
||||
if (szFilename && (szFilename[0] == '~') && (szFilename[1] == '/'))
|
||||
{
|
||||
// expand home-dir
|
||||
|
||||
char* home = getenv("HOME");
|
||||
if (!home)
|
||||
{
|
||||
struct passwd *pw = getpwuid(getuid());
|
||||
if (pw)
|
||||
{
|
||||
home = pw->pw_dir;
|
||||
}
|
||||
}
|
||||
|
||||
if (!home)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (home[strlen(home)-1] == '/')
|
||||
{
|
||||
snprintf(szBuffer, iBufSize, "%s%s", home, szFilename + 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(szBuffer, iBufSize, "%s/%s", home, szFilename + 2);
|
||||
}
|
||||
szBuffer[iBufSize - 1] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
strncpy(szBuffer, szFilename, iBufSize);
|
||||
szBuffer[iBufSize - 1] = '\0';
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Util::ExpandFileName(const char* szFilename, char* szBuffer, int iBufSize)
|
||||
{
|
||||
if (szFilename[0] != '\0' && szFilename[0] != '/')
|
||||
{
|
||||
char szCurDir[MAX_PATH + 1];
|
||||
getcwd(szCurDir, sizeof(szCurDir) - 1); // 1 char reserved for adding backslash
|
||||
int iOffset = 0;
|
||||
if (szFilename[0] == '.' && szFilename[1] == '/')
|
||||
{
|
||||
iOffset += 2;
|
||||
}
|
||||
snprintf(szBuffer, iBufSize, "%s/%s", szCurDir, szFilename + iOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
strncpy(szBuffer, szFilename, iBufSize);
|
||||
szBuffer[iBufSize - 1] = '\0';
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void Util::FormatFileSize(char * szBuffer, int iBufLen, long long lFileSize)
|
||||
{
|
||||
if (lFileSize > 1024 * 1024 * 1000)
|
||||
{
|
||||
snprintf(szBuffer, iBufLen, "%.2f GB", (float)(Util::Int64ToFloat(lFileSize) / 1024 / 1024 / 1024));
|
||||
}
|
||||
else if (lFileSize > 1024 * 1000)
|
||||
{
|
||||
snprintf(szBuffer, iBufLen, "%.2f MB", (float)(Util::Int64ToFloat(lFileSize) / 1024 / 1024));
|
||||
}
|
||||
else if (lFileSize > 1000)
|
||||
{
|
||||
snprintf(szBuffer, iBufLen, "%.2f KB", (float)(Util::Int64ToFloat(lFileSize) / 1024));
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(szBuffer, iBufLen, "%i B", (int)lFileSize);
|
||||
}
|
||||
szBuffer[iBufLen - 1] = '\0';
|
||||
}
|
||||
|
||||
void Util::InitVersionRevision()
|
||||
{
|
||||
#ifndef WIN32
|
||||
if ((strlen(svn_version()) > 0) && strstr(VERSION, "testing"))
|
||||
{
|
||||
snprintf(VersionRevisionBuf, sizeof(VersionRevisionBuf), "%s-r%s", VERSION, svn_version());
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
snprintf(VersionRevisionBuf, sizeof(VersionRevisionBuf), "%s", VERSION);
|
||||
}
|
||||
}
|
||||
|
||||
bool Util::SplitCommandLine(const char* szCommandLine, char*** argv)
|
||||
{
|
||||
int iArgCount = 0;
|
||||
char szBuf[1024];
|
||||
char* pszArgList[100];
|
||||
unsigned int iLen = 0;
|
||||
bool bEscaping = false;
|
||||
bool bSpace = true;
|
||||
for (const char* p = szCommandLine; ; p++)
|
||||
{
|
||||
if (*p)
|
||||
{
|
||||
const char c = *p;
|
||||
if (bEscaping)
|
||||
{
|
||||
if (c == '\'')
|
||||
{
|
||||
if (p[1] == '\'' && iLen < sizeof(szBuf) - 1)
|
||||
{
|
||||
szBuf[iLen++] = c;
|
||||
p++;
|
||||
}
|
||||
else
|
||||
{
|
||||
bEscaping = false;
|
||||
bSpace = true;
|
||||
}
|
||||
}
|
||||
else if (iLen < sizeof(szBuf) - 1)
|
||||
{
|
||||
szBuf[iLen++] = c;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (c == ' ')
|
||||
{
|
||||
bSpace = true;
|
||||
}
|
||||
else if (c == '\'' && bSpace)
|
||||
{
|
||||
bEscaping = true;
|
||||
bSpace = false;
|
||||
}
|
||||
else if (iLen < sizeof(szBuf) - 1)
|
||||
{
|
||||
szBuf[iLen++] = c;
|
||||
bSpace = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((bSpace || !*p) && iLen > 0 && iArgCount < 100)
|
||||
{
|
||||
//add token
|
||||
szBuf[iLen] = '\0';
|
||||
if (argv)
|
||||
{
|
||||
pszArgList[iArgCount] = strdup(szBuf);
|
||||
}
|
||||
(iArgCount)++;
|
||||
iLen = 0;
|
||||
}
|
||||
|
||||
if (!*p)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (argv)
|
||||
{
|
||||
pszArgList[iArgCount] = NULL;
|
||||
*argv = (char**)malloc((iArgCount + 1) * sizeof(char*));
|
||||
memcpy(*argv, pszArgList, sizeof(char*) * (iArgCount + 1));
|
||||
}
|
||||
|
||||
return iArgCount > 0;
|
||||
}
|
||||
|
||||
45
Util.h
45
Util.h
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2007-2009 Andrei Prygounkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2007 Andrei Prygounkov <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,6 +29,7 @@
|
||||
#ifdef WIN32
|
||||
#include <stdio.h>
|
||||
#include <io.h>
|
||||
#include <sys/timeb.h>
|
||||
#else
|
||||
#include <dirent.h>
|
||||
#endif
|
||||
@@ -65,7 +66,7 @@ public:
|
||||
static void NormalizePathSeparators(char* szPath);
|
||||
static bool LoadFileIntoBuffer(const char* szFileName, char** pBuffer, int* pBufferLength);
|
||||
static bool SetFileSize(const char* szFilename, int iSize);
|
||||
static void MakeValidFilename(char* szFilename, char cReplaceChar, bool bAllowSlashes);
|
||||
static void MakeValidFilename(char* szFilename, char cReplaceChar);
|
||||
static bool MoveFile(const char* szSrcFilename, const char* szDstFilename);
|
||||
static bool FileExists(const char* szFilename);
|
||||
static bool DirectoryExists(const char* szDirFilename);
|
||||
@@ -73,27 +74,6 @@ public:
|
||||
static bool ForceDirectories(const char* szPath);
|
||||
static long long FileSize(const char* szFilename);
|
||||
static long long FreeDiskSize(const char* szPath);
|
||||
static bool DirEmpty(const char* szDirFilename);
|
||||
static bool RenameBak(const char* szFilename, const char* szBakPart, bool bRemoveOldExtension, char* szNewNameBuf, int iNewNameBufSize);
|
||||
#ifndef WIN32
|
||||
static bool ExpandHomePath(const char* szFilename, char* szBuffer, int iBufSize);
|
||||
static void ExpandFileName(const char* szFilename, char* szBuffer, int iBufSize);
|
||||
#endif
|
||||
static void FormatFileSize(char* szBuffer, int iBufLen, long long lFileSize);
|
||||
|
||||
/*
|
||||
* Split command line int arguments.
|
||||
* Uses spaces and single quotation marks as separators.
|
||||
* Returns bool if sucessful or false if bad escaping was detected.
|
||||
* Parameter "argv" may be NULL if only a syntax check is needed.
|
||||
* Parsed parameters returned in Array "argv", which contains at least one element.
|
||||
* The last element in array is NULL.
|
||||
* Restrictions: the number of arguments is limited to 100 and each arguments must
|
||||
* be maximum 1024 chars long.
|
||||
* If these restrictions are exceeded, only first 100 arguments and only first 1024
|
||||
* for each argument are returned (the functions still returns "true").
|
||||
*/
|
||||
static bool SplitCommandLine(const char* szCommandLine, char*** argv);
|
||||
|
||||
static long long JoinInt64(unsigned long Hi, unsigned long Lo);
|
||||
static void SplitInt64(long long Int64, unsigned long* Hi, unsigned long* Lo);
|
||||
@@ -105,6 +85,10 @@ public:
|
||||
*/
|
||||
static float Int64ToFloat(long long Int64);
|
||||
|
||||
static float EqualTime(_timeval* t1, _timeval* t2);
|
||||
static bool EmptyTime(_timeval* t);
|
||||
static float DiffTime(_timeval* t1, _timeval* t2);
|
||||
|
||||
static unsigned int DecodeBase64(char* szInputBuffer, int iInputBufferLength, char* szOutputBuffer);
|
||||
|
||||
/*
|
||||
@@ -153,21 +137,6 @@ public:
|
||||
* The returned pointer points to the part of source-string, no additional strings are allocated.
|
||||
*/
|
||||
static const char* JsonNextValue(const char* szJsonText, int* pValueLength);
|
||||
|
||||
/*
|
||||
* 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").
|
||||
*/
|
||||
static const char* VersionRevision() { return VersionRevisionBuf; };
|
||||
|
||||
/*
|
||||
* Initialize buffer for program version and revision number.
|
||||
* This function must be called during program initialization before any
|
||||
* call to "VersionRevision()".
|
||||
*/
|
||||
static void InitVersionRevision();
|
||||
|
||||
static char VersionRevisionBuf[40];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
618
XmlRpc.cpp
618
XmlRpc.cpp
File diff suppressed because it is too large
Load Diff
45
XmlRpc.h
45
XmlRpc.h
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2007-2010 Andrei Prygounkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2007 Andrei Prygounkov <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
|
||||
@@ -26,6 +26,8 @@
|
||||
#ifndef XMLRPC_H
|
||||
#define XMLRPC_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "Connection.h"
|
||||
|
||||
class StringBuilder
|
||||
@@ -50,8 +52,7 @@ public:
|
||||
{
|
||||
rpUndefined,
|
||||
rpXmlRpc,
|
||||
rpJsonRpc,
|
||||
rpJsonPRpc
|
||||
rpJsonRpc
|
||||
};
|
||||
|
||||
enum EHttpMethod
|
||||
@@ -69,8 +70,7 @@ private:
|
||||
char* m_szUrl;
|
||||
|
||||
void Dispatch();
|
||||
void SendAuthResponse();
|
||||
void SendResponse(const char* szResponse, const char* szCallbackFunc, bool bFault);
|
||||
void SendResponse(const char* szResponse, bool bFault);
|
||||
XmlCommand* CreateCommand(const char* szMethodName);
|
||||
void MutliCall();
|
||||
|
||||
@@ -90,7 +90,6 @@ class XmlCommand
|
||||
protected:
|
||||
char* m_szRequest;
|
||||
char* m_szRequestPtr;
|
||||
char* m_szCallbackFunc;
|
||||
StringBuilder m_StringBuilder;
|
||||
bool m_bFault;
|
||||
XmlRpcProcessor::ERpcProtocol m_eProtocol;
|
||||
@@ -99,8 +98,7 @@ protected:
|
||||
void BuildErrorResponse(int iErrCode, const char* szErrText);
|
||||
void BuildBoolResponse(bool bOK);
|
||||
void AppendResponse(const char* szPart);
|
||||
bool IsJson();
|
||||
bool CheckSafeMethod();
|
||||
bool IsJson() { return m_eProtocol == XmlRpcProcessor::rpJsonRpc; }
|
||||
bool NextParamAsInt(int* iValue);
|
||||
bool NextParamAsBool(bool* bValue);
|
||||
bool NextParamAsStr(char** szValueBuf);
|
||||
@@ -116,7 +114,6 @@ public:
|
||||
void SetProtocol(XmlRpcProcessor::ERpcProtocol eProtocol) { m_eProtocol = eProtocol; }
|
||||
void SetHttpMethod(XmlRpcProcessor::EHttpMethod eHttpMethod) { m_eHttpMethod = eHttpMethod; }
|
||||
const char* GetResponse() { return m_StringBuilder.GetBuffer(); }
|
||||
const char* GetCallbackFunc() { return m_szCallbackFunc; }
|
||||
bool GetFault() { return m_bFault; }
|
||||
};
|
||||
|
||||
@@ -131,23 +128,15 @@ public:
|
||||
virtual void Execute();
|
||||
};
|
||||
|
||||
class PauseUnpauseXmlCommand: public XmlCommand
|
||||
class PauseXmlCommand: public XmlCommand
|
||||
{
|
||||
public:
|
||||
enum EPauseAction
|
||||
{
|
||||
paDownload,
|
||||
paDownload2,
|
||||
paPostProcess,
|
||||
paScan
|
||||
};
|
||||
|
||||
private:
|
||||
bool m_bPause;
|
||||
EPauseAction m_eEPauseAction;
|
||||
virtual void Execute();
|
||||
};
|
||||
|
||||
class UnPauseXmlCommand: public XmlCommand
|
||||
{
|
||||
public:
|
||||
PauseUnpauseXmlCommand(bool bPause, EPauseAction eEPauseAction);
|
||||
virtual void Execute();
|
||||
};
|
||||
|
||||
@@ -223,16 +212,4 @@ public:
|
||||
virtual void Execute();
|
||||
};
|
||||
|
||||
class ScanXmlCommand: public XmlCommand
|
||||
{
|
||||
public:
|
||||
virtual void Execute();
|
||||
};
|
||||
|
||||
class HistoryXmlCommand: public XmlCommand
|
||||
{
|
||||
public:
|
||||
virtual void Execute();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
330
aclocal.m4
vendored
330
aclocal.m4
vendored
@@ -1,7 +1,7 @@
|
||||
# generated automatically by aclocal 1.9.6 -*- Autoconf -*-
|
||||
# generated automatically by aclocal 1.10 -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
|
||||
# 2005 Free Software Foundation, Inc.
|
||||
# 2005, 2006 Free Software Foundation, Inc.
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
@@ -11,165 +11,12 @@
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
|
||||
#
|
||||
# Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
|
||||
#
|
||||
# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
m4_if(m4_PACKAGE_VERSION, [2.61],,
|
||||
[m4_fatal([this file was generated for autoconf 2.61.
|
||||
You have another version of autoconf. If you want to use that,
|
||||
you should regenerate the build system entirely.], [63])])
|
||||
|
||||
# PKG_PROG_PKG_CONFIG([MIN-VERSION])
|
||||
# ----------------------------------
|
||||
AC_DEFUN([PKG_PROG_PKG_CONFIG],
|
||||
[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
|
||||
m4_pattern_allow([^PKG_CONFIG(_PATH)?$])
|
||||
AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl
|
||||
if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
|
||||
AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
|
||||
fi
|
||||
if test -n "$PKG_CONFIG"; then
|
||||
_pkg_min_version=m4_default([$1], [0.9.0])
|
||||
AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
|
||||
if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
PKG_CONFIG=""
|
||||
fi
|
||||
|
||||
fi[]dnl
|
||||
])# PKG_PROG_PKG_CONFIG
|
||||
|
||||
# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
|
||||
#
|
||||
# Check to see whether a particular set of modules exists. Similar
|
||||
# to PKG_CHECK_MODULES(), but does not set variables or print errors.
|
||||
#
|
||||
#
|
||||
# Similar to PKG_CHECK_MODULES, make sure that the first instance of
|
||||
# this or PKG_CHECK_MODULES is called, or make sure to call
|
||||
# PKG_CHECK_EXISTS manually
|
||||
# --------------------------------------------------------------
|
||||
AC_DEFUN([PKG_CHECK_EXISTS],
|
||||
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
|
||||
if test -n "$PKG_CONFIG" && \
|
||||
AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
|
||||
m4_ifval([$2], [$2], [:])
|
||||
m4_ifvaln([$3], [else
|
||||
$3])dnl
|
||||
fi])
|
||||
|
||||
|
||||
# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
|
||||
# ---------------------------------------------
|
||||
m4_define([_PKG_CONFIG],
|
||||
[if test -n "$PKG_CONFIG"; then
|
||||
if test -n "$$1"; then
|
||||
pkg_cv_[]$1="$$1"
|
||||
else
|
||||
PKG_CHECK_EXISTS([$3],
|
||||
[pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`],
|
||||
[pkg_failed=yes])
|
||||
fi
|
||||
else
|
||||
pkg_failed=untried
|
||||
fi[]dnl
|
||||
])# _PKG_CONFIG
|
||||
|
||||
# _PKG_SHORT_ERRORS_SUPPORTED
|
||||
# -----------------------------
|
||||
AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
|
||||
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
|
||||
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
|
||||
_pkg_short_errors_supported=yes
|
||||
else
|
||||
_pkg_short_errors_supported=no
|
||||
fi[]dnl
|
||||
])# _PKG_SHORT_ERRORS_SUPPORTED
|
||||
|
||||
|
||||
# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
|
||||
# [ACTION-IF-NOT-FOUND])
|
||||
#
|
||||
#
|
||||
# Note that if there is a possibility the first call to
|
||||
# PKG_CHECK_MODULES might not happen, you should be sure to include an
|
||||
# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
|
||||
#
|
||||
#
|
||||
# --------------------------------------------------------------
|
||||
AC_DEFUN([PKG_CHECK_MODULES],
|
||||
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
|
||||
AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
|
||||
AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
|
||||
|
||||
pkg_failed=no
|
||||
AC_MSG_CHECKING([for $1])
|
||||
|
||||
_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
|
||||
_PKG_CONFIG([$1][_LIBS], [libs], [$2])
|
||||
|
||||
m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
|
||||
and $1[]_LIBS to avoid the need to call pkg-config.
|
||||
See the pkg-config man page for more details.])
|
||||
|
||||
if test $pkg_failed = yes; then
|
||||
_PKG_SHORT_ERRORS_SUPPORTED
|
||||
if test $_pkg_short_errors_supported = yes; then
|
||||
$1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "$2"`
|
||||
else
|
||||
$1[]_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"`
|
||||
fi
|
||||
# Put the nasty error message in config.log where it belongs
|
||||
echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
|
||||
|
||||
ifelse([$4], , [AC_MSG_ERROR(dnl
|
||||
[Package requirements ($2) were not met:
|
||||
|
||||
$$1_PKG_ERRORS
|
||||
|
||||
Consider adjusting the PKG_CONFIG_PATH environment variable if you
|
||||
installed software in a non-standard prefix.
|
||||
|
||||
_PKG_TEXT
|
||||
])],
|
||||
[AC_MSG_RESULT([no])
|
||||
$4])
|
||||
elif test $pkg_failed = untried; then
|
||||
ifelse([$4], , [AC_MSG_FAILURE(dnl
|
||||
[The pkg-config script could not be found or is too old. Make sure it
|
||||
is in your PATH or set the PKG_CONFIG environment variable to the full
|
||||
path to pkg-config.
|
||||
|
||||
_PKG_TEXT
|
||||
|
||||
To get pkg-config, see <http://pkg-config.freedesktop.org/>.])],
|
||||
[$4])
|
||||
else
|
||||
$1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
|
||||
$1[]_LIBS=$pkg_cv_[]$1[]_LIBS
|
||||
AC_MSG_RESULT([yes])
|
||||
ifelse([$3], , :, [$3])
|
||||
fi[]dnl
|
||||
])# PKG_CHECK_MODULES
|
||||
|
||||
# Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2002, 2003, 2005, 2006 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
@@ -179,14 +26,29 @@ fi[]dnl
|
||||
# ----------------------------
|
||||
# Automake X.Y traces this macro to ensure aclocal.m4 has been
|
||||
# generated from the m4 files accompanying Automake X.Y.
|
||||
AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version="1.9"])
|
||||
# (This private macro should not be called outside this file.)
|
||||
AC_DEFUN([AM_AUTOMAKE_VERSION],
|
||||
[am__api_version='1.10'
|
||||
dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
|
||||
dnl require some minimum version. Point them to the right macro.
|
||||
m4_if([$1], [1.10], [],
|
||||
[AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
|
||||
])
|
||||
|
||||
# _AM_AUTOCONF_VERSION(VERSION)
|
||||
# -----------------------------
|
||||
# aclocal traces this macro to find the Autoconf version.
|
||||
# This is a private macro too. Using m4_define simplifies
|
||||
# the logic in aclocal, which can simply ignore this definition.
|
||||
m4_define([_AM_AUTOCONF_VERSION], [])
|
||||
|
||||
# AM_SET_CURRENT_AUTOMAKE_VERSION
|
||||
# -------------------------------
|
||||
# Call AM_AUTOMAKE_VERSION so it can be traced.
|
||||
# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
|
||||
# This function is AC_REQUIREd by AC_INIT_AUTOMAKE.
|
||||
AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
|
||||
[AM_AUTOMAKE_VERSION([1.9.6])])
|
||||
[AM_AUTOMAKE_VERSION([1.10])dnl
|
||||
_AM_AUTOCONF_VERSION(m4_PACKAGE_VERSION)])
|
||||
|
||||
# AM_AUX_DIR_EXPAND -*- Autoconf -*-
|
||||
|
||||
@@ -243,14 +105,14 @@ am_aux_dir=`cd $ac_aux_dir && pwd`
|
||||
|
||||
# AM_CONDITIONAL -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005
|
||||
# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006
|
||||
# Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# serial 7
|
||||
# serial 8
|
||||
|
||||
# AM_CONDITIONAL(NAME, SHELL-CONDITION)
|
||||
# -------------------------------------
|
||||
@@ -259,8 +121,10 @@ AC_DEFUN([AM_CONDITIONAL],
|
||||
[AC_PREREQ(2.52)dnl
|
||||
ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])],
|
||||
[$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
|
||||
AC_SUBST([$1_TRUE])
|
||||
AC_SUBST([$1_FALSE])
|
||||
AC_SUBST([$1_TRUE])dnl
|
||||
AC_SUBST([$1_FALSE])dnl
|
||||
_AM_SUBST_NOTMAKE([$1_TRUE])dnl
|
||||
_AM_SUBST_NOTMAKE([$1_FALSE])dnl
|
||||
if $2; then
|
||||
$1_TRUE=
|
||||
$1_FALSE='#'
|
||||
@@ -274,15 +138,14 @@ AC_CONFIG_COMMANDS_PRE(
|
||||
Usually this means the macro was only invoked conditionally.]])
|
||||
fi])])
|
||||
|
||||
|
||||
# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
|
||||
# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
|
||||
# Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# serial 8
|
||||
# serial 9
|
||||
|
||||
# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be
|
||||
# written in clear, in which case automake, when reading aclocal.m4,
|
||||
@@ -310,6 +173,7 @@ AC_REQUIRE([AM_DEP_TRACK])dnl
|
||||
ifelse([$1], CC, [depcc="$CC" am_compiler_list=],
|
||||
[$1], CXX, [depcc="$CXX" am_compiler_list=],
|
||||
[$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'],
|
||||
[$1], UPC, [depcc="$UPC" am_compiler_list=],
|
||||
[$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'],
|
||||
[depcc="$$1" am_compiler_list=])
|
||||
|
||||
@@ -375,6 +239,7 @@ AC_CACHE_CHECK([dependency style of $depcc],
|
||||
depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
|
||||
$SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \
|
||||
>/dev/null 2>conftest.err &&
|
||||
grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
|
||||
grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
|
||||
grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
|
||||
${MAKE-make} -s -f confmf > /dev/null 2>&1; then
|
||||
@@ -427,7 +292,8 @@ if test "x$enable_dependency_tracking" != xno; then
|
||||
AMDEPBACKSLASH='\'
|
||||
fi
|
||||
AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
|
||||
AC_SUBST([AMDEPBACKSLASH])
|
||||
AC_SUBST([AMDEPBACKSLASH])dnl
|
||||
_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl
|
||||
])
|
||||
|
||||
# Generate code to set up dependency tracking. -*- Autoconf -*-
|
||||
@@ -452,8 +318,9 @@ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
|
||||
# some people rename them; so instead we look at the file content.
|
||||
# Grep'ing the first line is not enough: some people post-process
|
||||
# each Makefile.in and add a new line on top of each file to say so.
|
||||
# So let's grep whole file.
|
||||
if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then
|
||||
# Grep'ing the whole file is not good either: AIX grep has a line
|
||||
# limit of 2048, but all sed's we know have understand at least 4000.
|
||||
if sed 10q "$mf" | grep '^#.*generated by automake' > /dev/null 2>&1; then
|
||||
dirpart=`AS_DIRNAME("$mf")`
|
||||
else
|
||||
continue
|
||||
@@ -500,8 +367,8 @@ AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
|
||||
|
||||
# Do all the work for Automake. -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
|
||||
# Free Software Foundation, Inc.
|
||||
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
|
||||
# 2005, 2006 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
@@ -524,16 +391,20 @@ AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
|
||||
# arguments mandatory, and then we can depend on a new Autoconf
|
||||
# release and drop the old call support.
|
||||
AC_DEFUN([AM_INIT_AUTOMAKE],
|
||||
[AC_PREREQ([2.58])dnl
|
||||
[AC_PREREQ([2.60])dnl
|
||||
dnl Autoconf wants to disallow AM_ names. We explicitly allow
|
||||
dnl the ones we care about.
|
||||
m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
|
||||
AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
|
||||
AC_REQUIRE([AC_PROG_INSTALL])dnl
|
||||
# test to see if srcdir already configured
|
||||
if test "`cd $srcdir && pwd`" != "`pwd`" &&
|
||||
test -f $srcdir/config.status; then
|
||||
AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
|
||||
if test "`cd $srcdir && pwd`" != "`pwd`"; then
|
||||
# Use -I$(srcdir) only when $(srcdir) != ., so that make's output
|
||||
# is not polluted with repeated "-I."
|
||||
AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl
|
||||
# test to see if srcdir already configured
|
||||
if test -f $srcdir/config.status; then
|
||||
AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
|
||||
fi
|
||||
fi
|
||||
|
||||
# test whether we have cygpath
|
||||
@@ -553,6 +424,9 @@ m4_ifval([$2],
|
||||
AC_SUBST([PACKAGE], [$1])dnl
|
||||
AC_SUBST([VERSION], [$2])],
|
||||
[_AM_SET_OPTIONS([$1])dnl
|
||||
dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
|
||||
m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,,
|
||||
[m4_fatal([AC_INIT should be called with package and version arguments])])dnl
|
||||
AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
|
||||
AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
|
||||
|
||||
@@ -588,6 +462,10 @@ AC_PROVIDE_IFELSE([AC_PROG_CXX],
|
||||
[_AM_DEPENDENCIES(CXX)],
|
||||
[define([AC_PROG_CXX],
|
||||
defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl
|
||||
AC_PROVIDE_IFELSE([AC_PROG_OBJC],
|
||||
[_AM_DEPENDENCIES(OBJC)],
|
||||
[define([AC_PROG_OBJC],
|
||||
defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl
|
||||
])
|
||||
])
|
||||
|
||||
@@ -623,7 +501,7 @@ echo "timestamp for $1" >`AS_DIRNAME([$1])`/stamp-h[]$_am_stamp_count])
|
||||
# Define $install_sh.
|
||||
AC_DEFUN([AM_PROG_INSTALL_SH],
|
||||
[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
|
||||
install_sh=${install_sh-"$am_aux_dir/install-sh"}
|
||||
install_sh=${install_sh-"\$(SHELL) $am_aux_dir/install-sh"}
|
||||
AC_SUBST(install_sh)])
|
||||
|
||||
# Copyright (C) 2003, 2005 Free Software Foundation, Inc.
|
||||
@@ -701,14 +579,14 @@ rm -f confinc confmf
|
||||
|
||||
# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2005
|
||||
# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005
|
||||
# Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# serial 4
|
||||
# serial 5
|
||||
|
||||
# AM_MISSING_PROG(NAME, PROGRAM)
|
||||
# ------------------------------
|
||||
@@ -724,6 +602,7 @@ AC_SUBST($1)])
|
||||
# If it does, set am_missing_run to use it, otherwise, to nothing.
|
||||
AC_DEFUN([AM_MISSING_HAS_RUN],
|
||||
[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
|
||||
AC_REQUIRE_AUX_FILE([missing])dnl
|
||||
test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing"
|
||||
# Use eval to expand $SHELL
|
||||
if eval "$MISSING --run true"; then
|
||||
@@ -734,7 +613,7 @@ else
|
||||
fi
|
||||
])
|
||||
|
||||
# Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
@@ -742,60 +621,23 @@ fi
|
||||
|
||||
# AM_PROG_MKDIR_P
|
||||
# ---------------
|
||||
# Check whether `mkdir -p' is supported, fallback to mkinstalldirs otherwise.
|
||||
#
|
||||
# Automake 1.8 used `mkdir -m 0755 -p --' to ensure that directories
|
||||
# created by `make install' are always world readable, even if the
|
||||
# installer happens to have an overly restrictive umask (e.g. 077).
|
||||
# This was a mistake. There are at least two reasons why we must not
|
||||
# use `-m 0755':
|
||||
# - it causes special bits like SGID to be ignored,
|
||||
# - it may be too restrictive (some setups expect 775 directories).
|
||||
#
|
||||
# Do not use -m 0755 and let people choose whatever they expect by
|
||||
# setting umask.
|
||||
#
|
||||
# We cannot accept any implementation of `mkdir' that recognizes `-p'.
|
||||
# Some implementations (such as Solaris 8's) are not thread-safe: if a
|
||||
# parallel make tries to run `mkdir -p a/b' and `mkdir -p a/c'
|
||||
# concurrently, both version can detect that a/ is missing, but only
|
||||
# one can create it and the other will error out. Consequently we
|
||||
# restrict ourselves to GNU make (using the --version option ensures
|
||||
# this.)
|
||||
# Check for `mkdir -p'.
|
||||
AC_DEFUN([AM_PROG_MKDIR_P],
|
||||
[if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then
|
||||
# We used to keeping the `.' as first argument, in order to
|
||||
# allow $(mkdir_p) to be used without argument. As in
|
||||
# $(mkdir_p) $(somedir)
|
||||
# where $(somedir) is conditionally defined. However this is wrong
|
||||
# for two reasons:
|
||||
# 1. if the package is installed by a user who cannot write `.'
|
||||
# make install will fail,
|
||||
# 2. the above comment should most certainly read
|
||||
# $(mkdir_p) $(DESTDIR)$(somedir)
|
||||
# so it does not work when $(somedir) is undefined and
|
||||
# $(DESTDIR) is not.
|
||||
# To support the latter case, we have to write
|
||||
# test -z "$(somedir)" || $(mkdir_p) $(DESTDIR)$(somedir),
|
||||
# so the `.' trick is pointless.
|
||||
mkdir_p='mkdir -p --'
|
||||
else
|
||||
# On NextStep and OpenStep, the `mkdir' command does not
|
||||
# recognize any option. It will interpret all options as
|
||||
# directories to create, and then abort because `.' already
|
||||
# exists.
|
||||
for d in ./-p ./--version;
|
||||
do
|
||||
test -d $d && rmdir $d
|
||||
done
|
||||
# $(mkinstalldirs) is defined by Automake if mkinstalldirs exists.
|
||||
if test -f "$ac_aux_dir/mkinstalldirs"; then
|
||||
mkdir_p='$(mkinstalldirs)'
|
||||
else
|
||||
mkdir_p='$(install_sh) -d'
|
||||
fi
|
||||
fi
|
||||
AC_SUBST([mkdir_p])])
|
||||
[AC_PREREQ([2.60])dnl
|
||||
AC_REQUIRE([AC_PROG_MKDIR_P])dnl
|
||||
dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P,
|
||||
dnl while keeping a definition of mkdir_p for backward compatibility.
|
||||
dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile.
|
||||
dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of
|
||||
dnl Makefile.ins that do not define MKDIR_P, so we do our own
|
||||
dnl adjustment using top_builddir (which is defined more often than
|
||||
dnl MKDIR_P).
|
||||
AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl
|
||||
case $mkdir_p in
|
||||
[[\\/$]]* | ?:[[\\/]]*) ;;
|
||||
*/*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
|
||||
esac
|
||||
])
|
||||
|
||||
# Helper functions for option handling. -*- Autoconf -*-
|
||||
|
||||
@@ -907,9 +749,21 @@ dnl Don't test for $cross_compiling = yes, because it might be `maybe'.
|
||||
if test "$cross_compiling" != no; then
|
||||
AC_CHECK_TOOL([STRIP], [strip], :)
|
||||
fi
|
||||
INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s"
|
||||
INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
|
||||
AC_SUBST([INSTALL_STRIP_PROGRAM])])
|
||||
|
||||
# Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# _AM_SUBST_NOTMAKE(VARIABLE)
|
||||
# ---------------------------
|
||||
# Prevent Automake from outputing VARIABLE = @VARIABLE@ in Makefile.in.
|
||||
# This macro is traced by Automake.
|
||||
AC_DEFUN([_AM_SUBST_NOTMAKE])
|
||||
|
||||
# Check how to create a tarball. -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 2004, 2005 Free Software Foundation, Inc.
|
||||
|
||||
30
config.h.in
30
config.h.in
@@ -9,16 +9,10 @@
|
||||
/* Define to 1 to disable smart par-verification and restoration */
|
||||
#undef DISABLE_PARCHECK
|
||||
|
||||
/* Define to 1 to not use TLS/SSL */
|
||||
#undef DISABLE_TLS
|
||||
|
||||
/* Define to the name of macro which returns the name of function being
|
||||
compiled */
|
||||
#undef FUNCTION_MACRO_NAME
|
||||
|
||||
/* Define to 1 to create stacktrace on segmentation faults */
|
||||
#undef HAVE_BACKTRACE
|
||||
|
||||
/* Define to 1 if ctime_r takes 2 arguments */
|
||||
#undef HAVE_CTIME_R_2
|
||||
|
||||
@@ -28,15 +22,6 @@
|
||||
/* Define to 1 if you have the <curses.h> header file. */
|
||||
#undef HAVE_CURSES_H
|
||||
|
||||
/* Define to 1 if getaddrinfo is supported */
|
||||
#undef HAVE_GETADDRINFO
|
||||
|
||||
/* Define to 1 if gethostbyname_r is supported */
|
||||
#undef HAVE_GETHOSTBYNAME_R
|
||||
|
||||
/* Define to 1 if gethostbyname_r takes 3 arguments */
|
||||
#undef HAVE_GETHOSTBYNAME_R_3
|
||||
|
||||
/* Define to 1 if gethostbyname_r takes 5 arguments */
|
||||
#undef HAVE_GETHOSTBYNAME_R_5
|
||||
|
||||
@@ -49,9 +34,6 @@
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#undef HAVE_INTTYPES_H
|
||||
|
||||
/* Define to 1 to use GnuTLS library for TLS/SSL-support. */
|
||||
#undef HAVE_LIBGNUTLS
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#undef HAVE_MEMORY_H
|
||||
|
||||
@@ -61,12 +43,6 @@
|
||||
/* Define to 1 if you have the <ncurses/ncurses.h> header file. */
|
||||
#undef HAVE_NCURSES_NCURSES_H
|
||||
|
||||
/* Define to 1 to use OpenSSL library for TLS/SSL-support. */
|
||||
#undef HAVE_OPENSSL
|
||||
|
||||
/* Define to 1 if libpar2 supports cancelling (needs a special patch) */
|
||||
#undef HAVE_PAR2_CANCEL
|
||||
|
||||
/* Define to 1 if stat64 is supported */
|
||||
#undef HAVE_STAT64
|
||||
|
||||
@@ -82,9 +58,6 @@
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#undef HAVE_STRING_H
|
||||
|
||||
/* Define to 1 if you have the <sys/prctl.h> header file. */
|
||||
#undef HAVE_SYS_PRCTL_H
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#undef HAVE_SYS_STAT_H
|
||||
|
||||
@@ -115,9 +88,6 @@
|
||||
/* Define to the version of this package. */
|
||||
#undef PACKAGE_VERSION
|
||||
|
||||
/* Determine what socket length (socklen_t) data type is */
|
||||
#undef SOCKLEN_T
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#undef STDC_HEADERS
|
||||
|
||||
|
||||
487
configure.ac
487
configure.ac
@@ -2,34 +2,32 @@
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_PREREQ(2.59)
|
||||
AC_INIT(nzbget, 0.7.0, hugbug@users.sourceforge.net)
|
||||
AM_INIT_AUTOMAKE(nzbget, 0.7.0)
|
||||
AC_INIT(nzbget, 0.4.1, hugbug@users.sourceforge.net)
|
||||
AM_INIT_AUTOMAKE(nzbget, 0.4.1)
|
||||
AC_CONFIG_SRCDIR([nzbget.cpp])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
|
||||
|
||||
|
||||
dnl
|
||||
dnl Architecture check.
|
||||
dnl
|
||||
dnl Architecture check
|
||||
AC_CANONICAL_HOST
|
||||
case "$host" in
|
||||
*86-*-linux*)
|
||||
LIBPREF1="/usr"
|
||||
;;
|
||||
*-linux*)
|
||||
LIBPREF1="/usr"
|
||||
;;
|
||||
*-freebsd*)
|
||||
LIBPREF1="/usr/local"
|
||||
;;
|
||||
*-solaris*)
|
||||
LIBPREF1="/usr"
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
dnl
|
||||
dnl Set default library path, if not specified in environment variable "LIBPREF".
|
||||
dnl
|
||||
if test "$LIBPREF" = ""; then
|
||||
case "$host" in
|
||||
*-linux*)
|
||||
LIBPREF="/usr"
|
||||
;;
|
||||
*-freebsd*)
|
||||
LIBPREF="/usr/local"
|
||||
;;
|
||||
*-solaris*)
|
||||
LIBPREF="/usr"
|
||||
;;
|
||||
esac
|
||||
LIBPREF="$LIBPREF1"
|
||||
fi
|
||||
|
||||
|
||||
@@ -37,22 +35,30 @@ dnl
|
||||
dnl Check for programs.
|
||||
dnl
|
||||
AC_PROG_CXX
|
||||
AC_PROG_CC
|
||||
AC_PROG_GCC_TRADITIONAL
|
||||
AC_PROG_RANLIB
|
||||
AC_PROG_MAKE_SET
|
||||
AC_PATH_PROG(FALSE, false, /usr/bin/false)
|
||||
AC_PATH_PROG(TRUE, true, /usr/bin/true)
|
||||
AC_PATH_PROG(RM, rm, $FALSE)
|
||||
AC_PATH_PROG(LN, ln, $FALSE)
|
||||
AC_PATH_PROG(TAR, tar, $FALSE)
|
||||
AC_PATH_PROG(AR, ar, $FALSE)
|
||||
AC_PATH_PROG(MAKE, make, $FALSE)
|
||||
AC_PATH_PROG(CXXCPP, cpp, $FALSE)
|
||||
AC_PATH_PROG(MV, mv, $FALSE)
|
||||
AC_PATH_PROG(MKDIR, mkdir, $FALSE)
|
||||
AC_PATH_PROG(CP, cp, $FALSE)
|
||||
AC_PROG_INSTALL
|
||||
|
||||
|
||||
dnl
|
||||
dnl Do all tests with c++ compiler.
|
||||
dnl
|
||||
AC_LANG(C++)
|
||||
|
||||
|
||||
dnl
|
||||
dnl Checks for header files.
|
||||
dnl
|
||||
AC_CHECK_HEADERS(sys/prctl.h)
|
||||
|
||||
dnl AC_CHECK_HEADERS(stdarg.h time.h stdlib.h stdio.h unistd.h errno.h string.h sys/stat.h sys/time.h)
|
||||
dnl AC_CHECK_HEADERS(libgen.h pwd.h getopt.h dirent.h fcntl.h pthread.h semaphore.h)
|
||||
dnl AC_CHECK_HEADERS(sys/socket.h sys/types.h netinet/in.h arpa/inet.h netdb.h)
|
||||
|
||||
dnl
|
||||
dnl Check for libs
|
||||
@@ -60,6 +66,7 @@ dnl
|
||||
AC_SEARCH_LIBS([pthread_create], [pthread])
|
||||
AC_SEARCH_LIBS([socket], [socket])
|
||||
AC_SEARCH_LIBS([inet_addr], [nsl])
|
||||
AC_SEARCH_LIBS([gethostbyname_r], [nsl])
|
||||
AC_SEARCH_LIBS([hstrerror], [resolv])
|
||||
|
||||
|
||||
@@ -67,14 +74,16 @@ dnl
|
||||
dnl Getopt
|
||||
dnl
|
||||
AC_CHECK_FUNC(getopt_long,
|
||||
[AC_DEFINE([HAVE_GETOPT_LONG], 1, [Define to 1 if getopt_long is supported])],)
|
||||
[AC_DEFINE([HAVE_GETOPT_LONG], 1, [Define to 1 if getopt_long is supported])],
|
||||
[AC_LIBOBJ(getopt) AC_LIBOBJ(getopt1)])
|
||||
|
||||
|
||||
dnl
|
||||
dnl stat64
|
||||
dnl
|
||||
AC_CHECK_FUNC(stat64,
|
||||
[AC_DEFINE([HAVE_STAT64], 1, [Define to 1 if stat64 is supported])],)
|
||||
[AC_DEFINE([HAVE_STAT64], 1, [Define to 1 if stat64 is supported])],
|
||||
[AC_LIBOBJ(stat64)])
|
||||
|
||||
|
||||
dnl
|
||||
@@ -85,7 +94,6 @@ AC_TRY_COMPILE(
|
||||
[#include <time.h>],
|
||||
[ time_t clock; char buf[26]; ctime_r(&clock, buf, 26); ],
|
||||
AC_MSG_RESULT([[yes, and it takes 3 arguments]])
|
||||
FOUND="yes"
|
||||
AC_DEFINE([HAVE_CTIME_R_3], 1, [Define to 1 if ctime_r takes 3 arguments]),
|
||||
FOUND="no")
|
||||
if test "$FOUND" = "no"; then
|
||||
@@ -99,119 +107,82 @@ AC_TRY_COMPILE(
|
||||
fi
|
||||
if test "$FOUND" = "no"; then
|
||||
AC_MSG_RESULT([no])
|
||||
AC_MSG_ERROR("function ctime_r not found")
|
||||
AC_MSG_ERROR("function ctime_r not found.")
|
||||
fi
|
||||
|
||||
|
||||
dnl
|
||||
dnl check getaddrinfo
|
||||
dnl check gethostbyname_r
|
||||
dnl
|
||||
AC_CHECK_FUNC(getaddrinfo,
|
||||
FOUND="yes"
|
||||
[AC_DEFINE([HAVE_GETADDRINFO], 1, [Define to 1 if getaddrinfo is supported])]
|
||||
AC_SEARCH_LIBS([getaddrinfo], [nsl]),
|
||||
AC_MSG_CHECKING(for gethostbyname_r)
|
||||
AC_TRY_COMPILE(
|
||||
[#include <netdb.h>],
|
||||
[ char* szHost; struct hostent hinfobuf; char* strbuf; int h_errnop;
|
||||
struct hostent* hinfo = gethostbyname_r(szHost, &hinfobuf, strbuf, 1024, &h_errnop); ],
|
||||
AC_MSG_RESULT([[yes, and it takes 5 arguments]])
|
||||
FOUND="yes"
|
||||
AC_DEFINE([HAVE_GETHOSTBYNAME_R_5], 1, [Define to 1 if gethostbyname_r takes 5 arguments]),
|
||||
FOUND="no")
|
||||
|
||||
|
||||
dnl
|
||||
dnl check gethostbyname_r, if getaddrinfo is not available
|
||||
dnl
|
||||
if test "$FOUND" = "no"; then
|
||||
AC_MSG_CHECKING(for gethostbyname_r)
|
||||
|
||||
AC_TRY_COMPILE(
|
||||
[#include <netdb.h>],
|
||||
[ char* szHost; struct hostent hinfobuf; char* strbuf; int h_errnop;
|
||||
struct hostent* hinfo = gethostbyname_r(szHost, &hinfobuf, strbuf, 1024, &h_errnop); ],
|
||||
AC_MSG_RESULT([[yes, and it takes 5 arguments]])
|
||||
FOUND="yes"
|
||||
AC_DEFINE([HAVE_GETHOSTBYNAME_R_5], 1, [Define to 1 if gethostbyname_r takes 5 arguments]),
|
||||
FOUND="no")
|
||||
|
||||
if test "$FOUND" = "no"; then
|
||||
AC_TRY_COMPILE(
|
||||
[#include <netdb.h>],
|
||||
[ char* szHost; struct hostent* hinfo; struct hostent hinfobuf; char* strbuf; int h_errnop;
|
||||
int err = gethostbyname_r(szHost, &hinfobuf, strbuf, 1024, &hinfo, &h_errnop); ],
|
||||
AC_MSG_RESULT([[yes, and it takes 6 arguments]])
|
||||
FOUND="yes"
|
||||
AC_DEFINE([HAVE_GETHOSTBYNAME_R_6], 1, [Define to 1 if gethostbyname_r takes 6 arguments]),
|
||||
FOUND="no")
|
||||
fi
|
||||
|
||||
if test "$FOUND" = "no"; then
|
||||
AC_TRY_COMPILE(
|
||||
[#include <netdb.h>],
|
||||
[ char* szHost; struct hostent hinfo; struct hostent_data hinfobuf;
|
||||
int err = gethostbyname_r(szHost, &hinfo, &hinfobuf); ],
|
||||
AC_MSG_RESULT([[yes, and it takes 3 arguments]])
|
||||
FOUND="yes"
|
||||
AC_DEFINE([HAVE_GETHOSTBYNAME_R_3], 1, [Define to 1 if gethostbyname_r takes 3 arguments]),
|
||||
AC_MSG_RESULT([[no]])
|
||||
FOUND="no")
|
||||
fi
|
||||
|
||||
if test "$FOUND" = "yes"; then
|
||||
AC_DEFINE([HAVE_GETHOSTBYNAME_R], 1, [Define to 1 if gethostbyname_r is supported])
|
||||
AC_SEARCH_LIBS([gethostbyname_r], [nsl])
|
||||
fi
|
||||
AC_TRY_COMPILE(
|
||||
[#include <netdb.h>],
|
||||
[ char* szHost; struct hostent* hinfo; struct hostent hinfobuf; char* strbuf; int h_errnop;
|
||||
int err = gethostbyname_r(szHost, &hinfobuf, strbuf, 1024, &hinfo, &h_errnop); ],
|
||||
AC_MSG_RESULT([[yes, and it takes 6 arguments]])
|
||||
FOUND="yes"
|
||||
AC_DEFINE([HAVE_GETHOSTBYNAME_R_6], 1, [Define to 1 if gethostbyname_r takes 6 arguments]),
|
||||
FOUND="no")
|
||||
fi
|
||||
if test "$FOUND" = "no"; then
|
||||
AC_MSG_RESULT([no])
|
||||
AC_MSG_ERROR("function gethostbyname_r not found.")
|
||||
fi
|
||||
|
||||
|
||||
dnl
|
||||
dnl Determine what socket length (socklen_t) data type is
|
||||
dnl check for __FUNCTION__ or __func__ macro
|
||||
dnl
|
||||
AC_MSG_CHECKING([for type of socket length (socklen_t)])
|
||||
AC_TRY_COMPILE([
|
||||
#include <stddef.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>],[
|
||||
(void)getsockopt (1, 1, 1, NULL, (socklen_t*)NULL)],[
|
||||
AC_MSG_RESULT(socklen_t)
|
||||
SOCKLEN_T=socklen_t],[
|
||||
AC_TRY_COMPILE([
|
||||
#include <stddef.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>],[
|
||||
(void)getsockopt (1, 1, 1, NULL, (size_t*)NULL)],[
|
||||
AC_MSG_RESULT(size_t)
|
||||
SOCKLEN_T=size_t],[
|
||||
AC_TRY_COMPILE([
|
||||
#include <stddef.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>],[
|
||||
(void)getsockopt (1, 1, 1, NULL, (int*)NULL)],[
|
||||
AC_MSG_RESULT(int)
|
||||
SOCKLEN_T=int],[
|
||||
AC_MSG_WARN(could not determine)
|
||||
SOCKLEN_T=int])])])
|
||||
AC_DEFINE_UNQUOTED(SOCKLEN_T, $SOCKLEN_T, [Determine what socket length (socklen_t) data type is])
|
||||
AC_MSG_CHECKING(for __FUNCTION__ macro)
|
||||
AC_LANG_PUSH(C++)
|
||||
AC_TRY_COMPILE([#include <stdio.h>], [printf("%s\n", __FUNCTION__);],
|
||||
AC_MSG_RESULT([yes])
|
||||
AC_DEFINE([FUNCTION_MACRO_NAME],[__FUNCTION__],[Define to the name of macro which returns the name of funtion being compiled])
|
||||
HAVE_FUNCTION_MACRO=yes,
|
||||
AC_MSG_RESULT([no]))
|
||||
AC_LANG_POP(C++)
|
||||
if test "$HAVE_FUNCTION_MACRO" != "yes"; then
|
||||
AC_MSG_CHECKING(for __func__ macro)
|
||||
AC_LANG_PUSH(C++)
|
||||
AC_TRY_COMPILE([#include <stdio.h>], [printf("%s\n", __func__);],
|
||||
AC_MSG_RESULT([yes])
|
||||
AC_DEFINE([FUNCTION_MACRO_NAME],[__func__],[Define to the name of macro which returns the name of function being compiled])
|
||||
HAVE_FUNCTION_MACRO=yes,
|
||||
AC_MSG_RESULT([no]))
|
||||
AC_LANG_POP(C++)
|
||||
fi
|
||||
if test "$HAVE_FUNCTION_MACRO" != "yes"; then
|
||||
AC_DEFINE([FUNCTION_MACRO_NAME],[NULL],[Define to the name of macro which returns the name of function being compiled])
|
||||
fi
|
||||
|
||||
|
||||
dnl
|
||||
dnl checks for libxml2 includes and libraries.
|
||||
dnl
|
||||
dnl
|
||||
INCVAL="${LIBPREF}/include/libxml2"
|
||||
LIBVAL="${LIBPREF}/lib"
|
||||
AC_ARG_WITH(libxml2_includes,
|
||||
[AS_HELP_STRING([--with-libxml2-includes=DIR], [libxml2 include directory])],
|
||||
[CPPFLAGS="${CPPFLAGS} -I${withval}"]
|
||||
[CFLAGS="${CFLAGS} -I${withval}"]
|
||||
[INCVAL="yes"],
|
||||
[INCVAL="no"])
|
||||
AC_ARG_WITH(libxml2_libraries,
|
||||
[AS_HELP_STRING([--with-libxml2-libraries=DIR], [libxml2 library directory])],
|
||||
[LDFLAGS="${LDFLAGS} -L${withval}"]
|
||||
[LIBVAL="yes"],
|
||||
[LIBVAL="no"])
|
||||
if test "$INCVAL" = "no" -o "$LIBVAL" = "no"; then
|
||||
PKG_CHECK_MODULES(libxml2, libxml-2.0,
|
||||
[LDFLAGS="${LDFLAGS} $libxml2_LIBS"]
|
||||
[CPPFLAGS="${CPPFLAGS} $libxml2_CFLAGS"]
|
||||
[CFLAGS="${CFLAGS} $libxml2_CFLAGS"])
|
||||
fi
|
||||
[ --with-libxml2-includes=DIR libxml2 include directory],
|
||||
[INCVAL="$withval"])
|
||||
CPPFLAGS="${CPPFLAGS} -I${INCVAL}"
|
||||
CFLAGS="${CFLAGS} -I${INCVAL}"
|
||||
AC_CHECK_HEADER(libxml/tree.h,,
|
||||
AC_MSG_ERROR("libxml2 header files not found"))
|
||||
AC_MSG_ERROR("libxml2 header files were not found."))
|
||||
AC_ARG_WITH(libxml2_libraries,
|
||||
[ --with-libxml2-libraries=DIR libxml2 library directory],
|
||||
[LIBVAL="$withval"])
|
||||
LDFLAGS="${LDFLAGS} -L${LIBVAL}"
|
||||
AC_SEARCH_LIBS([xmlNewNode], [xml2], ,
|
||||
AC_MSG_ERROR("libxml2 library not found"))
|
||||
AC_MSG_ERROR("libxml2 library not found in $LIBVAL."))
|
||||
|
||||
|
||||
dnl
|
||||
@@ -219,20 +190,20 @@ dnl Use curses. Deafult: yes
|
||||
dnl
|
||||
AC_MSG_CHECKING(whether to use curses)
|
||||
AC_ARG_ENABLE(curses,
|
||||
[AS_HELP_STRING([--disable-curses], [do not use curses (removes dependency from curses-library)])],
|
||||
[USECURSES=$enableval],
|
||||
[USECURSES=yes] )
|
||||
[ --disable-curses do not use curses (removes dependency from curses-library and makes executable smaller)],
|
||||
[ USECURSES=$enableval ],
|
||||
[ USECURSES=yes] )
|
||||
AC_MSG_RESULT($USECURSES)
|
||||
if test "$USECURSES" = "yes"; then
|
||||
INCVAL="${LIBPREF}/include"
|
||||
LIBVAL="${LIBPREF}/lib"
|
||||
AC_ARG_WITH(libcurses_includes,
|
||||
[AS_HELP_STRING([--with-libcurses-includes=DIR], [libcurses include directory])],
|
||||
[ --with-libcurses-includes=DIR libcurses include directory],
|
||||
[INCVAL="$withval"])
|
||||
CPPFLAGS="${CPPFLAGS} -I${INCVAL}"
|
||||
CFLAGS="${CFLAGS} -I${INCVAL}"
|
||||
AC_ARG_WITH(libcurses_libraries,
|
||||
[AS_HELP_STRING([--with-libcurses-libraries=DIR], [libcurses library directory])],
|
||||
[ --with-libcurses-libraries=DIR libcurses library directory],
|
||||
[LIBVAL="$withval"])
|
||||
LDFLAGS="${LDFLAGS} -L${LIBVAL}"
|
||||
|
||||
@@ -253,7 +224,7 @@ if test "$USECURSES" = "yes"; then
|
||||
FOUND=no)
|
||||
fi
|
||||
if test "$FOUND" = "no"; then
|
||||
AC_MSG_ERROR([Couldn't find curses headers (ncurses.h or curses.h)])
|
||||
AC_MSG_ERROR([Couldn't find curses headers (ncurses.h or curses.h).])
|
||||
fi
|
||||
AC_SEARCH_LIBS([refresh], [ncurses curses],,
|
||||
AC_ERROR([Couldn't find curses library]))
|
||||
@@ -263,11 +234,11 @@ fi
|
||||
|
||||
|
||||
dnl
|
||||
dnl Use libpar2 for par-checking. Deafult: no
|
||||
dnl Use lib2par for par-checking. Deafult: no
|
||||
dnl
|
||||
AC_MSG_CHECKING(whether to include code for par-checking)
|
||||
AC_ARG_ENABLE(parcheck,
|
||||
[AS_HELP_STRING([--disable-parcheck], [do not include par-check/-repair-support (removes dependency from libpar2- and libsigc-libraries)])],
|
||||
[ --enable-parcheck include code for par-checking],
|
||||
[ ENABLEPARCHECK=$enableval ],
|
||||
[ ENABLEPARCHECK=yes] )
|
||||
AC_MSG_RESULT($ENABLEPARCHECK)
|
||||
@@ -276,26 +247,23 @@ if test "$ENABLEPARCHECK" = "yes"; then
|
||||
dnl
|
||||
dnl checks for libsigc++ includes and libraries (required for libpar2).
|
||||
dnl
|
||||
|
||||
INCVAL="${LIBPREF}/include/sigc++-2.0"
|
||||
LIBVAL="${LIBPREF}/lib"
|
||||
AC_ARG_WITH(libsigc_includes,
|
||||
[AS_HELP_STRING([--with-libsigc-includes=DIR], [libsigc++-2.0 include directory])],
|
||||
[CPPFLAGS="${CPPFLAGS} -I${withval}"]
|
||||
[INCVAL="yes"],
|
||||
[INCVAL="no"])
|
||||
AC_ARG_WITH(libsigc_libraries,
|
||||
[AS_HELP_STRING([--with-libsigc-libraries=DIR], [libsigc++-2.0 library directory])],
|
||||
[LDFLAGS="${LDFLAGS} -L${withval}"]
|
||||
[CPPFLAGS="${CPPFLAGS} -I${withval}/sigc++-2.0/include"]
|
||||
[LIBVAL="yes"],
|
||||
[LIBVAL="no"])
|
||||
if test "$INCVAL" = "no" -o "$LIBVAL" = "no"; then
|
||||
PKG_CHECK_MODULES(libsigc, sigc++-2.0,
|
||||
[LDFLAGS="${LDFLAGS} $libsigc_LIBS"]
|
||||
[CPPFLAGS="${CPPFLAGS} $libsigc_CFLAGS"])
|
||||
fi
|
||||
[ --with-libsigc-includes=DIR libsigc++-2.0 include directory],
|
||||
[INCVAL="$withval"])
|
||||
|
||||
AC_ARG_WITH(libsigc_libraries,
|
||||
[ --with-libsigc-libraries=DIR libsigc++-2.0 library directory],
|
||||
[LIBVAL="$withval"])
|
||||
|
||||
LDFLAGS="${LDFLAGS} -L${LIBVAL}"
|
||||
CPPFLAGS="${CPPFLAGS} -I${INCVAL} -I${LIBVAL}/sigc++-2.0/include"
|
||||
|
||||
AC_LANG_PUSH(C++)
|
||||
AC_CHECK_HEADER(sigc++/type_traits.h,,
|
||||
AC_MSG_ERROR("libsigc++-2.0 header files not found"))
|
||||
AC_MSG_ERROR("libsigc++-2.0 header files were not found in $INCVAL."))
|
||||
AC_LANG_POP(C++)
|
||||
|
||||
dnl
|
||||
dnl checks for libpar2 includes and libraries.
|
||||
@@ -303,197 +271,51 @@ if test "$ENABLEPARCHECK" = "yes"; then
|
||||
INCVAL="${LIBPREF}/include"
|
||||
LIBVAL="${LIBPREF}/lib"
|
||||
AC_ARG_WITH(libpar2_includes,
|
||||
[AS_HELP_STRING([--with-libpar2-includes=DIR], [libpar2 include directory])],
|
||||
[ --with-libpar2-includes=DIR libpar2 include directory],
|
||||
[INCVAL="$withval"])
|
||||
|
||||
CPPFLAGS="${CPPFLAGS} -I${INCVAL}"
|
||||
|
||||
AC_LANG_PUSH(C++)
|
||||
AC_CHECK_HEADER(libpar2/libpar2.h,,
|
||||
AC_MSG_ERROR("libpar2 header files not found"))
|
||||
AC_MSG_ERROR("libpar2 header files were not found in $INCVAL."))
|
||||
AC_LANG_POP(C++)
|
||||
|
||||
AC_ARG_WITH(libpar2_libraries,
|
||||
[AS_HELP_STRING([--with-libpar2-libraries=DIR], [libpar2 library directory])],
|
||||
[ --with-libpar2-libraries=DIR libpar2 library directory],
|
||||
[LIBVAL="$withval"])
|
||||
|
||||
LDFLAGS="${LDFLAGS} -L${LIBVAL}"
|
||||
|
||||
AC_SEARCH_LIBS([_ZN12Par2RepairerC1Ev], [par2], ,
|
||||
AC_MSG_ERROR("libpar2 library not found"))
|
||||
dnl Q: How to check for c++-class in library?
|
||||
LIBS="${LIBS} -lpar2"
|
||||
dnl AC_CHECK_LIB(par2, GenerateCRC32Table, , FOUND=no)
|
||||
dnl if test "$FOUND" = "no"; then
|
||||
dnl AC_MSG_ERROR("libpar2 library not found in $LIBVAL.")
|
||||
dnl fi
|
||||
|
||||
dnl
|
||||
dnl check if libpar2 library is linkable
|
||||
dnl
|
||||
AC_MSG_CHECKING(for libpar2 linking)
|
||||
AC_TRY_LINK(
|
||||
[#include <libpar2/par2cmdline.h>]
|
||||
[#include <libpar2/par2repairer.h>]
|
||||
[ class Repairer : public Par2Repairer { }; ],
|
||||
[ Repairer* p = new Repairer(); ],
|
||||
AC_MSG_RESULT([[yes]]),
|
||||
AC_MSG_RESULT([[no]])
|
||||
AC_MSG_ERROR("libpar2 library not found"))
|
||||
|
||||
dnl
|
||||
dnl check if libpar2 has support for cancelling
|
||||
dnl
|
||||
AC_MSG_CHECKING(whether libpar2 supports cancelling)
|
||||
AC_TRY_COMPILE(
|
||||
[#include <libpar2/par2cmdline.h>]
|
||||
[#include <libpar2/par2repairer.h>]
|
||||
[ class Repairer : public Par2Repairer { void test() { cancelled = true; } }; ],
|
||||
[],
|
||||
AC_MSG_RESULT([[yes]])
|
||||
AC_DEFINE([HAVE_PAR2_CANCEL], 1, [Define to 1 if libpar2 supports cancelling (needs a special patch)]),
|
||||
AC_MSG_RESULT([[no]]))
|
||||
else
|
||||
AC_DEFINE([DISABLE_PARCHECK],1,[Define to 1 to disable smart par-verification and restoration])
|
||||
fi
|
||||
|
||||
|
||||
dnl
|
||||
dnl Use TLS/SSL. Deafult: yes
|
||||
dnl
|
||||
AC_MSG_CHECKING(whether to use TLS/SSL)
|
||||
AC_ARG_ENABLE(tls,
|
||||
[AS_HELP_STRING([--disable-tls], [do not use TLS/SSL (removes dependency from TLS/SSL-libraries)])],
|
||||
[ USETLS=$enableval ],
|
||||
[ USETLS=yes] )
|
||||
AC_MSG_RESULT($USETLS)
|
||||
if test "$USETLS" = "yes"; then
|
||||
AC_ARG_WITH(tlslib,
|
||||
[AS_HELP_STRING([--with-tlslib=(GnuTLS, OpenSSL)], [TLS/SSL library to use])],
|
||||
[TLSLIB="$withval"])
|
||||
if test "$TLSLIB" != "GnuTLS" -a "$TLSLIB" != "OpenSSL" -a "$TLSLIB" != ""; then
|
||||
AC_MSG_ERROR([Invalid argument for option --with-tlslib])
|
||||
fi
|
||||
|
||||
if test "$TLSLIB" = "GnuTLS" -o "$TLSLIB" = ""; then
|
||||
INCVAL="${LIBPREF}/include"
|
||||
LIBVAL="${LIBPREF}/lib"
|
||||
AC_ARG_WITH(libgnutls_includes,
|
||||
[AS_HELP_STRING([--with-libgnutls-includes=DIR], [GnuTLS include directory])],
|
||||
[INCVAL="$withval"])
|
||||
CPPFLAGS="${CPPFLAGS} -I${INCVAL}"
|
||||
CFLAGS="${CFLAGS} -I${INCVAL}"
|
||||
AC_ARG_WITH(libgnutls_libraries,
|
||||
[AS_HELP_STRING([--with-libgnutls-libraries=DIR], [GnuTLS library directory])],
|
||||
[LIBVAL="$withval"])
|
||||
LDFLAGS="${LDFLAGS} -L${LIBVAL}"
|
||||
|
||||
AC_CHECK_HEADER(gnutls/gnutls.h,
|
||||
FOUND=yes
|
||||
TLSHEADERS=yes,
|
||||
FOUND=no)
|
||||
if test "$FOUND" = "no" -a "$TLSLIB" = "GnuTLS"; then
|
||||
AC_MSG_ERROR([Couldn't find GnuTLS headers (gnutls.h)])
|
||||
fi
|
||||
if test "$FOUND" = "yes"; then
|
||||
AC_SEARCH_LIBS([gnutls_global_init], [gnutls],
|
||||
AC_SEARCH_LIBS([gcry_control], [gnutls gcrypt],
|
||||
FOUND=yes,
|
||||
FOUND=no),
|
||||
FOUND=no)
|
||||
if test "$FOUND" = "no" -a "$TLSLIB" = "GnuTLS"; then
|
||||
AC_MSG_ERROR([Couldn't find GnuTLS library])
|
||||
fi
|
||||
if test "$FOUND" = "yes"; then
|
||||
TLSLIB="GnuTLS"
|
||||
AC_DEFINE([HAVE_LIBGNUTLS],1,[Define to 1 to use GnuTLS library for TLS/SSL-support.])
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$TLSLIB" = "OpenSSL" -o "$TLSLIB" = ""; then
|
||||
INCVAL="${LIBPREF}/include"
|
||||
LIBVAL="${LIBPREF}/lib"
|
||||
AC_ARG_WITH(openssl_includes,
|
||||
[AS_HELP_STRING([--with-openssl-includes=DIR], [OpenSSL include directory])],
|
||||
[INCVAL="$withval"])
|
||||
CPPFLAGS="${CPPFLAGS} -I${INCVAL}"
|
||||
CFLAGS="${CFLAGS} -I${INCVAL}"
|
||||
AC_ARG_WITH(openssl_libraries,
|
||||
[AS_HELP_STRING([--with-openssl-libraries=DIR], [OpenSSL library directory])],
|
||||
[LIBVAL="$withval"])
|
||||
LDFLAGS="${LDFLAGS} -L${LIBVAL}"
|
||||
|
||||
AC_CHECK_HEADER(openssl/ssl.h,
|
||||
FOUND=yes
|
||||
TLSHEADERS=yes,
|
||||
FOUND=no)
|
||||
if test "$FOUND" = "no" -a "$TLSLIB" = "OpenSSL"; then
|
||||
AC_MSG_ERROR([Couldn't find OpenSSL headers (ssl.h)])
|
||||
fi
|
||||
if test "$FOUND" = "yes"; then
|
||||
AC_SEARCH_LIBS([SSL_library_init], [ssl],
|
||||
FOUND=yes,
|
||||
FOUND=no)
|
||||
if test "$FOUND" = "no" -a "$TLSLIB" = "OpenSSL"; then
|
||||
AC_MSG_ERROR([Couldn't find OpenSSL library])
|
||||
fi
|
||||
if test "$FOUND" = "yes"; then
|
||||
TLSLIB="OpenSSL"
|
||||
AC_DEFINE([HAVE_OPENSSL],1,[Define to 1 to use OpenSSL library for TLS/SSL-support.])
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$TLSLIB" = ""; then
|
||||
if test "$TLSHEADERS" = ""; then
|
||||
AC_MSG_ERROR([Couldn't find neither GnuTLS nor OpenSSL headers (gnutls.h or ssl.h)])
|
||||
else
|
||||
AC_MSG_ERROR([Couldn't find neither GnuTLS nor OpenSSL library])
|
||||
fi
|
||||
fi
|
||||
else
|
||||
AC_DEFINE([DISABLE_TLS],1,[Define to 1 to not use TLS/SSL])
|
||||
fi
|
||||
|
||||
|
||||
dnl
|
||||
dnl Debugging. Default: no
|
||||
dnl
|
||||
AC_MSG_CHECKING(whether to include all debugging code)
|
||||
AC_ARG_ENABLE(debug,
|
||||
[AS_HELP_STRING([--enable-debug], [enable debugging])],
|
||||
[ --enable-debug enable debugging],
|
||||
[ ENABLEDEBUG=$enableval ],
|
||||
[ ENABLEDEBUG=no] )
|
||||
AC_MSG_RESULT($ENABLEDEBUG)
|
||||
|
||||
|
||||
if test "$ENABLEDEBUG" = "yes"; then
|
||||
|
||||
dnl
|
||||
dnl Begin of debugging code
|
||||
dnl
|
||||
|
||||
AC_DEFINE([DEBUG],1,Define to 1 to include debug-code)
|
||||
|
||||
|
||||
dnl
|
||||
dnl Set debug flags for gcc (if gcc is used)
|
||||
dnl
|
||||
if test "$CC" = "gcc"; then
|
||||
CXXFLAGS="-g -Wall"
|
||||
else
|
||||
CXXFLAGS=""
|
||||
fi
|
||||
|
||||
|
||||
dnl
|
||||
dnl check for __FUNCTION__ or __func__ macro
|
||||
dnl
|
||||
AC_MSG_CHECKING(for macro returning current function name)
|
||||
AC_TRY_COMPILE(
|
||||
[#include <stdio.h>], [printf("%s\n", __FUNCTION__);],
|
||||
AC_MSG_RESULT(__FUNCTION__)
|
||||
FUNCTION_MACRO_NAME=__FUNCTION__,
|
||||
AC_TRY_COMPILE([#include <stdio.h>], [printf("%s\n", __func__);],
|
||||
AC_MSG_RESULT(__func__)
|
||||
FUNCTION_MACRO_NAME=__func__,
|
||||
AC_MSG_RESULT(none)))
|
||||
if test "$FUNCTION_MACRO_NAME" != ""; then
|
||||
AC_DEFINE_UNQUOTED(FUNCTION_MACRO_NAME, $FUNCTION_MACRO_NAME, [Define to the name of macro which returns the name of function being compiled])
|
||||
AC_DEFINE([DEBUG],1,Define to 1 to include debug-code)
|
||||
if test "$CC" = "gcc"; then
|
||||
CXXFLAGS="-g -Wall"
|
||||
else
|
||||
CXXFLAGS=""
|
||||
fi
|
||||
fi
|
||||
AC_MSG_RESULT($ENABLEDEBUG)
|
||||
|
||||
|
||||
dnl
|
||||
@@ -510,41 +332,6 @@ AC_COMPILE_IFELSE([
|
||||
AC_MSG_RESULT([no]))
|
||||
|
||||
|
||||
dnl
|
||||
dnl Backtracing on segmentation faults
|
||||
dnl
|
||||
AC_MSG_CHECKING(for backtrace)
|
||||
AC_TRY_COMPILE(
|
||||
[#include <execinfo.h>]
|
||||
[#include <stdio.h>]
|
||||
[#include <stdlib.h>],
|
||||
[ void *array[100]; size_t size; char **strings; ]
|
||||
[ size = backtrace(array, 100); ]
|
||||
[ strings = backtrace_symbols(array, size); ],
|
||||
FOUND=yes
|
||||
AC_MSG_RESULT([[yes]])
|
||||
AC_DEFINE([HAVE_BACKTRACE], 1, [Define to 1 to create stacktrace on segmentation faults]),
|
||||
FOUND=no
|
||||
AC_MSG_RESULT([[no]]))
|
||||
|
||||
|
||||
dnl
|
||||
dnl "rdynamic" linker flag
|
||||
dnl
|
||||
AC_MSG_CHECKING(for rdynamic linker flag)
|
||||
old_LDFLAGS="$LDFLAGS"
|
||||
LDFLAGS="$LDFLAGS -rdynamic"
|
||||
AC_TRY_LINK([], [],
|
||||
AC_MSG_RESULT([[yes]]),
|
||||
AC_MSG_RESULT([[no]])
|
||||
[LDFLAGS="$old_LDFLAGS"])
|
||||
|
||||
dnl
|
||||
dnl End of debugging code
|
||||
dnl
|
||||
fi
|
||||
|
||||
|
||||
dnl Substitute flags.
|
||||
AC_SUBST(CFLAGS)
|
||||
AC_SUBST(CPPFLAGS)
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
diff -aud ../libpar2-0.2-original/par2repairer.cpp ../libpar2-0.2/par2repairer.cpp
|
||||
--- ../libpar2-0.2-original/par2repairer.cpp 2006-01-20 18:25:20.000000000 +0100
|
||||
+++ ../libpar2-0.2/par2repairer.cpp 2008-02-06 12:02:53.226050300 +0100
|
||||
@@ -78,6 +78,7 @@
|
||||
|
||||
delete mainpacket;
|
||||
delete creatorpacket;
|
||||
+ delete headers;
|
||||
}
|
||||
|
||||
|
||||
@@ -1261,7 +1262,7 @@
|
||||
DiskFile::SplitFilename(filename, path, name);
|
||||
|
||||
cout << "Target: \"" << name << "\" - missing." << endl;
|
||||
- sig_done.emit(name, 0, sourcefile->GetVerificationPacket()->BlockCount());
|
||||
+ sig_done.emit(name, 0, sourcefile->GetVerificationPacket() ? sourcefile->GetVerificationPacket()->BlockCount() : 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1804,7 +1805,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
- sig_done.emit(name,count,sourcefile->GetVerificationPacket()->BlockCount());
|
||||
+ sig_done.emit(name,count, sourcefile->GetVerificationPacket() ? sourcefile->GetVerificationPacket()->BlockCount() : 0);
|
||||
sig_progress.emit(1000.0);
|
||||
return true;
|
||||
}
|
||||
@@ -1,187 +0,0 @@
|
||||
diff -aud ../libpar2-0.2-original/par2repairer.cpp ../libpar2-0.2/par2repairer.cpp
|
||||
--- ../libpar2-0.2-original/par2repairer.cpp 2008-10-26 19:54:33.000000000 +0100
|
||||
+++ ../libpar2-0.2/par2repairer.cpp 2008-10-29 10:24:48.000000000 +0100
|
||||
@@ -52,6 +52,8 @@
|
||||
noiselevel = CommandLine::nlNormal;
|
||||
headers = new ParHeaders;
|
||||
alreadyloaded = false;
|
||||
+
|
||||
+ cancelled = false;
|
||||
}
|
||||
|
||||
Par2Repairer::~Par2Repairer(void)
|
||||
@@ -406,6 +408,10 @@
|
||||
progress = offset;
|
||||
sig_progress.emit(newfraction);
|
||||
|
||||
+ if (cancelled)
|
||||
+ {
|
||||
+ break;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -584,6 +590,11 @@
|
||||
delete diskfile;
|
||||
}
|
||||
|
||||
+ if (cancelled)
|
||||
+ {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -833,9 +844,17 @@
|
||||
for (list<string>::const_iterator s=files->begin(); s!=files->end(); ++s)
|
||||
{
|
||||
LoadPacketsFromFile(*s);
|
||||
+ if (cancelled)
|
||||
+ {
|
||||
+ break;
|
||||
+ }
|
||||
}
|
||||
|
||||
delete files;
|
||||
+ if (cancelled)
|
||||
+ {
|
||||
+ return false;
|
||||
+ }
|
||||
}
|
||||
|
||||
{
|
||||
@@ -846,9 +865,17 @@
|
||||
for (list<string>::const_iterator s=files->begin(); s!=files->end(); ++s)
|
||||
{
|
||||
LoadPacketsFromFile(*s);
|
||||
+ if (cancelled)
|
||||
+ {
|
||||
+ break;
|
||||
+ }
|
||||
}
|
||||
|
||||
delete files;
|
||||
+ if (cancelled)
|
||||
+ {
|
||||
+ return false;
|
||||
+ }
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -866,9 +893,18 @@
|
||||
string::npos != filename.find(".PAR2"))
|
||||
{
|
||||
LoadPacketsFromFile(filename);
|
||||
+ if (cancelled)
|
||||
+ {
|
||||
+ break;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
+ if (cancelled)
|
||||
+ {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1210,6 +1246,11 @@
|
||||
sf = sortedfiles.begin();
|
||||
while (sf != sortedfiles.end())
|
||||
{
|
||||
+ if (cancelled)
|
||||
+ {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
// Do we have a source file
|
||||
Par2RepairerSourceFile *sourcefile = *sf;
|
||||
|
||||
@@ -1562,6 +1603,10 @@
|
||||
cout << "Scanning: \"" << shortname << "\": " << newfraction/10 << '.' << newfraction%10 << "%\r" << flush;
|
||||
sig_progress.emit(newfraction);
|
||||
|
||||
+ if (cancelled)
|
||||
+ {
|
||||
+ break;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1651,6 +1696,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
+ if (cancelled)
|
||||
+ {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
// Get the Full and 16k hash values of the file
|
||||
filechecksummer.GetFileHashes(hashfull, hash16k);
|
||||
|
||||
@@ -2291,10 +2341,19 @@
|
||||
cout << "Repairing: " << newfraction/10 << '.' << newfraction%10 << "%\r" << flush;
|
||||
sig_progress.emit(newfraction);
|
||||
|
||||
+ if (cancelled)
|
||||
+ {
|
||||
+ break;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+ if (cancelled)
|
||||
+ {
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
++inputblock;
|
||||
++inputindex;
|
||||
}
|
||||
@@ -2348,9 +2407,18 @@
|
||||
cout << "Processing: " << newfraction/10 << '.' << newfraction%10 << "%\r" << flush;
|
||||
sig_progress.emit(newfraction);
|
||||
|
||||
+ if (cancelled)
|
||||
+ {
|
||||
+ break;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
+ if (cancelled)
|
||||
+ {
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
++copyblock;
|
||||
++inputblock;
|
||||
}
|
||||
@@ -2362,6 +2430,11 @@
|
||||
lastopenfile->Close();
|
||||
}
|
||||
|
||||
+ if (cancelled)
|
||||
+ {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
if (noiselevel > CommandLine::nlQuiet)
|
||||
cout << "Writing recovered data\r";
|
||||
|
||||
diff -aud ../libpar2-0.2-original/par2repairer.h ../libpar2-0.2/par2repairer.h
|
||||
--- ../libpar2-0.2-original/par2repairer.h 2006-01-20 00:38:27.000000000 +0100
|
||||
+++ ../libpar2-0.2/par2repairer.h 2008-10-26 19:01:08.000000000 +0100
|
||||
@@ -183,6 +183,7 @@
|
||||
u64 totaldata; // Total amount of data to be processed.
|
||||
u64 totalsize; // Total data size
|
||||
|
||||
+ bool cancelled; // repair cancelled
|
||||
};
|
||||
|
||||
#endif // __PAR2REPAIRER_H__
|
||||
@@ -1,35 +0,0 @@
|
||||
@echo off
|
||||
|
||||
rem
|
||||
rem Batch file to start nzbget shell
|
||||
rem
|
||||
rem Copyright (C) 2009 orbisvicis <orbisvicis@users.sourceforge.net>
|
||||
rem Copyright (C) 2009 Andrei Prygounkov <hugbug@users.sourceforge.net>
|
||||
rem
|
||||
rem This program is free software; you can redistribute it and/or modify
|
||||
rem it under the terms of the GNU General Public License as published by
|
||||
rem the Free Software Foundation; either version 2 of the License, or
|
||||
rem (at your option) any later version.
|
||||
rem
|
||||
rem This program is distributed in the hope that it will be useful,
|
||||
rem but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
rem MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
rem GNU General Public License for more details.
|
||||
rem
|
||||
rem You should have received a copy of the GNU General Public License
|
||||
rem along with this program; if not, write to the Free Software
|
||||
rem Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
rem
|
||||
|
||||
rem ####################### Usage instructions #######################
|
||||
rem
|
||||
rem After starting the batch file you can use all nzbget commands
|
||||
rem (like nzbget -s, nzbget -L, etc) without typing the full
|
||||
rem path to nzbget executable.
|
||||
rem
|
||||
rem ####################### End of Usage instructions #######################
|
||||
|
||||
|
||||
rem expression "%~dp0" means the location of an executing batch file
|
||||
set PATH=%PATH%;%~dp0
|
||||
cmd /U /K "cd %USERPROFILE% & nzbget"
|
||||
File diff suppressed because it is too large
Load Diff
322
nzbget.cpp
322
nzbget.cpp
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007-2010 Andrei Prygounkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
|
||||
* Copyright (C) 2007 Andrei Prygounkov <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
|
||||
@@ -40,22 +40,15 @@
|
||||
#include <unistd.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
#include <sys/resource.h>
|
||||
#ifdef HAVE_SYS_PRCTL_H
|
||||
#include <sys/prctl.h>
|
||||
#endif
|
||||
#include <signal.h>
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#ifndef DISABLE_PARCHECK
|
||||
#include <iostream>
|
||||
#endif
|
||||
#ifdef HAVE_BACKTRACE
|
||||
#include <execinfo.h>
|
||||
#endif
|
||||
|
||||
#include "nzbget.h"
|
||||
#include "ServerPool.h"
|
||||
@@ -72,8 +65,6 @@
|
||||
#include "DiskState.h"
|
||||
#include "PrePostProcessor.h"
|
||||
#include "ParChecker.h"
|
||||
#include "Scheduler.h"
|
||||
#include "Util.h"
|
||||
#ifdef WIN32
|
||||
#include "NTService.h"
|
||||
#endif
|
||||
@@ -85,13 +76,6 @@ void ProcessClientRequest();
|
||||
#ifndef WIN32
|
||||
void InstallSignalHandlers();
|
||||
void Daemonize();
|
||||
void PrintBacktrace();
|
||||
#ifdef HAVE_SYS_PRCTL_H
|
||||
void EnableDumpCore();
|
||||
#endif
|
||||
#ifdef DEBUG
|
||||
void MakeSegFault();
|
||||
#endif
|
||||
#endif
|
||||
#ifndef DISABLE_PARCHECK
|
||||
void DisableCout();
|
||||
@@ -103,17 +87,15 @@ ServerPool* g_pServerPool = NULL;
|
||||
QueueCoordinator* g_pQueueCoordinator = NULL;
|
||||
RemoteServer* g_pRemoteServer = NULL;
|
||||
DownloadSpeedMeter* g_pDownloadSpeedMeter = NULL;
|
||||
DownloadQueueHolder* g_pDownloadQueueHolder = NULL;
|
||||
Log* g_pLog = NULL;
|
||||
PrePostProcessor* g_pPrePostProcessor = NULL;
|
||||
DiskState* g_pDiskState = NULL;
|
||||
Scheduler* g_pScheduler = NULL;
|
||||
char* (*szEnvironmentVariables)[] = NULL;
|
||||
|
||||
|
||||
/*
|
||||
* Main loop
|
||||
*/
|
||||
int main(int argc, char *argv[], char *argp[])
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
#ifdef WIN32
|
||||
#ifdef _DEBUG
|
||||
@@ -127,9 +109,8 @@ int main(int argc, char *argv[], char *argp[])
|
||||
#endif
|
||||
#endif
|
||||
|
||||
Util::InitVersionRevision();
|
||||
|
||||
#ifdef WIN32
|
||||
_set_fmode(_O_BINARY);
|
||||
InstallUninstallServiceCheck(argc, argv);
|
||||
#endif
|
||||
|
||||
@@ -137,17 +118,11 @@ int main(int argc, char *argv[], char *argp[])
|
||||
DisableCout();
|
||||
#endif
|
||||
|
||||
// Init options & get the name of the .nzb file
|
||||
g_pLog = new Log();
|
||||
|
||||
debug("nzbget %s", Util::VersionRevision());
|
||||
|
||||
g_pServerPool = new ServerPool();
|
||||
g_pScheduler = new Scheduler();
|
||||
Thread::Init();
|
||||
|
||||
debug("Reading options");
|
||||
debug("Options parsing");
|
||||
g_pOptions = new Options(argc, argv);
|
||||
szEnvironmentVariables = (char*(*)[])argp;
|
||||
|
||||
#ifndef WIN32
|
||||
if (g_pOptions->GetUMask() < 01000)
|
||||
@@ -159,53 +134,30 @@ int main(int argc, char *argv[], char *argp[])
|
||||
|
||||
if (g_pOptions->GetServerMode() && g_pOptions->GetCreateLog() && g_pOptions->GetResetLog())
|
||||
{
|
||||
debug("Deleting old log-file");
|
||||
debug("deleting old log-file");
|
||||
g_pLog->ResetLog();
|
||||
}
|
||||
|
||||
g_pLog->InitOptions();
|
||||
|
||||
if (g_pOptions->GetDaemonMode())
|
||||
{
|
||||
#ifdef WIN32
|
||||
info("nzbget %s service-mode", Util::VersionRevision());
|
||||
info("nzbget service-mode");
|
||||
StartService(Run);
|
||||
return 0;
|
||||
#else
|
||||
Daemonize();
|
||||
info("nzbget %s daemon-mode", Util::VersionRevision());
|
||||
info("nzbget daemon-mode");
|
||||
#endif
|
||||
}
|
||||
else if (g_pOptions->GetServerMode())
|
||||
{
|
||||
info("nzbget %s server-mode", Util::VersionRevision());
|
||||
info("nzbget server-mode");
|
||||
}
|
||||
else if (g_pOptions->GetRemoteClientMode())
|
||||
{
|
||||
info("nzbget %s remote-mode", Util::VersionRevision());
|
||||
info("nzbget remote-mode");
|
||||
}
|
||||
|
||||
if (!g_pOptions->GetRemoteClientMode())
|
||||
{
|
||||
g_pServerPool->InitConnections();
|
||||
#ifdef DEBUG
|
||||
g_pServerPool->LogDebugInfo();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
if (g_pOptions->GetDaemonMode())
|
||||
{
|
||||
StartService(Run);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#ifdef HAVE_SYS_PRCTL_H
|
||||
if (g_pOptions->GetDumpCore())
|
||||
{
|
||||
EnableDumpCore();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
Run();
|
||||
|
||||
#ifdef WIN32
|
||||
@@ -221,16 +173,10 @@ void Run()
|
||||
{
|
||||
#ifndef WIN32
|
||||
InstallSignalHandlers();
|
||||
#ifdef DEBUG
|
||||
if (g_pOptions->GetTestBacktrace())
|
||||
{
|
||||
MakeSegFault();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
Connection::Init(g_pOptions->GetTLS() && !g_pOptions->GetRemoteClientMode() &&
|
||||
(g_pOptions->GetClientOperation() == Options::opClientNoOperation));
|
||||
|
||||
Thread::Init();
|
||||
Connection::Init();
|
||||
|
||||
// client request
|
||||
if (g_pOptions->GetClientOperation() != Options::opClientNoOperation)
|
||||
@@ -245,7 +191,6 @@ void Run()
|
||||
{
|
||||
g_pQueueCoordinator = new QueueCoordinator();
|
||||
g_pDownloadSpeedMeter = g_pQueueCoordinator;
|
||||
g_pDownloadQueueHolder = g_pQueueCoordinator;
|
||||
}
|
||||
|
||||
// Setup the network-server
|
||||
@@ -290,16 +235,10 @@ void Run()
|
||||
if (!g_pOptions->GetRemoteClientMode())
|
||||
{
|
||||
// Standalone-mode
|
||||
if (!g_pOptions->GetServerMode())
|
||||
if (!g_pOptions->GetServerMode() && !g_pQueueCoordinator->AddFileToQueue(g_pOptions->GetArgFilename()))
|
||||
{
|
||||
NZBFile* pNZBFile = NZBFile::CreateFromFile(g_pOptions->GetArgFilename(), g_pOptions->GetCategory() ? g_pOptions->GetCategory() : "");
|
||||
if (!pNZBFile)
|
||||
{
|
||||
abort("FATAL ERROR: Parsing NZB-document %s failed\n\n", g_pOptions->GetArgFilename() ? g_pOptions->GetArgFilename() : "N/A");
|
||||
return;
|
||||
}
|
||||
g_pQueueCoordinator->AddNZBFileToQueue(pNZBFile, false);
|
||||
delete pNZBFile;
|
||||
abort("FATAL ERROR: Parsing NZB-document %s failed!!\n\n", g_pOptions->GetArgFilename() ? g_pOptions->GetArgFilename() : "N/A");
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_pOptions->GetSaveQueue() && g_pOptions->GetServerMode())
|
||||
@@ -374,99 +313,54 @@ void ProcessClientRequest()
|
||||
{
|
||||
RemoteClient* Client = new RemoteClient();
|
||||
|
||||
switch (g_pOptions->GetClientOperation())
|
||||
if (g_pOptions->GetClientOperation() == Options::opClientRequestList)
|
||||
{
|
||||
case Options::opClientRequestListFiles:
|
||||
Client->RequestServerList(true, false);
|
||||
break;
|
||||
|
||||
case Options::opClientRequestListGroups:
|
||||
Client->RequestServerList(false, true);
|
||||
break;
|
||||
|
||||
case Options::opClientRequestListStatus:
|
||||
Client->RequestServerList(false, false);
|
||||
break;
|
||||
|
||||
case Options::opClientRequestDownloadPause:
|
||||
Client->RequestServerPauseUnpause(true, eRemotePauseUnpauseActionDownload);
|
||||
break;
|
||||
|
||||
case Options::opClientRequestDownloadUnpause:
|
||||
Client->RequestServerPauseUnpause(false, eRemotePauseUnpauseActionDownload);
|
||||
break;
|
||||
|
||||
case Options::opClientRequestDownload2Pause:
|
||||
Client->RequestServerPauseUnpause(true, eRemotePauseUnpauseActionDownload2);
|
||||
break;
|
||||
|
||||
case Options::opClientRequestDownload2Unpause:
|
||||
Client->RequestServerPauseUnpause(false, eRemotePauseUnpauseActionDownload2);
|
||||
break;
|
||||
|
||||
case Options::opClientRequestSetRate:
|
||||
Client->RequestServerSetDownloadRate(g_pOptions->GetSetRate());
|
||||
break;
|
||||
|
||||
case Options::opClientRequestDumpDebug:
|
||||
Client->RequestServerDumpDebug();
|
||||
break;
|
||||
|
||||
case Options::opClientRequestEditQueue:
|
||||
Client->RequestServerEditQueue((eRemoteEditAction)g_pOptions->GetEditQueueAction(), g_pOptions->GetEditQueueOffset(),
|
||||
g_pOptions->GetEditQueueText(), g_pOptions->GetEditQueueIDList(), g_pOptions->GetEditQueueIDCount(), true);
|
||||
break;
|
||||
|
||||
case Options::opClientRequestLog:
|
||||
Client->RequestServerLog(g_pOptions->GetLogLines());
|
||||
break;
|
||||
|
||||
case Options::opClientRequestShutdown:
|
||||
Client->RequestServerShutdown();
|
||||
break;
|
||||
|
||||
case Options::opClientRequestDownload:
|
||||
Client->RequestServerDownload(g_pOptions->GetArgFilename(), g_pOptions->GetCategory(), g_pOptions->GetAddTop());
|
||||
break;
|
||||
|
||||
case Options::opClientRequestVersion:
|
||||
Client->RequestServerVersion();
|
||||
break;
|
||||
|
||||
case Options::opClientRequestPostQueue:
|
||||
Client->RequestPostQueue();
|
||||
break;
|
||||
|
||||
case Options::opClientRequestWriteLog:
|
||||
Client->RequestWriteLog(g_pOptions->GetWriteLogKind(), g_pOptions->GetLastArg());
|
||||
break;
|
||||
|
||||
case Options::opClientRequestScan:
|
||||
Client->RequestScan();
|
||||
break;
|
||||
|
||||
case Options::opClientRequestPostPause:
|
||||
Client->RequestServerPauseUnpause(true, eRemotePauseUnpauseActionPostProcess);
|
||||
break;
|
||||
|
||||
case Options::opClientRequestPostUnpause:
|
||||
Client->RequestServerPauseUnpause(false, eRemotePauseUnpauseActionPostProcess);
|
||||
break;
|
||||
|
||||
case Options::opClientRequestScanPause:
|
||||
Client->RequestServerPauseUnpause(true, eRemotePauseUnpauseActionScan);
|
||||
break;
|
||||
|
||||
case Options::opClientRequestScanUnpause:
|
||||
Client->RequestServerPauseUnpause(false, eRemotePauseUnpauseActionScan);
|
||||
break;
|
||||
|
||||
case Options::opClientRequestHistory:
|
||||
Client->RequestHistory();
|
||||
break;
|
||||
|
||||
case Options::opClientNoOperation:
|
||||
break;
|
||||
Client->RequestServerList();
|
||||
}
|
||||
else if (g_pOptions->GetClientOperation() == Options::opClientRequestPause)
|
||||
{
|
||||
Client->RequestServerPauseUnpause(true);
|
||||
}
|
||||
else if (g_pOptions->GetClientOperation() == Options::opClientRequestUnpause)
|
||||
{
|
||||
Client->RequestServerPauseUnpause(false);
|
||||
}
|
||||
else if (g_pOptions->GetClientOperation() == Options::opClientRequestSetRate)
|
||||
{
|
||||
Client->RequestServerSetDownloadRate(g_pOptions->GetSetRate());
|
||||
}
|
||||
else if (g_pOptions->GetClientOperation() == Options::opClientRequestDumpDebug)
|
||||
{
|
||||
Client->RequestServerDumpDebug();
|
||||
}
|
||||
else if (g_pOptions->GetClientOperation() == Options::opClientRequestEditQueue)
|
||||
{
|
||||
Client->RequestServerEditQueue(g_pOptions->GetEditQueueAction(), g_pOptions->GetEditQueueOffset(),
|
||||
g_pOptions->GetEditQueueIDList(), g_pOptions->GetEditQueueIDCount(), true);
|
||||
}
|
||||
else if (g_pOptions->GetClientOperation() == Options::opClientRequestLog)
|
||||
{
|
||||
Client->RequestServerLog(g_pOptions->GetLogLines());
|
||||
}
|
||||
else if (g_pOptions->GetClientOperation() == Options::opClientRequestShutdown)
|
||||
{
|
||||
Client->RequestServerShutdown();
|
||||
}
|
||||
else if (g_pOptions->GetClientOperation() == Options::opClientRequestDownload)
|
||||
{
|
||||
Client->RequestServerDownload(g_pOptions->GetArgFilename(), g_pOptions->GetAddTop());
|
||||
}
|
||||
else if (g_pOptions->GetClientOperation() == Options::opClientRequestVersion)
|
||||
{
|
||||
Client->RequestServerVersion();
|
||||
}
|
||||
else if (g_pOptions->GetClientOperation() == Options::opClientRequestPostQueue)
|
||||
{
|
||||
Client->RequestPostQueue();
|
||||
}
|
||||
else if (g_pOptions->GetClientOperation() == Options::opClientRequestWriteLog)
|
||||
{
|
||||
Client->RequestWriteLog(g_pOptions->GetWriteLogKind(), g_pOptions->GetLastArg());
|
||||
}
|
||||
|
||||
delete Client;
|
||||
@@ -517,18 +411,18 @@ void SignalProc(int iSignal)
|
||||
ExitProc();
|
||||
break;
|
||||
|
||||
case SIGCHLD:
|
||||
// ignoring
|
||||
break;
|
||||
|
||||
#ifdef DEBUG
|
||||
case SIGPIPE:
|
||||
// ignoring
|
||||
break;
|
||||
|
||||
case SIGCHLD:
|
||||
// ignoring
|
||||
break;
|
||||
|
||||
case SIGSEGV:
|
||||
signal(SIGSEGV, SIG_DFL); // Reset the signal handler
|
||||
PrintBacktrace();
|
||||
debug("SIGSEGV received");
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -546,7 +440,6 @@ void InstallSignalHandlers()
|
||||
{
|
||||
signal(SIGINT, SignalProc);
|
||||
signal(SIGTERM, SignalProc);
|
||||
signal(SIGCHLD, SignalProc);
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
#ifdef DEBUG
|
||||
SignalProcList.clear();
|
||||
@@ -557,62 +450,6 @@ void InstallSignalHandlers()
|
||||
signal(SIGWINCH, SIG_DFL);
|
||||
#endif
|
||||
}
|
||||
|
||||
void PrintBacktrace()
|
||||
{
|
||||
#ifdef HAVE_BACKTRACE
|
||||
printf("Segmentation fault, tracing...\n");
|
||||
|
||||
void *array[100];
|
||||
size_t size;
|
||||
char **strings;
|
||||
size_t i;
|
||||
|
||||
size = backtrace(array, 100);
|
||||
strings = backtrace_symbols(array, size);
|
||||
|
||||
// first trace to screen
|
||||
printf("Obtained %zd stack frames\n", size);
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
printf("%s\n", strings[i]);
|
||||
}
|
||||
|
||||
// then trace to log
|
||||
error("Segmentation fault, tracing...");
|
||||
error("Obtained %zd stack frames", size);
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
error("%s", strings[i]);
|
||||
}
|
||||
|
||||
free(strings);
|
||||
#else
|
||||
error("Segmentation fault");
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void MakeSegFault()
|
||||
{
|
||||
char* N = NULL;
|
||||
strcpy(N, "");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_PRCTL_H
|
||||
/**
|
||||
* activates the creation of core-files
|
||||
*/
|
||||
void EnableDumpCore()
|
||||
{
|
||||
rlimit rlim;
|
||||
rlim.rlim_cur= RLIM_INFINITY;
|
||||
rlim.rlim_max= RLIM_INFINITY;
|
||||
setrlimit(RLIMIT_CORE, &rlim);
|
||||
prctl(PR_SET_DUMPABLE, 1);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void Cleanup()
|
||||
@@ -664,7 +501,6 @@ void Cleanup()
|
||||
{
|
||||
if (g_pOptions->GetDaemonMode())
|
||||
{
|
||||
info("Deleting lock file");
|
||||
remove(g_pOptions->GetLockFile());
|
||||
}
|
||||
delete g_pOptions;
|
||||
@@ -680,17 +516,8 @@ void Cleanup()
|
||||
}
|
||||
debug("ServerPool deleted");
|
||||
|
||||
debug("Deleting Scheduler");
|
||||
if (g_pScheduler)
|
||||
{
|
||||
delete g_pScheduler;
|
||||
g_pScheduler = NULL;
|
||||
}
|
||||
debug("Scheduler deleted");
|
||||
|
||||
Connection::Final();
|
||||
|
||||
Thread::Final();
|
||||
Connection::Final();
|
||||
|
||||
debug("Global objects cleaned up");
|
||||
|
||||
@@ -725,7 +552,6 @@ void Daemonize()
|
||||
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. */
|
||||
|
||||
24
nzbget.h
24
nzbget.h
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2007-2009 Andrei Prygounkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2007 Andrei Prygounkov <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
|
||||
@@ -36,46 +36,40 @@
|
||||
#endif
|
||||
#define fdopen _fdopen
|
||||
#define ctime_r(timep, buf, bufsize) ctime_s(buf, bufsize, timep)
|
||||
#define localtime_r(time, tm) localtime_s(tm, time)
|
||||
#define int32_t __int32
|
||||
#define mkdir(dir, flags) _mkdir(dir)
|
||||
#define rmdir _rmdir
|
||||
#define strcasecmp(a, b) _stricmp(a, b)
|
||||
#define strncasecmp(a, b, c) _strnicmp(a, b, c)
|
||||
#define ssize_t SSIZE_T
|
||||
|
||||
#pragma warning(disable:4800) // 'type' : forcing value to bool 'true' or 'false' (performance warning)
|
||||
#pragma warning(disable:4267) // 'var' : conversion from 'size_t' to 'type', possible loss of data
|
||||
|
||||
#define __S_ISTYPE(mode, mask) (((mode) & _S_IFMT) == (mask))
|
||||
#define S_ISDIR(mode) __S_ISTYPE((mode), _S_IFDIR)
|
||||
#define S_ISREG(mode) __S_ISTYPE((mode), _S_IFREG)
|
||||
#define S_DIRMODE NULL
|
||||
|
||||
#define usleep(usec) Sleep((usec) / 1000)
|
||||
#define gettimeofday(tm, ignore) _ftime(tm)
|
||||
#define _timeval _timeb
|
||||
#define socklen_t int
|
||||
#define SHUT_RDWR 0x02
|
||||
#define PATH_SEPARATOR '\\'
|
||||
#define ALT_PATH_SEPARATOR '/'
|
||||
#define LINE_ENDING "\r\n"
|
||||
#define pid_t int
|
||||
|
||||
#pragma warning(disable:4800) // 'type' : forcing value to bool 'true' or 'false' (performance warning)
|
||||
#pragma warning(disable:4267) // 'var' : conversion from 'size_t' to 'type', possible loss of data
|
||||
|
||||
#else
|
||||
|
||||
// POSIX
|
||||
|
||||
#define _timeval timeval
|
||||
#define closesocket(sock) close(sock)
|
||||
#define SOCKET int
|
||||
#define INVALID_SOCKET (-1)
|
||||
#define PATH_SEPARATOR '/'
|
||||
#define ALT_PATH_SEPARATOR '\\'
|
||||
#define MAX_PATH 1024
|
||||
#define S_DIRMODE (S_IRWXU | S_IRWXG | S_IRWXO)
|
||||
#define LINE_ENDING "\n"
|
||||
#define S_DIRMODE (S_IRWXU | S_IRWXG | S_IRWXO)
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef SHUT_RDWR
|
||||
#define SHUT_RDWR 2
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -6,14 +6,11 @@ EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release (no TLS)|Win32 = Release (no TLS)|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{41BFB691-0127-4391-9629-F1BA6740DDFE}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{41BFB691-0127-4391-9629-F1BA6740DDFE}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{41BFB691-0127-4391-9629-F1BA6740DDFE}.Release (no TLS)|Win32.ActiveCfg = Release (no TLS)|Win32
|
||||
{41BFB691-0127-4391-9629-F1BA6740DDFE}.Release (no TLS)|Win32.Build.0 = Release (no TLS)|Win32
|
||||
{41BFB691-0127-4391-9629-F1BA6740DDFE}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{41BFB691-0127-4391-9629-F1BA6740DDFE}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
|
||||
112
nzbget.vcproj
112
nzbget.vcproj
@@ -58,7 +58,7 @@
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="WS2_32.lib ole32.lib OleAut32.Lib comsuppwd.lib Advapi32.lib sigc-2.0d.lib par2d.lib libgnutls-26.lib libgcrypt-11.lib $(NOINHERIT)"
|
||||
AdditionalDependencies="WS2_32.Lib ole32.lib OleAut32.Lib comsuppwd.lib Advapi32.lib sigc-2.0d.lib par2d.lib"
|
||||
LinkIncremental="2"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
@@ -113,7 +113,6 @@
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;"
|
||||
ExceptionHandling="1"
|
||||
RuntimeLibrary="0"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
@@ -131,82 +130,7 @@
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="WS2_32.lib ole32.lib OleAut32.Lib comsuppwd.lib Advapi32.lib sigc-2.0.lib par2.lib libgnutls-26.lib libgcrypt-11.lib $(NOINHERIT)"
|
||||
LinkIncremental="0"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release (no TLS)|Win32"
|
||||
OutputDirectory="..\bin"
|
||||
IntermediateDirectory="..\bin\Release (no TLS)"
|
||||
ConfigurationType="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;DISABLE_TLS"
|
||||
ExceptionHandling="1"
|
||||
RuntimeLibrary="0"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="WS2_32.lib ole32.lib OleAut32.Lib comsuppwd.lib Advapi32.lib sigc-2.0.lib par2.lib $(NOINHERIT)"
|
||||
AdditionalDependencies="WS2_32.Lib ole32.lib OleAut32.Lib comsuppwd.lib Advapi32.lib sigc-2.0.lib par2.lib"
|
||||
LinkIncremental="0"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
@@ -407,6 +331,14 @@
|
||||
RelativePath=".\ParChecker.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\PostInfo.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\PostInfo.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\PrePostProcessor.cpp"
|
||||
>
|
||||
@@ -447,22 +379,6 @@
|
||||
RelativePath=".\RemoteServer.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Scanner.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Scanner.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Scheduler.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Scheduler.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\ScriptController.cpp"
|
||||
>
|
||||
@@ -487,14 +403,6 @@
|
||||
RelativePath=".\Thread.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\TLS.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\TLS.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Util.cpp"
|
||||
>
|
||||
|
||||
79
nzbgetd
79
nzbgetd
@@ -1,79 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Script used to start and stop the nzbget usenet service
|
||||
#
|
||||
# Copyright (C) 2009 orbisvicis <orbisvicis@users.sourceforge.net>
|
||||
# Copyright (C) 2009 Andrei Prygounkov <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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
#
|
||||
#
|
||||
|
||||
# Location of the nzbget executable
|
||||
export NZBGET_BINARY="/usr/local/bin/nzbget"
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
# start/stop section
|
||||
|
||||
execCommand() {
|
||||
"$NZBGET_BINARY" $@
|
||||
sleep 1 # allows prompt to return
|
||||
}
|
||||
|
||||
start() {
|
||||
execCommand "--daemon"
|
||||
}
|
||||
|
||||
stop() {
|
||||
execCommand "--quit"
|
||||
}
|
||||
|
||||
status() {
|
||||
execCommand "--log 5"
|
||||
}
|
||||
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
start
|
||||
;;
|
||||
stop)
|
||||
stop
|
||||
;;
|
||||
restart)
|
||||
stop
|
||||
sleep 10 # since stop is backgrounded
|
||||
start
|
||||
;;
|
||||
pstatus)
|
||||
retval=$(pgrep -l -f "$NZBGET_BINARY --daemon" > /dev/null ; echo $?)
|
||||
if [ "$retval" = "0" ] ; then
|
||||
echo " ------- nzbget *is* running -------"
|
||||
ps -Ho user,pid,cmd:32,pcpu -C nzbget
|
||||
exit 0
|
||||
else
|
||||
echo " ------- nzbget is *not* running -------"
|
||||
exit 0
|
||||
fi
|
||||
;;
|
||||
istatus)
|
||||
status
|
||||
;;
|
||||
*)
|
||||
echo "Usage $0 {start|stop|restart|pstatus|istatus}"
|
||||
exit 1
|
||||
esac
|
||||
|
||||
exit 0
|
||||
@@ -1,45 +0,0 @@
|
||||
# Template configuration file for postprocessing script "postprocess-example.sh".
|
||||
# Please refer to "postprocess-example.sh" for usage instructions.
|
||||
|
||||
##############################################################################
|
||||
### PATHS ###
|
||||
|
||||
# Set the full path to unrar if it is not in your PATH.
|
||||
UnrarCmd=unrar
|
||||
|
||||
|
||||
##############################################################################
|
||||
### OPTIONS ###
|
||||
|
||||
# Delete rar-files after unpacking (yes, no).
|
||||
DeleteRarFiles=yes
|
||||
|
||||
# Rename img-files to iso (yes, no).
|
||||
RenameIMG=yes
|
||||
|
||||
# Joint TS-files (yes, no).
|
||||
JoinTS=no
|
||||
|
||||
##############################################################################
|
||||
### 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 "password" to value "123" for
|
||||
# nzb-file with id=2:
|
||||
# nzbget -E G O Password=123 2
|
||||
|
||||
# Perform postprocessing (yes, no).
|
||||
#
|
||||
# Set to "no" to skip postprocessing for this nzb-file.
|
||||
PostProcess=yes
|
||||
|
||||
# Password for encrypted posts.
|
||||
#
|
||||
# If the post requires a password for unpacking.
|
||||
Password=
|
||||
|
||||
# Destination directory.
|
||||
#
|
||||
# NOTE: NZBGet must have write-access-rights for that directory.
|
||||
DestDir=
|
||||
@@ -1,326 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Example postprocessing script for NZBGet
|
||||
#
|
||||
# Copyright (C) 2008 Peter Roubos <peterroubos@hotmail.com>
|
||||
# Copyright (C) 2008 Otmar Werner
|
||||
# Copyright (C) 2008-2009 Andrei Prygounkov <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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
#
|
||||
#
|
||||
|
||||
####################### Usage instructions #######################
|
||||
# o Script will unrar downloaded rar files, 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 "postprocess-example.conf". Put the configuration file
|
||||
# into the directory where nzbget's configuration file (nzbget.conf) or where
|
||||
# this script itself 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 (requires
|
||||
# NZBGetWeb 1.4 or later). Set the options "PostProcessConfigFile" and
|
||||
# "PostProcessConfigTemplate" to point to "postprocess-example.conf"
|
||||
# (including full path). The both options are under the section
|
||||
# "CONFIGURATION OF POSTPROCESSING-SCRIPT" in NZBGetWeb.
|
||||
#
|
||||
# o There are few options, which can be ajdusted for each nzb-file
|
||||
# individually. To view/edit them in web-interface click on a spanner icon
|
||||
# near the name of nzb-file.
|
||||
#
|
||||
# o The script supports the feature called "delayed par-check".
|
||||
# That means it can try to unpack downloaded files without par-checking
|
||||
# them fisrt. Only if unpack fails, the script schedules par-check,
|
||||
# then unpacks again.
|
||||
# To use delayed par-check set following options in nzbget configuration file:
|
||||
# ParCheck=no
|
||||
# ParRepair=yes
|
||||
# LoadPars=one (or) LoadPars=all
|
||||
#
|
||||
# o If you want to par-check/repair all files before trying to unpack them,
|
||||
# set option "ParCheck=yes".
|
||||
#
|
||||
####################### End of Usage instructions #######################
|
||||
|
||||
|
||||
# NZBGet passes following arguments to postprocess-programm as environment
|
||||
# variables:
|
||||
# NZBPP_DIRECTORY - path to destination dir for downloaded files;
|
||||
# NZBPP_NZBFILENAME - name of processed nzb-file;
|
||||
# NZBPP_PARFILENAME - name of par-file or empty string (if no collections were
|
||||
# found);
|
||||
# NZBPP_PARSTATUS - result of par-check:
|
||||
# 0 = not checked: par-check 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_NZBCOMPLETED - state of nzb-job:
|
||||
# 0 = there are more collections in this nzb-file queued;
|
||||
# 1 = this was the last collection in nzb-file;
|
||||
# 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_CATEGORY - category assigned to nzb-file (can be empty string).
|
||||
|
||||
|
||||
# Name of script's configuration file
|
||||
SCRIPT_CONFIG_FILE="postprocess-example.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
|
||||
if [ "$NZBPP_DIRECTORY" = "" -o "$NZBOP_CONFIGFILE" = "" ]; then
|
||||
echo "*** NZBGet post-process script ***"
|
||||
echo "This script is supposed to be called from nzbget (0.7.0 or later)."
|
||||
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: Postprocessing disabled for this nzb-file, exiting"
|
||||
exit $POSTPROCESS_NONE
|
||||
fi
|
||||
|
||||
echo "[INFO] Post-Process: Post-process script successfully started"
|
||||
|
||||
# Determine the location of configuration file (it must be stored in
|
||||
# the directory with nzbget.conf or in this script's directory).
|
||||
ConfigDir="${NZBOP_CONFIGFILE%/*}"
|
||||
ScriptConfigFile="$ConfigDir/$SCRIPT_CONFIG_FILE"
|
||||
if [ ! -f "$ScriptConfigFile" ]; then
|
||||
ConfigDir="${0%/*}"
|
||||
ScriptConfigFile="$ConfigDir/$SCRIPT_CONFIG_FILE"
|
||||
fi
|
||||
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_LOADPARS" = "none" ]; then
|
||||
echo "[ERROR] Post-Process: Please set option \"LoadPars\" to \"One\" or \"All\" in nzbget configuration file"
|
||||
BadConfig=1
|
||||
fi
|
||||
|
||||
if [ "$NZBOP_PARREPAIR" = "no" ]; then
|
||||
echo "[ERROR] Post-Process: Please set option \"ParRepair\" to \"Yes\" in nzbget configuration file"
|
||||
BadConfig=1
|
||||
fi
|
||||
|
||||
if [ "$BadConfig" -eq 1 ]; then
|
||||
echo "[ERROR] Post-Process: Existing because of not compatible nzbget configuration"
|
||||
exit $POSTPROCESS_ERROR
|
||||
fi
|
||||
|
||||
# Check if all collections in nzb-file were downloaded
|
||||
if [ ! "$NZBPP_NZBCOMPLETED" -eq 1 ]; then
|
||||
echo "[INFO] Post-Process: Not the last collection in nzb-file, exiting"
|
||||
exit $POSTPROCESS_SUCCESS
|
||||
fi
|
||||
|
||||
# Check par status
|
||||
if [ "$NZBPP_PARSTATUS" -eq 1 -o "$NZBPP_PARSTATUS" -eq 3 -o "$NZBPP_PARFAILED" -eq 1 ]; then
|
||||
if [ "$NZBPP_PARSTATUS" -eq 3 ]; then
|
||||
echo "[WARNING] Post-Process: Par-check successful, but Par-repair disabled, exiting"
|
||||
else
|
||||
echo "[WARNING] Post-Process: Par-check failed, exiting"
|
||||
fi
|
||||
exit $POSTPROCESS_ERROR
|
||||
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
|
||||
|
||||
cd "$NZBPP_DIRECTORY"
|
||||
|
||||
# If not just repaired and file "_brokenlog.txt" exists, the collection is damaged
|
||||
# exiting with returning code $POSTPROCESS_PARCHECK_ALL to request par-repair
|
||||
if [ ! "$NZBPP_PARSTATUS" -eq 2 ]; then
|
||||
if [ -f "_brokenlog.txt" ]; then
|
||||
if (ls *.[pP][aA][rR]2 >/dev/null 2>&1); then
|
||||
echo "[INFO] Post-Process: Brokenlog found, requesting par-repair"
|
||||
exit $POSTPROCESS_PARCHECK_ALL
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# All checks done, now processing the files
|
||||
|
||||
# Flag indicates that something was unrared
|
||||
Unrared=0
|
||||
|
||||
# Unrar the files (if any) to the temporary directory, if there are no rar files this will do nothing
|
||||
if (ls *.rar >/dev/null 2>&1); then
|
||||
|
||||
# Check if unrar exists
|
||||
$UnrarCmd >/dev/null 2>&1
|
||||
if [ "$?" -eq 127 ]; then
|
||||
echo "[ERROR] Post-Process: Unrar not found. Set the path to unrar in script's configuration"
|
||||
exit $POSTPROCESS_ERROR
|
||||
fi
|
||||
|
||||
# Make a temporary directory to store the unrarred files
|
||||
ExtractedDirExists=0
|
||||
if [ -d extracted ]; then
|
||||
ExtractedDirExists=1
|
||||
else
|
||||
mkdir extracted
|
||||
fi
|
||||
|
||||
echo "[INFO] Post-Process: Unraring"
|
||||
rarpasswordparam=""
|
||||
if [ "$NZBPR_Password" != "" ]; then
|
||||
rarpasswordparam="-p$NZBPR_Password"
|
||||
fi
|
||||
|
||||
$UnrarCmd x -y -p- "$rarpasswordparam" -o+ "*.rar" ./extracted/
|
||||
if [ "$?" -eq 3 ]; then
|
||||
echo "[ERROR] Post-Process: Unrar failed"
|
||||
if [ "$ExtractedDirExists" -eq 0 ]; then
|
||||
rm -R extracted
|
||||
fi
|
||||
# for delayed par-check/-repair at least one par-file must be already downloaded
|
||||
if (ls *.[pP][aA][rR]2 >/dev/null 2>&1); then
|
||||
echo "[INFO] Post-Process: Requesting par-repair"
|
||||
exit $POSTPROCESS_PARCHECK_ALL
|
||||
fi
|
||||
exit $POSTPROCESS_ERROR
|
||||
fi
|
||||
Unrared=1
|
||||
|
||||
# Remove the rar files
|
||||
if [ "$DeleteRarFiles" = "yes" ]; then
|
||||
echo "[INFO] Post-Process: Deleting rar-files"
|
||||
rm *.r[0-9][0-9] >/dev/null 2>&1
|
||||
rm *.rar >/dev/null 2>&1
|
||||
rm *.s[0-9][0-9] >/dev/null 2>&1
|
||||
fi
|
||||
|
||||
# Go to the temp directory and try to unrar again.
|
||||
# If there are any rars inside the extracted rars then these will no also be unrarred
|
||||
cd extracted
|
||||
if (ls *.rar >/dev/null 2>&1); then
|
||||
echo "[INFO] Post-Process: Unraring (second pass)"
|
||||
$UnrarCmd x -y -p- -o+ "*.rar"
|
||||
|
||||
if [ "$?" -eq 3 ]; then
|
||||
echo "[INFO] Post-Process: Unrar (second pass) failed"
|
||||
exit $POSTPROCESS_ERROR
|
||||
fi
|
||||
|
||||
# Delete the Rar files
|
||||
if [ "$DeleteRarFiles" = "yes" ]; then
|
||||
echo "[INFO] Post-Process: Deleting rar-files (second pass)"
|
||||
rm *.r[0-9][0-9] >/dev/null 2>&1
|
||||
rm *.rar >/dev/null 2>&1
|
||||
rm *.s[0-9][0-9] >/dev/null 2>&1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Move everything back to the Download folder
|
||||
mv * ..
|
||||
cd ..
|
||||
rmdir extracted
|
||||
fi
|
||||
|
||||
# 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
|
||||
if [ "$Unrared" -eq 1 ]; then
|
||||
# Delete par2-file only if there were files for unpacking.
|
||||
rm *.[pP][aA][rR]2 >/dev/null 2>&1
|
||||
fi
|
||||
|
||||
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
|
||||
fi
|
||||
|
||||
# Remove all the split .ts files
|
||||
echo "[INFO] Post-Process: Deleting source ts-files"
|
||||
rm *0???.ts >/dev/null 2>&1
|
||||
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
|
||||
28
win32.h
28
win32.h
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of nzbget
|
||||
*
|
||||
* Copyright (C) 2007-2010 Andrei Prygounkov <hugbug@users.sourceforge.net>
|
||||
* Copyright (C) 2007 Andrei Prygounkov <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
|
||||
@@ -25,18 +25,10 @@
|
||||
/* win32.h - Defines and standard includes for MS Windows / Visual C++ 2005 */
|
||||
|
||||
/* Define to 1 to not use curses */
|
||||
//#define DISABLE_CURSES
|
||||
#undef DISABLE_CURSES
|
||||
|
||||
/* Define to 1 to disable smart par-verification and restoration */
|
||||
//#define DISABLE_PARCHECK
|
||||
|
||||
/* Define to 1 to disable TLS/SSL-support. */
|
||||
//#define DISABLE_TLS
|
||||
|
||||
#ifndef DISABLE_TLS
|
||||
/* Define to 1 to use GnuTLS library for TLS/SSL-support */
|
||||
#define HAVE_LIBGNUTLS
|
||||
#endif
|
||||
#undef DISABLE_PARCHECK
|
||||
|
||||
/* Define to the name of macro which returns the name of function being
|
||||
compiled */
|
||||
@@ -54,16 +46,7 @@
|
||||
/* Define to 1 if variadic macros are supported */
|
||||
#define HAVE_VARIADIC_MACROS
|
||||
|
||||
/* Define to 1 if libpar2 supports cancelling (needs a special patch) */
|
||||
#define HAVE_PAR2_CANCEL
|
||||
|
||||
/* Define to 1 if function GetAddrInfo is supported */
|
||||
#define HAVE_GETADDRINFO
|
||||
|
||||
/* Determine what socket length (socklen_t) data type is */
|
||||
#define SOCKLEN_T socklen_t
|
||||
|
||||
#define VERSION "0.7.0"
|
||||
#define VERSION "0.4.1"
|
||||
|
||||
/* Suppress warnings */
|
||||
#define _CRT_SECURE_NO_DEPRECATE
|
||||
@@ -80,7 +63,6 @@
|
||||
#include <crtdbg.h>
|
||||
#endif
|
||||
|
||||
#ifndef SKIP_DEFAULT_WINDOWS_HEADERS
|
||||
#include <windows.h>
|
||||
#include <winbase.h>
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user