1 /*
2  *  This file is part of nzbget. See <http://nzbget.net>.
3  *
4  *  Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
5  *  Copyright (C) 2007-2019 Andrey Prygunkov <hugbug@users.sourceforge.net>
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 2 of the License, or
10  *  (at your option) any later version.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
19  */
20 
21 
22 #ifndef DOWNLOADINFO_H
23 #define DOWNLOADINFO_H
24 
25 #include "NString.h"
26 #include "Container.h"
27 #include "Observer.h"
28 #include "Log.h"
29 #include "Thread.h"
30 
31 class NzbInfo;
32 class DownloadQueue;
33 class PostInfo;
34 
35 class ServerStat
36 {
37 public:
ServerStat(int serverId)38 	ServerStat(int serverId) : m_serverId(serverId) {}
GetServerId()39 	int GetServerId() { return m_serverId; }
GetSuccessArticles()40 	int GetSuccessArticles() { return m_successArticles; }
SetSuccessArticles(int successArticles)41 	void SetSuccessArticles(int successArticles) { m_successArticles = successArticles; }
GetFailedArticles()42 	int GetFailedArticles() { return m_failedArticles; }
SetFailedArticles(int failedArticles)43 	void SetFailedArticles(int failedArticles) { m_failedArticles = failedArticles; }
44 
45 private:
46 	int m_serverId;
47 	int m_successArticles = 0;
48 	int m_failedArticles = 0;
49 };
50 
51 typedef std::vector<ServerStat> ServerStatListBase;
52 
53 class ServerStatList : public ServerStatListBase
54 {
55 public:
56 	enum EStatOperation
57 	{
58 		soSet,
59 		soAdd,
60 		soSubtract
61 	};
62 
63 	void StatOp(int serverId, int successArticles, int failedArticles, EStatOperation statOperation);
64 	void ListOp(ServerStatList* serverStats, EStatOperation statOperation);
65 };
66 
67 class SegmentData
68 {
69 public:
70 	virtual char* GetData() = 0;
~SegmentData()71 	virtual ~SegmentData() {}
72 };
73 
74 class ArticleInfo
75 {
76 public:
77 	enum EStatus
78 	{
79 		aiUndefined,
80 		aiRunning,
81 		aiFinished,
82 		aiFailed
83 	};
84 
SetPartNumber(int s)85 	void SetPartNumber(int s) { m_partNumber = s; }
GetPartNumber()86 	int GetPartNumber() { return m_partNumber; }
GetMessageId()87 	const char* GetMessageId() { return m_messageId; }
SetMessageId(const char * messageId)88 	void SetMessageId(const char* messageId) { m_messageId = messageId; }
SetSize(int size)89 	void SetSize(int size) { m_size = size; }
GetSize()90 	int GetSize() { return m_size; }
91 	void AttachSegment(std::unique_ptr<SegmentData> content, int64 offset, int size);
92 	void DiscardSegment();
GetSegmentContent()93 	const char* GetSegmentContent() { return m_segmentContent ? m_segmentContent->GetData() : nullptr; }
SetSegmentOffset(int64 segmentOffset)94 	void SetSegmentOffset(int64 segmentOffset) { m_segmentOffset = segmentOffset; }
GetSegmentOffset()95 	int64 GetSegmentOffset() { return m_segmentOffset; }
SetSegmentSize(int segmentSize)96 	void SetSegmentSize(int segmentSize) { m_segmentSize = segmentSize; }
GetSegmentSize()97 	int GetSegmentSize() { return m_segmentSize; }
GetStatus()98 	EStatus GetStatus() { return m_status; }
SetStatus(EStatus Status)99 	void SetStatus(EStatus Status) { m_status = Status; }
GetResultFilename()100 	const char* GetResultFilename() { return m_resultFilename; }
SetResultFilename(const char * resultFilename)101 	void SetResultFilename(const char* resultFilename) { m_resultFilename = resultFilename; }
GetCrc()102 	uint32 GetCrc() { return m_crc; }
SetCrc(uint32 crc)103 	void SetCrc(uint32 crc) { m_crc = crc; }
104 
105 private:
106 	int m_partNumber;
107 	CString m_messageId;
108 	int m_size = 0;
109 	std::unique_ptr<SegmentData> m_segmentContent;
110 	int64 m_segmentOffset = 0;
111 	int m_segmentSize = 0;
112 	EStatus m_status = aiUndefined;
113 	CString m_resultFilename;
114 	uint32 m_crc = 0;
115 };
116 
117 typedef std::vector<std::unique_ptr<ArticleInfo>> ArticleList;
118 
119 class FileInfo
120 {
121 public:
122 	enum EPartialState
123 	{
124 		psNone,
125 		psPartial,
126 		psCompleted
127 	};
128 
129 	typedef std::vector<CString> Groups;
130 
131 	FileInfo(int id = 0) : m_id(id ? id : ++m_idGen) {}
GetId()132 	int GetId() { return m_id; }
133 	void SetId(int id);
134 	static void ResetGenId(bool max);
GetNzbInfo()135 	NzbInfo* GetNzbInfo() { return m_nzbInfo; }
SetNzbInfo(NzbInfo * nzbInfo)136 	void SetNzbInfo(NzbInfo* nzbInfo) { m_nzbInfo = nzbInfo; }
GetArticles()137 	ArticleList* GetArticles() { return &m_articles; }
GetGroups()138 	Groups* GetGroups() { return &m_groups; }
GetSubject()139 	const char* GetSubject() { return m_subject; }
SetSubject(const char * subject)140 	void SetSubject(const char* subject) { m_subject = subject; }
GetFilename()141 	const char* GetFilename() { return m_filename; }
SetFilename(const char * filename)142 	void SetFilename(const char* filename) { m_filename = filename; }
SetOrigname(const char * origname)143 	void SetOrigname(const char* origname) { m_origname = origname; }
GetOrigname()144 	const char* GetOrigname() { return m_origname; }
145 	void MakeValidFilename();
GetFilenameConfirmed()146 	bool GetFilenameConfirmed() { return m_filenameConfirmed; }
SetFilenameConfirmed(bool filenameConfirmed)147 	void SetFilenameConfirmed(bool filenameConfirmed) { m_filenameConfirmed = filenameConfirmed; }
SetSize(int64 size)148 	void SetSize(int64 size) { m_size = size; m_remainingSize = size; }
GetSize()149 	int64 GetSize() { return m_size; }
GetRemainingSize()150 	int64 GetRemainingSize() { return m_remainingSize; }
SetRemainingSize(int64 remainingSize)151 	void SetRemainingSize(int64 remainingSize) { m_remainingSize = remainingSize; }
GetMissedSize()152 	int64 GetMissedSize() { return m_missedSize; }
SetMissedSize(int64 missedSize)153 	void SetMissedSize(int64 missedSize) { m_missedSize = missedSize; }
GetSuccessSize()154 	int64 GetSuccessSize() { return m_successSize; }
SetSuccessSize(int64 successSize)155 	void SetSuccessSize(int64 successSize) { m_successSize = successSize; }
GetFailedSize()156 	int64 GetFailedSize() { return m_failedSize; }
SetFailedSize(int64 failedSize)157 	void SetFailedSize(int64 failedSize) { m_failedSize = failedSize; }
GetTotalArticles()158 	int GetTotalArticles() { return m_totalArticles; }
SetTotalArticles(int totalArticles)159 	void SetTotalArticles(int totalArticles) { m_totalArticles = totalArticles; }
GetMissedArticles()160 	int GetMissedArticles() { return m_missedArticles; }
SetMissedArticles(int missedArticles)161 	void SetMissedArticles(int missedArticles) { m_missedArticles = missedArticles; }
GetFailedArticles()162 	int GetFailedArticles() { return m_failedArticles; }
SetFailedArticles(int failedArticles)163 	void SetFailedArticles(int failedArticles) { m_failedArticles = failedArticles; }
GetSuccessArticles()164 	int GetSuccessArticles() { return m_successArticles; }
SetSuccessArticles(int successArticles)165 	void SetSuccessArticles(int successArticles) { m_successArticles = successArticles; }
GetTime()166 	time_t GetTime() { return m_time; }
SetTime(time_t time)167 	void SetTime(time_t time) { m_time = time; }
GetPaused()168 	bool GetPaused() { return m_paused; }
169 	void SetPaused(bool paused);
GetDeleted()170 	bool GetDeleted() { return m_deleted; }
SetDeleted(bool Deleted)171 	void SetDeleted(bool Deleted) { m_deleted = Deleted; }
GetCompletedArticles()172 	int GetCompletedArticles() { return m_completedArticles; }
SetCompletedArticles(int completedArticles)173 	void SetCompletedArticles(int completedArticles) { m_completedArticles = completedArticles; }
GetParFile()174 	bool GetParFile() { return m_parFile; }
SetParFile(bool parFile)175 	void SetParFile(bool parFile) { m_parFile = parFile; }
GuardOutputFile()176 	Guard GuardOutputFile() { return Guard(m_outputFileMutex); }
GetOutputFilename()177 	const char* GetOutputFilename() { return m_outputFilename; }
SetOutputFilename(const char * outputFilename)178 	void SetOutputFilename(const char* outputFilename) { m_outputFilename = outputFilename; }
GetOutputInitialized()179 	bool GetOutputInitialized() { return m_outputInitialized; }
SetOutputInitialized(bool outputInitialized)180 	void SetOutputInitialized(bool outputInitialized) { m_outputInitialized = outputInitialized; }
GetExtraPriority()181 	bool GetExtraPriority() { return m_extraPriority; }
182 	void SetExtraPriority(bool extraPriority);
GetActiveDownloads()183 	int GetActiveDownloads() { return m_activeDownloads; }
184 	void SetActiveDownloads(int activeDownloads);
GetDupeDeleted()185 	bool GetDupeDeleted() { return m_dupeDeleted; }
SetDupeDeleted(bool dupeDeleted)186 	void SetDupeDeleted(bool dupeDeleted) { m_dupeDeleted = dupeDeleted; }
GetCachedArticles()187 	int GetCachedArticles() { return m_cachedArticles; }
SetCachedArticles(int cachedArticles)188 	void SetCachedArticles(int cachedArticles) { m_cachedArticles = cachedArticles; }
GetPartialChanged()189 	bool GetPartialChanged() { return m_partialChanged; }
SetPartialChanged(bool partialChanged)190 	void SetPartialChanged(bool partialChanged) { m_partialChanged = partialChanged; }
GetForceDirectWrite()191 	bool GetForceDirectWrite() { return m_forceDirectWrite; }
SetForceDirectWrite(bool forceDirectWrite)192 	void SetForceDirectWrite(bool forceDirectWrite) { m_forceDirectWrite = forceDirectWrite; }
GetPartialState()193 	EPartialState GetPartialState() { return m_partialState; }
SetPartialState(EPartialState partialState)194 	void SetPartialState(EPartialState partialState) { m_partialState = partialState; }
GetCrc()195 	uint32 GetCrc() { return m_crc; }
SetCrc(uint32 crc)196 	void SetCrc(uint32 crc) { m_crc = crc; }
GetHash16k()197 	const char* GetHash16k() { return m_hash16k; }
SetHash16k(const char * hash16k)198 	void SetHash16k(const char* hash16k) { m_hash16k = hash16k; }
GetParSetId()199 	const char* GetParSetId() { return m_parSetId; }
SetParSetId(const char * parSetId)200 	void SetParSetId(const char* parSetId) { m_parSetId = parSetId; }
GetFlushLocked()201 	bool GetFlushLocked() { return m_flushLocked; }
SetFlushLocked(bool flushLocked)202 	void SetFlushLocked(bool flushLocked) { m_flushLocked = flushLocked; }
203 
GetServerStats()204 	ServerStatList* GetServerStats() { return &m_serverStats; }
205 
206 private:
207 	int m_id;
208 	NzbInfo* m_nzbInfo = nullptr;
209 	ArticleList m_articles;
210 	Groups m_groups;
211 	ServerStatList m_serverStats;
212 	CString m_subject;
213 	CString m_filename;
214 	CString m_origname;
215 	int64 m_size = 0;
216 	int64 m_remainingSize = 0;
217 	int64 m_successSize = 0;
218 	int64 m_failedSize = 0;
219 	int64 m_missedSize = 0;
220 	int m_totalArticles = 0;
221 	int m_missedArticles = 0;
222 	int m_failedArticles = 0;
223 	int m_successArticles = 0;
224 	time_t m_time = 0;
225 	bool m_paused = false;
226 	bool m_deleted = false;
227 	bool m_filenameConfirmed = false;
228 	bool m_parFile = false;
229 	int m_completedArticles = 0;
230 	bool m_outputInitialized = false;
231 	CString m_outputFilename;
232 	std::unique_ptr<Mutex> m_outputFileMutex;
233 	bool m_extraPriority = false;
234 	int m_activeDownloads = 0;
235 	bool m_dupeDeleted = false;
236 	int m_cachedArticles = 0;
237 	bool m_partialChanged = false;
238 	bool m_forceDirectWrite = false;
239 	EPartialState m_partialState = psNone;
240 	uint32 m_crc = 0;
241 	CString m_hash16k;
242 	CString m_parSetId;
243 	bool m_flushLocked = false;
244 
245 	static int m_idGen;
246 	static int m_idMax;
247 
248 	friend class CompletedFile;
249 };
250 
251 typedef UniqueDeque<FileInfo> FileList;
252 typedef std::vector<FileInfo*> RawFileList;
253 
254 class CompletedFile
255 {
256 public:
257 	enum EStatus
258 	{
259 		cfNone,
260 		cfSuccess,
261 		cfPartial,
262 		cfFailure
263 	};
264 
265 	CompletedFile(int id, const char* filename, const char* oldname, EStatus status,
266 		uint32 crc, bool parFile, const char* hash16k, const char* parSetId);
GetId()267 	int GetId() { return m_id; }
SetFilename(const char * filename)268 	void SetFilename(const char* filename) { m_filename = filename; }
GetFilename()269 	const char* GetFilename() { return m_filename; }
SetOrigname(const char * origname)270 	void SetOrigname(const char* origname) { m_origname = origname; }
GetOrigname()271 	const char* GetOrigname() { return m_origname; }
GetParFile()272 	bool GetParFile() { return m_parFile; }
GetStatus()273 	EStatus GetStatus() { return m_status; }
GetCrc()274 	uint32 GetCrc() { return m_crc; }
GetHash16k()275 	const char* GetHash16k() { return m_hash16k; }
SetHash16k(const char * hash16k)276 	void SetHash16k(const char* hash16k) { m_hash16k = hash16k; }
GetParSetId()277 	const char* GetParSetId() { return m_parSetId; }
SetParSetId(const char * parSetId)278 	void SetParSetId(const char* parSetId) { m_parSetId = parSetId; }
279 
280 private:
281 	int m_id;
282 	CString m_filename;
283 	CString m_origname;
284 	EStatus m_status;
285 	uint32 m_crc;
286 	bool m_parFile;
287 	CString m_hash16k;
288 	CString m_parSetId;
289 };
290 
291 typedef std::deque<CompletedFile> CompletedFileList;
292 
293 class NzbParameter
294 {
295 public:
NzbParameter(const char * name,const char * value)296 	NzbParameter(const char* name, const char* value) :
297 		m_name(name), m_value(value) {}
GetName()298 	const char* GetName() { return m_name; }
GetValue()299 	const char* GetValue() { return m_value; }
300 
301 private:
302 	CString m_name;
303 	CString m_value;
304 
SetValue(const char * value)305 	void SetValue(const char* value) { m_value = value; }
306 
307 	friend class NzbParameterList;
308 };
309 
310 typedef std::deque<NzbParameter> NzbParameterListBase;
311 
312 class NzbParameterList : public NzbParameterListBase
313 {
314 public:
315 	void SetParameter(const char* name, const char* value);
316 	NzbParameter* Find(const char* name);
317 	void CopyFrom(NzbParameterList* sourceParameters);
318 };
319 
320 class ScriptStatus
321 {
322 public:
323 	enum EStatus
324 	{
325 		srNone,
326 		srFailure,
327 		srSuccess
328 	};
329 
ScriptStatus(const char * name,EStatus status)330 	ScriptStatus(const char* name, EStatus status) :
331 		m_name(name), m_status(status) {}
GetName()332 	const char* GetName() { return m_name; }
GetStatus()333 	EStatus GetStatus() { return m_status; }
334 
335 private:
336 	CString m_name;
337 	EStatus m_status;
338 
339 	friend class ScriptStatusList;
340 };
341 
342 typedef std::deque<ScriptStatus> ScriptStatusListBase;
343 
344 class ScriptStatusList : public ScriptStatusListBase
345 {
346 public:
347 	ScriptStatus::EStatus CalcTotalStatus();
348 };
349 
350 enum EDupeMode
351 {
352 	dmScore,
353 	dmAll,
354 	dmForce
355 };
356 
357 class NzbInfo
358 {
359 public:
360 	enum EDirectRenameStatus
361 	{
362 		tsNone,
363 		tsRunning,
364 		tsFailure,
365 		tsSuccess
366 	};
367 
368 	enum EPostRenameStatus
369 	{
370 		rsNone,
371 		rsSkipped,
372 		rsNothing,
373 		rsSuccess
374 	};
375 
376 	enum EParStatus
377 	{
378 		psNone,
379 		psSkipped,
380 		psFailure,
381 		psSuccess,
382 		psRepairPossible,
383 		psManual
384 	};
385 
386 	enum EDirectUnpackStatus
387 	{
388 		nsNone,
389 		nsRunning,
390 		nsFailure,
391 		nsSuccess
392 	};
393 
394 	enum EPostUnpackStatus
395 	{
396 		usNone,
397 		usSkipped,
398 		usFailure,
399 		usSuccess,
400 		usSpace,
401 		usPassword
402 	};
403 
404 	enum ECleanupStatus
405 	{
406 		csNone,
407 		csFailure,
408 		csSuccess
409 	};
410 
411 	enum EMoveStatus
412 	{
413 		msNone,
414 		msFailure,
415 		msSuccess
416 	};
417 
418 	enum EDeleteStatus
419 	{
420 		dsNone,
421 		dsManual,
422 		dsHealth,
423 		dsDupe,
424 		dsBad,
425 		dsGood,
426 		dsCopy,
427 		dsScan
428 	};
429 
430 	enum EMarkStatus
431 	{
432 		ksNone,
433 		ksBad,
434 		ksGood,
435 		ksSuccess
436 	};
437 
438 	enum EUrlStatus
439 	{
440 		lsNone,
441 		lsRunning,
442 		lsFinished,
443 		lsFailed,
444 		lsRetry,
445 		lsScanSkipped,
446 		lsScanFailed
447 	};
448 
449 	enum EKind
450 	{
451 		nkNzb,
452 		nkUrl
453 	};
454 
455 	enum EDupeHint
456 	{
457 		dhNone,
458 		dhRedownloadManual,
459 		dhRedownloadAuto
460 	};
461 
GetId()462 	int GetId() { return m_id; }
463 	void SetId(int id);
464 	static void ResetGenId(bool max);
465 	static int GenerateId();
GetKind()466 	EKind GetKind() { return m_kind; }
SetKind(EKind kind)467 	void SetKind(EKind kind) { m_kind = kind; }
GetUrl()468 	const char* GetUrl() { return m_url; }
469 	void SetUrl(const char* url);
GetFilename()470 	const char* GetFilename() { return m_filename; }
471 	void SetFilename(const char* filename);
472 	static CString MakeNiceNzbName(const char* nzbFilename, bool removeExt);
473 	static CString MakeNiceUrlName(const char* url, const char* nzbFilename);
GetDestDir()474 	const char* GetDestDir() { return m_destDir; }
SetDestDir(const char * destDir)475 	void SetDestDir(const char* destDir) { m_destDir = destDir; }
GetFinalDir()476 	const char* GetFinalDir() { return m_finalDir; }
SetFinalDir(const char * finalDir)477 	void SetFinalDir(const char* finalDir) { m_finalDir = finalDir; }
GetCategory()478 	const char* GetCategory() { return m_category; }
SetCategory(const char * category)479 	void SetCategory(const char* category) { m_category = category; }
GetName()480 	const char* GetName() { return m_name; }
SetName(const char * name)481 	void SetName(const char* name) { m_name = name; }
GetFileCount()482 	int GetFileCount() { return m_fileCount; }
SetFileCount(int fileCount)483 	void SetFileCount(int fileCount) { m_fileCount = fileCount; }
GetParkedFileCount()484 	int GetParkedFileCount() { return m_parkedFileCount; }
SetParkedFileCount(int parkedFileCount)485 	void SetParkedFileCount(int parkedFileCount) { m_parkedFileCount = parkedFileCount; }
GetSize()486 	int64 GetSize() { return m_size; }
SetSize(int64 size)487 	void SetSize(int64 size) { m_size = size; }
GetRemainingSize()488 	int64 GetRemainingSize() { return m_remainingSize; }
SetRemainingSize(int64 remainingSize)489 	void SetRemainingSize(int64 remainingSize) { m_remainingSize = remainingSize; }
GetPausedSize()490 	int64 GetPausedSize() { return m_pausedSize; }
SetPausedSize(int64 pausedSize)491 	void SetPausedSize(int64 pausedSize) { m_pausedSize = pausedSize; }
GetPausedFileCount()492 	int GetPausedFileCount() { return m_pausedFileCount; }
SetPausedFileCount(int pausedFileCount)493 	void SetPausedFileCount(int pausedFileCount) { m_pausedFileCount = pausedFileCount; }
GetRemainingParCount()494 	int GetRemainingParCount() { return m_remainingParCount; }
SetRemainingParCount(int remainingParCount)495 	void SetRemainingParCount(int remainingParCount) { m_remainingParCount = remainingParCount; }
GetActiveDownloads()496 	int GetActiveDownloads() { return m_activeDownloads; }
497 	void SetActiveDownloads(int activeDownloads);
GetSuccessSize()498 	int64 GetSuccessSize() { return m_successSize; }
SetSuccessSize(int64 successSize)499 	void SetSuccessSize(int64 successSize) { m_successSize = successSize; }
GetFailedSize()500 	int64 GetFailedSize() { return m_failedSize; }
SetFailedSize(int64 failedSize)501 	void SetFailedSize(int64 failedSize) { m_failedSize = failedSize; }
GetCurrentSuccessSize()502 	int64 GetCurrentSuccessSize() { return m_currentSuccessSize; }
SetCurrentSuccessSize(int64 currentSuccessSize)503 	void SetCurrentSuccessSize(int64 currentSuccessSize) { m_currentSuccessSize = currentSuccessSize; }
GetCurrentFailedSize()504 	int64 GetCurrentFailedSize() { return m_currentFailedSize; }
SetCurrentFailedSize(int64 currentFailedSize)505 	void SetCurrentFailedSize(int64 currentFailedSize) { m_currentFailedSize = currentFailedSize; }
GetParSize()506 	int64 GetParSize() { return m_parSize; }
SetParSize(int64 parSize)507 	void SetParSize(int64 parSize) { m_parSize = parSize; }
GetParSuccessSize()508 	int64 GetParSuccessSize() { return m_parSuccessSize; }
SetParSuccessSize(int64 parSuccessSize)509 	void SetParSuccessSize(int64 parSuccessSize) { m_parSuccessSize = parSuccessSize; }
GetParFailedSize()510 	int64 GetParFailedSize() { return m_parFailedSize; }
SetParFailedSize(int64 parFailedSize)511 	void SetParFailedSize(int64 parFailedSize) { m_parFailedSize = parFailedSize; }
GetParCurrentSuccessSize()512 	int64 GetParCurrentSuccessSize() { return m_parCurrentSuccessSize; }
SetParCurrentSuccessSize(int64 parCurrentSuccessSize)513 	void SetParCurrentSuccessSize(int64 parCurrentSuccessSize) { m_parCurrentSuccessSize = parCurrentSuccessSize; }
GetParCurrentFailedSize()514 	int64 GetParCurrentFailedSize() { return m_parCurrentFailedSize; }
SetParCurrentFailedSize(int64 parCurrentFailedSize)515 	void SetParCurrentFailedSize(int64 parCurrentFailedSize) { m_parCurrentFailedSize = parCurrentFailedSize; }
GetTotalArticles()516 	int GetTotalArticles() { return m_totalArticles; }
SetTotalArticles(int totalArticles)517 	void SetTotalArticles(int totalArticles) { m_totalArticles = totalArticles; }
GetSuccessArticles()518 	int GetSuccessArticles() { return m_successArticles; }
SetSuccessArticles(int successArticles)519 	void SetSuccessArticles(int successArticles) { m_successArticles = successArticles; }
GetFailedArticles()520 	int GetFailedArticles() { return m_failedArticles; }
SetFailedArticles(int failedArticles)521 	void SetFailedArticles(int failedArticles) { m_failedArticles = failedArticles; }
GetCurrentSuccessArticles()522 	int GetCurrentSuccessArticles() { return m_currentSuccessArticles; }
SetCurrentSuccessArticles(int currentSuccessArticles)523 	void SetCurrentSuccessArticles(int currentSuccessArticles) { m_currentSuccessArticles = currentSuccessArticles; }
GetCurrentFailedArticles()524 	int GetCurrentFailedArticles() { return m_currentFailedArticles; }
SetCurrentFailedArticles(int currentFailedArticles)525 	void SetCurrentFailedArticles(int currentFailedArticles) { m_currentFailedArticles = currentFailedArticles; }
GetPriority()526 	int GetPriority() { return m_priority; }
SetPriority(int priority)527 	void SetPriority(int priority) { m_priority = priority; }
GetExtraPriority()528 	int GetExtraPriority() { return m_extraPriority; }
SetExtraPriority(int extraPriority)529 	void SetExtraPriority(int extraPriority) { m_extraPriority = extraPriority; }
HasExtraPriority()530 	bool HasExtraPriority() { return m_extraPriority > 0; }
GetForcePriority()531 	bool GetForcePriority() { return m_priority >= FORCE_PRIORITY; }
GetMinTime()532 	time_t GetMinTime() { return m_minTime; }
SetMinTime(time_t minTime)533 	void SetMinTime(time_t minTime) { m_minTime = minTime; }
GetMaxTime()534 	time_t GetMaxTime() { return m_maxTime; }
SetMaxTime(time_t maxTime)535 	void SetMaxTime(time_t maxTime) { m_maxTime = maxTime; }
536 	void BuildDestDirName();
537 	CString BuildFinalDirName();
GetCompletedFiles()538 	CompletedFileList* GetCompletedFiles() { return &m_completedFiles; }
SetDirectRenameStatus(EDirectRenameStatus renameStatus)539 	void SetDirectRenameStatus(EDirectRenameStatus renameStatus) { m_directRenameStatus = renameStatus; }
GetDirectRenameStatus()540 	EDirectRenameStatus GetDirectRenameStatus() { return m_directRenameStatus; }
GetParRenameStatus()541 	EPostRenameStatus GetParRenameStatus() { return m_parRenameStatus; }
SetParRenameStatus(EPostRenameStatus renameStatus)542 	void SetParRenameStatus(EPostRenameStatus renameStatus) { m_parRenameStatus = renameStatus; }
GetRarRenameStatus()543 	EPostRenameStatus GetRarRenameStatus() { return m_rarRenameStatus; }
SetRarRenameStatus(EPostRenameStatus renameStatus)544 	void SetRarRenameStatus(EPostRenameStatus renameStatus) { m_rarRenameStatus = renameStatus; }
GetParStatus()545 	EParStatus GetParStatus() { return m_parStatus; }
SetParStatus(EParStatus parStatus)546 	void SetParStatus(EParStatus parStatus) { m_parStatus = parStatus; }
GetDirectUnpackStatus()547 	EDirectUnpackStatus GetDirectUnpackStatus() { return m_directUnpackStatus; }
SetDirectUnpackStatus(EDirectUnpackStatus directUnpackStatus)548 	void SetDirectUnpackStatus(EDirectUnpackStatus directUnpackStatus) { m_directUnpackStatus = directUnpackStatus; }
GetUnpackStatus()549 	EPostUnpackStatus GetUnpackStatus() { return m_unpackStatus; }
SetUnpackStatus(EPostUnpackStatus unpackStatus)550 	void SetUnpackStatus(EPostUnpackStatus unpackStatus) { m_unpackStatus = unpackStatus; }
GetCleanupStatus()551 	ECleanupStatus GetCleanupStatus() { return m_cleanupStatus; }
SetCleanupStatus(ECleanupStatus cleanupStatus)552 	void SetCleanupStatus(ECleanupStatus cleanupStatus) { m_cleanupStatus = cleanupStatus; }
GetMoveStatus()553 	EMoveStatus GetMoveStatus() { return m_moveStatus; }
SetMoveStatus(EMoveStatus moveStatus)554 	void SetMoveStatus(EMoveStatus moveStatus) { m_moveStatus = moveStatus; }
GetDeleteStatus()555 	EDeleteStatus GetDeleteStatus() { return m_deleteStatus; }
SetDeleteStatus(EDeleteStatus deleteStatus)556 	void SetDeleteStatus(EDeleteStatus deleteStatus) { m_deleteStatus = deleteStatus; }
GetMarkStatus()557 	EMarkStatus GetMarkStatus() { return m_markStatus; }
SetMarkStatus(EMarkStatus markStatus)558 	void SetMarkStatus(EMarkStatus markStatus) { m_markStatus = markStatus; }
GetUrlStatus()559 	EUrlStatus GetUrlStatus() { return m_urlStatus; }
GetExtraParBlocks()560 	int GetExtraParBlocks() { return m_extraParBlocks; }
SetExtraParBlocks(int extraParBlocks)561 	void SetExtraParBlocks(int extraParBlocks) { m_extraParBlocks = extraParBlocks; }
SetUrlStatus(EUrlStatus urlStatus)562 	void SetUrlStatus(EUrlStatus urlStatus) { m_urlStatus = urlStatus; }
GetQueuedFilename()563 	const char* GetQueuedFilename() { return m_queuedFilename; }
SetQueuedFilename(const char * queuedFilename)564 	void SetQueuedFilename(const char* queuedFilename) { m_queuedFilename = queuedFilename; }
GetDeleting()565 	bool GetDeleting() { return m_deleting; }
SetDeleting(bool deleting)566 	void SetDeleting(bool deleting) { m_deleting = deleting; }
GetParking()567 	bool GetParking() { return m_parking; }
SetParking(bool parking)568 	void SetParking(bool parking) { m_parking = parking; }
GetDeletePaused()569 	bool GetDeletePaused() { return m_deletePaused; }
SetDeletePaused(bool deletePaused)570 	void SetDeletePaused(bool deletePaused) { m_deletePaused = deletePaused; }
GetManyDupeFiles()571 	bool GetManyDupeFiles() { return m_manyDupeFiles; }
SetManyDupeFiles(bool manyDupeFiles)572 	void SetManyDupeFiles(bool manyDupeFiles) { m_manyDupeFiles = manyDupeFiles; }
GetAvoidHistory()573 	bool GetAvoidHistory() { return m_avoidHistory; }
SetAvoidHistory(bool avoidHistory)574 	void SetAvoidHistory(bool avoidHistory) { m_avoidHistory = avoidHistory; }
GetHealthPaused()575 	bool GetHealthPaused() { return m_healthPaused; }
SetHealthPaused(bool healthPaused)576 	void SetHealthPaused(bool healthPaused) { m_healthPaused = healthPaused; }
GetCleanupDisk()577 	bool GetCleanupDisk() { return m_cleanupDisk; }
SetCleanupDisk(bool cleanupDisk)578 	void SetCleanupDisk(bool cleanupDisk) { m_cleanupDisk = cleanupDisk; }
GetUnpackCleanedUpDisk()579 	bool GetUnpackCleanedUpDisk() { return m_unpackCleanedUpDisk; }
SetUnpackCleanedUpDisk(bool unpackCleanedUpDisk)580 	void SetUnpackCleanedUpDisk(bool unpackCleanedUpDisk) { m_unpackCleanedUpDisk = unpackCleanedUpDisk; }
GetAddUrlPaused()581 	bool GetAddUrlPaused() { return m_addUrlPaused; }
SetAddUrlPaused(bool addUrlPaused)582 	void SetAddUrlPaused(bool addUrlPaused) { m_addUrlPaused = addUrlPaused; }
GetFileList()583 	FileList* GetFileList() { return &m_fileList; }
GetParameters()584 	NzbParameterList* GetParameters() { return &m_ppParameters; }
GetScriptStatuses()585 	ScriptStatusList* GetScriptStatuses() { return &m_scriptStatuses; }
GetServerStats()586 	ServerStatList* GetServerStats() { return &m_serverStats; }
GetCurrentServerStats()587 	ServerStatList* GetCurrentServerStats() { return &m_currentServerStats; }
588 	int CalcHealth();
589 	int CalcCriticalHealth(bool allowEstimation);
GetDupeKey()590 	const char* GetDupeKey() { return m_dupeKey; }
SetDupeKey(const char * dupeKey)591 	void SetDupeKey(const char* dupeKey) { m_dupeKey = dupeKey ? dupeKey : ""; }
GetDupeScore()592 	int GetDupeScore() { return m_dupeScore; }
SetDupeScore(int dupeScore)593 	void SetDupeScore(int dupeScore) { m_dupeScore = dupeScore; }
GetDupeMode()594 	EDupeMode GetDupeMode() { return m_dupeMode; }
SetDupeMode(EDupeMode dupeMode)595 	void SetDupeMode(EDupeMode dupeMode) { m_dupeMode = dupeMode; }
GetDupeHint()596 	EDupeHint GetDupeHint() { return m_dupeHint; }
SetDupeHint(EDupeHint dupeHint)597 	void SetDupeHint(EDupeHint dupeHint) { m_dupeHint = dupeHint; }
GetFullContentHash()598 	uint32 GetFullContentHash() { return m_fullContentHash; }
SetFullContentHash(uint32 fullContentHash)599 	void SetFullContentHash(uint32 fullContentHash) { m_fullContentHash = fullContentHash; }
GetFilteredContentHash()600 	uint32 GetFilteredContentHash() { return m_filteredContentHash; }
SetFilteredContentHash(uint32 filteredContentHash)601 	void SetFilteredContentHash(uint32 filteredContentHash) { m_filteredContentHash = filteredContentHash; }
GetDownloadedSize()602 	int64 GetDownloadedSize() { return m_downloadedSize; }
SetDownloadedSize(int64 downloadedSize)603 	void SetDownloadedSize(int64 downloadedSize) { m_downloadedSize = downloadedSize; }
GetDownloadSec()604 	int GetDownloadSec() { return m_downloadSec; }
SetDownloadSec(int downloadSec)605 	void SetDownloadSec(int downloadSec) { m_downloadSec = downloadSec; }
GetPostTotalSec()606 	int GetPostTotalSec() { return m_postTotalSec; }
SetPostTotalSec(int postTotalSec)607 	void SetPostTotalSec(int postTotalSec) { m_postTotalSec = postTotalSec; }
GetParSec()608 	int GetParSec() { return m_parSec; }
SetParSec(int parSec)609 	void SetParSec(int parSec) { m_parSec = parSec; }
GetRepairSec()610 	int GetRepairSec() { return m_repairSec; }
SetRepairSec(int repairSec)611 	void SetRepairSec(int repairSec) { m_repairSec = repairSec; }
GetUnpackSec()612 	int GetUnpackSec() { return m_unpackSec; }
SetUnpackSec(int unpackSec)613 	void SetUnpackSec(int unpackSec) { m_unpackSec = unpackSec; }
GetDownloadStartTime()614 	time_t GetDownloadStartTime() { return m_downloadStartTime; }
SetDownloadStartTime(time_t downloadStartTime)615 	void SetDownloadStartTime(time_t downloadStartTime) { m_downloadStartTime = downloadStartTime; }
GetChanged()616 	bool GetChanged() { return m_changed; }
SetChanged(bool changed)617 	void SetChanged(bool changed) { m_changed = changed; }
SetReprocess(bool reprocess)618 	void SetReprocess(bool reprocess) { m_reprocess = reprocess; }
GetReprocess()619 	bool GetReprocess() { return m_reprocess; }
GetQueueScriptTime()620 	time_t GetQueueScriptTime() { return m_queueScriptTime; }
SetQueueScriptTime(time_t queueScriptTime)621 	void SetQueueScriptTime(time_t queueScriptTime) { m_queueScriptTime = queueScriptTime; }
SetParFull(bool parFull)622 	void SetParFull(bool parFull) { m_parFull = parFull; }
GetParFull()623 	bool GetParFull() { return m_parFull; }
GetFeedId()624 	int GetFeedId() { return m_feedId; }
SetFeedId(int feedId)625 	void SetFeedId(int feedId) { m_feedId = feedId; }
626 	void MoveFileList(NzbInfo* srcNzbInfo);
627 	void UpdateMinMaxTime();
GetPostInfo()628 	PostInfo* GetPostInfo() { return m_postInfo.get(); }
629 	void EnterPostProcess();
630 	void LeavePostProcess();
631 	bool IsDupeSuccess();
632 	const char* MakeTextStatus(bool ignoreScriptStatus);
633 	void AddMessage(Message::EKind kind, const char* text, bool print = true);
634 	void PrintMessage(Message::EKind kind, const char* format, ...) PRINTF_SYNTAX(3);
GetMessageCount()635 	int GetMessageCount() { return m_messageCount; }
SetMessageCount(int messageCount)636 	void SetMessageCount(int messageCount) { m_messageCount = messageCount; }
GetCachedMessageCount()637 	int GetCachedMessageCount() { return m_cachedMessageCount; }
GuardCachedMessages()638 	GuardedMessageList GuardCachedMessages() { return GuardedMessageList(&m_messages, &m_logMutex); }
GetAllFirst()639 	bool GetAllFirst() { return m_allFirst; }
SetAllFirst(bool allFirst)640 	void SetAllFirst(bool allFirst) { m_allFirst = allFirst; }
GetWaitingPar()641 	bool GetWaitingPar() { return m_waitingPar; }
SetWaitingPar(bool waitingPar)642 	void SetWaitingPar(bool waitingPar) { m_waitingPar = waitingPar; }
GetLoadingPar()643 	bool GetLoadingPar() { return m_loadingPar; }
SetLoadingPar(bool loadingPar)644 	void SetLoadingPar(bool loadingPar) { m_loadingPar = loadingPar; }
GetUnpackThread()645 	Thread* GetUnpackThread() { return m_unpackThread; }
SetUnpackThread(Thread * unpackThread)646 	void SetUnpackThread(Thread* unpackThread) { m_unpackThread = unpackThread; }
647 	void UpdateCurrentStats();
648 	void UpdateCompletedStats(FileInfo* fileInfo);
649 	void UpdateDeletedStats(FileInfo* fileInfo);
650 	bool IsDownloadCompleted(bool ignorePausedPars);
651 
652 	static const int FORCE_PRIORITY = 900;
653 
654 private:
655 	int m_id = ++m_idGen;
656 	EKind m_kind = nkNzb;
657 	CString m_url = "";
658 	CString m_filename = "";
659 	CString m_name;
660 	CString m_destDir = "";
661 	CString m_finalDir = "";
662 	CString m_category = "";
663 	int m_fileCount = 0;
664 	int m_parkedFileCount = 0;
665 	int64 m_size = 0;
666 	int64 m_remainingSize = 0;
667 	int m_pausedFileCount = 0;
668 	int64 m_pausedSize = 0;
669 	int m_remainingParCount = 0;
670 	int m_activeDownloads = 0;
671 	int64 m_successSize = 0;
672 	int64 m_failedSize = 0;
673 	int64 m_currentSuccessSize = 0;
674 	int64 m_currentFailedSize = 0;
675 	int64 m_parSize = 0;
676 	int64 m_parSuccessSize = 0;
677 	int64 m_parFailedSize = 0;
678 	int64 m_parCurrentSuccessSize = 0;
679 	int64 m_parCurrentFailedSize = 0;
680 	int m_totalArticles = 0;
681 	int m_successArticles = 0;
682 	int m_failedArticles = 0;
683 	int m_currentSuccessArticles = 0;
684 	int m_currentFailedArticles = 0;
685 	time_t m_minTime = 0;
686 	time_t m_maxTime = 0;
687 	int m_priority = 0;
688 	int m_extraPriority = 0;
689 	CompletedFileList m_completedFiles;
690 	EDirectRenameStatus m_directRenameStatus = tsNone;
691 	EPostRenameStatus m_parRenameStatus = rsNone;
692 	EPostRenameStatus m_rarRenameStatus = rsNone;
693 	EParStatus m_parStatus = psNone;
694 	EDirectUnpackStatus m_directUnpackStatus = nsNone;
695 	EPostUnpackStatus m_unpackStatus = usNone;
696 	ECleanupStatus m_cleanupStatus = csNone;
697 	EMoveStatus m_moveStatus = msNone;
698 	EDeleteStatus m_deleteStatus = dsNone;
699 	EMarkStatus m_markStatus = ksNone;
700 	EUrlStatus m_urlStatus = lsNone;
701 	int m_extraParBlocks = 0;
702 	bool m_addUrlPaused = false;
703 	bool m_deletePaused = false;
704 	bool m_manyDupeFiles = false;
705 	CString m_queuedFilename = "";
706 	bool m_deleting = false;
707 	bool m_parking = false;
708 	bool m_avoidHistory = false;
709 	bool m_healthPaused = false;
710 	bool m_parManual = false;
711 	bool m_cleanupDisk = false;
712 	bool m_unpackCleanedUpDisk = false;
713 	CString m_dupeKey = "";
714 	int m_dupeScore = 0;
715 	EDupeMode m_dupeMode = dmScore;
716 	EDupeHint m_dupeHint = dhNone;
717 	uint32 m_fullContentHash = 0;
718 	uint32 m_filteredContentHash = 0;
719 	FileList m_fileList;
720 	NzbParameterList m_ppParameters;
721 	ScriptStatusList m_scriptStatuses;
722 	ServerStatList m_serverStats;
723 	ServerStatList m_currentServerStats;
724 	Mutex m_logMutex;
725 	MessageList m_messages;
726 	int m_idMessageGen = 0;
727 	std::unique_ptr<PostInfo> m_postInfo;
728 	int64 m_downloadedSize = 0;
729 	time_t m_downloadStartTime = 0;
730 	int m_downloadStartSec = 0;
731 	int m_downloadSec = 0;
732 	int m_postTotalSec = 0;
733 	int m_parSec = 0;
734 	int m_repairSec = 0;
735 	int m_unpackSec = 0;
736 	bool m_reprocess = false;
737 	bool m_changed = false;
738 	time_t m_queueScriptTime = 0;
739 	bool m_parFull = false;
740 	int m_messageCount = 0;
741 	int m_cachedMessageCount = 0;
742 	int m_feedId = 0;
743 	bool m_allFirst = false;
744 	bool m_waitingPar = false;
745 	bool m_loadingPar = false;
746 	Thread* m_unpackThread = nullptr;
747 
748 	static int m_idGen;
749 	static int m_idMax;
750 
751 	void ClearMessages();
752 
753 	friend class DupInfo;
754 };
755 
756 typedef UniqueDeque<NzbInfo> NzbList;
757 typedef std::vector<NzbInfo*> RawNzbList;
758 
759 class PostInfo
760 {
761 public:
762 	enum EStage
763 	{
764 		ptQueued,
765 		ptLoadingPars,
766 		ptVerifyingSources,
767 		ptRepairing,
768 		ptVerifyingRepaired,
769 		ptParRenaming,
770 		ptRarRenaming,
771 		ptUnpacking,
772 		ptCleaningUp,
773 		ptMoving,
774 		ptExecutingScript,
775 		ptFinished
776 	};
777 
778 	typedef std::vector<CString> ParredFiles;
779 	typedef std::vector<CString> ExtractedArchives;
780 
GetNzbInfo()781 	NzbInfo* GetNzbInfo() { return m_nzbInfo; }
SetNzbInfo(NzbInfo * nzbInfo)782 	void SetNzbInfo(NzbInfo* nzbInfo) { m_nzbInfo = nzbInfo; }
GetStage()783 	EStage GetStage() { return m_stage; }
SetStage(EStage stage)784 	void SetStage(EStage stage) { m_stage = stage; }
SetProgressLabel(const char * progressLabel)785 	void SetProgressLabel(const char* progressLabel) { m_progressLabel = progressLabel; }
GetProgressLabel()786 	const char* GetProgressLabel() { return m_progressLabel; }
GetFileProgress()787 	int GetFileProgress() { return m_fileProgress; }
SetFileProgress(int fileProgress)788 	void SetFileProgress(int fileProgress) { m_fileProgress = fileProgress; }
GetStageProgress()789 	int GetStageProgress() { return m_stageProgress; }
SetStageProgress(int stageProgress)790 	void SetStageProgress(int stageProgress) { m_stageProgress = stageProgress; }
GetStartTime()791 	time_t GetStartTime() { return m_startTime; }
SetStartTime(time_t startTime)792 	void SetStartTime(time_t startTime) { m_startTime = startTime; }
GetStageTime()793 	time_t GetStageTime() { return m_stageTime; }
SetStageTime(time_t stageTime)794 	void SetStageTime(time_t stageTime) { m_stageTime = stageTime; }
GetWorking()795 	bool GetWorking() { return m_working; }
SetWorking(bool working)796 	void SetWorking(bool working) { m_working = working; }
GetDeleted()797 	bool GetDeleted() { return m_deleted; }
SetDeleted(bool deleted)798 	void SetDeleted(bool deleted) { m_deleted = deleted; }
GetRequestParCheck()799 	bool GetRequestParCheck() { return m_requestParCheck; }
SetRequestParCheck(bool requestParCheck)800 	void SetRequestParCheck(bool requestParCheck) { m_requestParCheck = requestParCheck; }
GetForceParFull()801 	bool GetForceParFull() { return m_forceParFull; }
SetForceParFull(bool forceParFull)802 	void SetForceParFull(bool forceParFull) { m_forceParFull = forceParFull; }
GetForceRepair()803 	bool GetForceRepair() { return m_forceRepair; }
SetForceRepair(bool forceRepair)804 	void SetForceRepair(bool forceRepair) { m_forceRepair = forceRepair; }
GetParRepaired()805 	bool GetParRepaired() { return m_parRepaired; }
SetParRepaired(bool parRepaired)806 	void SetParRepaired(bool parRepaired) { m_parRepaired = parRepaired; }
GetUnpackTried()807 	bool GetUnpackTried() { return m_unpackTried; }
SetUnpackTried(bool unpackTried)808 	void SetUnpackTried(bool unpackTried) { m_unpackTried = unpackTried; }
GetPassListTried()809 	bool GetPassListTried() { return m_passListTried; }
SetPassListTried(bool passListTried)810 	void SetPassListTried(bool passListTried) { m_passListTried = passListTried; }
GetLastUnpackStatus()811 	int GetLastUnpackStatus() { return m_lastUnpackStatus; }
SetLastUnpackStatus(int unpackStatus)812 	void SetLastUnpackStatus(int unpackStatus) { m_lastUnpackStatus = unpackStatus; }
GetNeedParCheck()813 	bool GetNeedParCheck() { return m_needParCheck; }
SetNeedParCheck(bool needParCheck)814 	void SetNeedParCheck(bool needParCheck) { m_needParCheck = needParCheck; }
GetPostThread()815 	Thread* GetPostThread() { return m_postThread; }
SetPostThread(Thread * postThread)816 	void SetPostThread(Thread* postThread) { m_postThread = postThread; }
GetParredFiles()817 	ParredFiles* GetParredFiles() { return &m_parredFiles; }
GetExtractedArchives()818 	ExtractedArchives* GetExtractedArchives() { return &m_extractedArchives; }
819 
820 private:
821 	NzbInfo* m_nzbInfo = nullptr;
822 	bool m_working = false;
823 	bool m_deleted = false;
824 	bool m_requestParCheck = false;
825 	bool m_forceParFull = false;
826 	bool m_forceRepair = false;
827 	bool m_parRepaired = false;
828 	bool m_unpackTried = false;
829 	bool m_passListTried = false;
830 	int m_lastUnpackStatus = 0;
831 	bool m_needParCheck = false;
832 	EStage m_stage = ptQueued;
833 	CString m_progressLabel = "";
834 	int m_fileProgress = 0;
835 	int m_stageProgress = 0;
836 	time_t m_startTime = 0;
837 	time_t m_stageTime = 0;
838 	Thread* m_postThread = nullptr;
839 	ParredFiles m_parredFiles;
840 	ExtractedArchives m_extractedArchives;
841 };
842 
843 typedef std::vector<int> IdList;
844 
845 typedef std::vector<CString> NameList;
846 
847 class DupInfo
848 {
849 public:
850 	enum EStatus
851 	{
852 		dsUndefined,
853 		dsSuccess,
854 		dsFailed,
855 		dsDeleted,
856 		dsDupe,
857 		dsBad,
858 		dsGood
859 	};
860 
GetId()861 	int GetId() { return m_id; }
862 	void SetId(int id);
GetName()863 	const char* GetName() { return m_name; }
SetName(const char * name)864 	void SetName(const char* name) { m_name = name; }
GetDupeKey()865 	const char* GetDupeKey() { return m_dupeKey; }
SetDupeKey(const char * dupeKey)866 	void SetDupeKey(const char* dupeKey) { m_dupeKey = dupeKey; }
GetDupeScore()867 	int GetDupeScore() { return m_dupeScore; }
SetDupeScore(int dupeScore)868 	void SetDupeScore(int dupeScore) { m_dupeScore = dupeScore; }
GetDupeMode()869 	EDupeMode GetDupeMode() { return m_dupeMode; }
SetDupeMode(EDupeMode dupeMode)870 	void SetDupeMode(EDupeMode dupeMode) { m_dupeMode = dupeMode; }
GetSize()871 	int64 GetSize() { return m_size; }
SetSize(int64 size)872 	void SetSize(int64 size) { m_size = size; }
GetFullContentHash()873 	uint32 GetFullContentHash() { return m_fullContentHash; }
SetFullContentHash(uint32 fullContentHash)874 	void SetFullContentHash(uint32 fullContentHash) { m_fullContentHash = fullContentHash; }
GetFilteredContentHash()875 	uint32 GetFilteredContentHash() { return m_filteredContentHash; }
SetFilteredContentHash(uint32 filteredContentHash)876 	void SetFilteredContentHash(uint32 filteredContentHash) { m_filteredContentHash = filteredContentHash; }
GetStatus()877 	EStatus GetStatus() { return m_status; }
SetStatus(EStatus Status)878 	void SetStatus(EStatus Status) { m_status = Status; }
879 
880 private:
881 	int m_id = 0;
882 	CString m_name;
883 	CString m_dupeKey;
884 	int m_dupeScore = 0;
885 	EDupeMode m_dupeMode = dmScore;
886 	int64 m_size = 0;
887 	uint32 m_fullContentHash = 0;
888 	uint32 m_filteredContentHash = 0;
889 	EStatus m_status = dsUndefined;
890 };
891 
892 class HistoryInfo
893 {
894 public:
895 	enum EKind
896 	{
897 		hkUnknown,
898 		hkNzb,
899 		hkUrl,
900 		hkDup
901 	};
902 
HistoryInfo(std::unique_ptr<NzbInfo> nzbInfo)903 	HistoryInfo(std::unique_ptr<NzbInfo> nzbInfo) : m_info(nzbInfo.release()),
904 		m_kind(GetNzbInfo()->GetKind() == NzbInfo::nkNzb ? hkNzb : hkUrl) {}
HistoryInfo(std::unique_ptr<DupInfo> dupInfo)905 	HistoryInfo(std::unique_ptr<DupInfo> dupInfo) : m_info(dupInfo.release()), m_kind(hkDup) {}
906 	~HistoryInfo();
GetKind()907 	EKind GetKind() { return m_kind; }
908 	int GetId();
GetNzbInfo()909 	NzbInfo* GetNzbInfo() { return (NzbInfo*)m_info; }
GetDupInfo()910 	DupInfo* GetDupInfo() { return (DupInfo*)m_info; }
DiscardNzbInfo()911 	void DiscardNzbInfo() { m_info = nullptr; }
GetTime()912 	time_t GetTime() { return m_time; }
SetTime(time_t time)913 	void SetTime(time_t time) { m_time = time; }
914 	const char* GetName();
915 
916 private:
917 	void* m_info;
918 	EKind m_kind;
919 	time_t m_time = 0;
920 };
921 
922 typedef UniqueDeque<HistoryInfo> HistoryList;
923 
924 typedef GuardedPtr<DownloadQueue> GuardedDownloadQueue;
925 
926 class DownloadQueue : public Subject
927 {
928 public:
929 	enum EAspectAction
930 	{
931 		eaNzbFound,
932 		eaNzbAdded,
933 		eaNzbDeleted,
934 		eaNzbNamed,
935 		eaNzbReturned,
936 		eaFileCompleted,
937 		eaFileDeleted,
938 		eaUrlFound,
939 		eaUrlAdded,
940 		eaUrlDeleted,
941 		eaUrlCompleted,
942 		eaUrlFailed,
943 		eaUrlReturned
944 	};
945 
946 	struct Aspect
947 	{
948 		EAspectAction action;
949 		DownloadQueue* downloadQueue;
950 		NzbInfo* nzbInfo;
951 		FileInfo* fileInfo;
952 	};
953 
954 	enum EEditAction
955 	{
956 		eaFileMoveOffset = 1, // move files to m_iOffset relative to the current position in download-queue
957 		eaFileMoveTop, // move files to the top of download-queue
958 		eaFileMoveBottom, // move files to the bottom of download-queue
959 		eaFilePause, // pause files
960 		eaFileResume, // resume (unpause) files
961 		eaFileDelete, // delete files
962 		eaFilePauseAllPars, // pause only (all) pars (does not affect other files)
963 		eaFilePauseExtraPars, // pause (almost all) pars, except main par-file (does not affect other files)
964 		eaFileReorder, // set file order
965 		eaFileSplit, // split - create new group from selected files
966 		eaGroupMoveOffset, // move group to offset relative to the current position in download-queue
967 		eaGroupMoveTop, // move group to the top of download-queue
968 		eaGroupMoveBottom, // move group to the bottom of download-queue
969 		eaGroupMoveBefore, // move group to a certain position
970 		eaGroupMoveAfter, // move group to a certain position
971 		eaGroupPause, // pause group
972 		eaGroupResume, // resume (unpause) group
973 		eaGroupDelete, // delete group and put to history, delete already downloaded files
974 		eaGroupParkDelete, // delete group and put to history, keep already downloaded files
975 		eaGroupDupeDelete, // delete group, put to history and mark as duplicate, delete already downloaded files
976 		eaGroupFinalDelete, // delete group without adding to history, delete already downloaded files
977 		eaGroupPauseAllPars, // pause only (all) pars (does not affect other files) in group
978 		eaGroupPauseExtraPars, // pause only (almost all) pars in group, except main par-file (does not affect other files)
979 		eaGroupSetPriority, // set priority for groups
980 		eaGroupSetCategory, // set or change category for a group
981 		eaGroupApplyCategory, // set or change category for a group and reassign pp-params according to category settings
982 		eaGroupMerge, // merge groups
983 		eaGroupSetParameter, // set post-process parameter for group
984 		eaGroupSetName, // set group name (rename group)
985 		eaGroupSetDupeKey, // set duplicate key
986 		eaGroupSetDupeScore, // set duplicate score
987 		eaGroupSetDupeMode, // set duplicate mode
988 		eaGroupSort, // sort groups
989 		eaGroupSortFiles, // sort files for optimal download order
990 		eaPostDelete, // cancel post-processing
991 		eaHistoryDelete, // hide history-item
992 		eaHistoryFinalDelete, // delete history-item
993 		eaHistoryReturn, // move history-item back to download queue
994 		eaHistoryProcess, // move history-item back to download queue and start postprocessing
995 		eaHistoryRedownload, // move history-item back to download queue for full redownload
996 		eaHistoryRetryFailed, // move history-item back to download queue for redownload of failed articles
997 		eaHistorySetParameter, // set post-process parameter for history-item
998 		eaHistorySetDupeKey, // set duplicate key
999 		eaHistorySetDupeScore, // set duplicate score
1000 		eaHistorySetDupeMode, // set duplicate mode
1001 		eaHistorySetDupeBackup, // set duplicate backup flag
1002 		eaHistoryMarkBad, // mark history-item as bad (and download other duplicate)
1003 		eaHistoryMarkGood, // mark history-item as good (and push it into dup-history)
1004 		eaHistoryMarkSuccess, // mark history-item as success (and do nothing more)
1005 		eaHistorySetCategory, // set or change category for history-item
1006 		eaHistorySetName // set history-item name (rename)
1007 	};
1008 
1009 	enum EMatchMode
1010 	{
1011 		mmId = 1,
1012 		mmName,
1013 		mmRegEx
1014 	};
1015 
IsLoaded()1016 	static bool IsLoaded() { return g_Loaded; }
Guard()1017 	static GuardedDownloadQueue Guard() { return GuardedDownloadQueue(g_DownloadQueue, &g_DownloadQueue->m_lockMutex); }
GetQueue()1018 	NzbList* GetQueue() { return &m_queue; }
GetHistory()1019 	HistoryList* GetHistory() { return &m_history; }
1020 	virtual bool EditEntry(int ID, EEditAction action, const char* args) = 0;
1021 	virtual bool EditList(IdList* idList, NameList* nameList, EMatchMode matchMode, EEditAction action, const char* args) = 0;
1022 	virtual void HistoryChanged() = 0;
1023 	virtual void Save() = 0;
1024 	virtual void SaveChanged() = 0;
1025 	void CalcRemainingSize(int64* remaining, int64* remainingForced);
1026 
1027 protected:
DownloadQueue()1028 	DownloadQueue() {}
Init(DownloadQueue * globalInstance)1029 	static void Init(DownloadQueue* globalInstance) { g_DownloadQueue = globalInstance; }
Final()1030 	static void Final() { g_DownloadQueue = nullptr; }
Loaded()1031 	static void Loaded() { g_Loaded = true; }
1032 
1033 private:
1034 	NzbList m_queue;
1035 	HistoryList m_history;
1036 	Mutex m_lockMutex;
1037 
1038 	static DownloadQueue* g_DownloadQueue;
1039 	static bool g_Loaded;
1040 };
1041 
1042 #endif
1043