mirror of
https://github.com/nzbget/nzbget.git
synced 2025-12-23 22:27:45 -05:00
- added link to http://nzbget.net; - replaced FSF Post address with a web link; - removed unusable subversion-tags; - updated year.
950 lines
26 KiB
C++
950 lines
26 KiB
C++
/*
|
|
* This file is part of nzbget. See <http://nzbget.net>.
|
|
*
|
|
* Copyright (C) 2007-2016 Andrey Prygunkov <hugbug@users.sourceforge.net>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
|
|
#include "nzbget.h"
|
|
#include "CommandLineParser.h"
|
|
#include "Log.h"
|
|
#include "MessageBase.h"
|
|
#include "DownloadInfo.h"
|
|
#include "FileSystem.h"
|
|
#include "Util.h"
|
|
|
|
#ifdef HAVE_GETOPT_LONG
|
|
static struct option long_options[] =
|
|
{
|
|
{"help", no_argument, 0, 'h'},
|
|
{"configfile", required_argument, 0, 'c'},
|
|
{"noconfigfile", no_argument, 0, 'n'},
|
|
{"printconfig", no_argument, 0, 'p'},
|
|
{"server", no_argument, 0, 's' },
|
|
{"daemon", no_argument, 0, 'D' },
|
|
{"version", no_argument, 0, 'v'},
|
|
{"serverversion", no_argument, 0, 'V'},
|
|
{"option", required_argument, 0, 'o'},
|
|
{"append", no_argument, 0, 'A'},
|
|
{"list", no_argument, 0, 'L'},
|
|
{"pause", no_argument, 0, 'P'},
|
|
{"unpause", no_argument, 0, 'U'},
|
|
{"rate", required_argument, 0, 'R'},
|
|
{"system", no_argument, 0, 'B'},
|
|
{"log", required_argument, 0, 'G'},
|
|
{"top", no_argument, 0, 'T'},
|
|
{"edit", required_argument, 0, 'E'},
|
|
{"connect", no_argument, 0, 'C'},
|
|
{"quit", no_argument, 0, 'Q'},
|
|
{"reload", no_argument, 0, 'O'},
|
|
{"write", required_argument, 0, 'W'},
|
|
{"category", required_argument, 0, 'K'},
|
|
{"scan", no_argument, 0, 'S'},
|
|
{0, 0, 0, 0}
|
|
};
|
|
#endif
|
|
|
|
static char short_options[] = "c:hno:psvAB:DCE:G:K:LPR:STUQOVW:";
|
|
|
|
|
|
CommandLineParser::CommandLineParser(int argc, const char* argv[])
|
|
{
|
|
InitCommandLine(argc, argv);
|
|
|
|
if (argc == 1)
|
|
{
|
|
m_printUsage = true;
|
|
return;
|
|
}
|
|
|
|
if (!m_printOptions && !m_printUsage && !m_printVersion)
|
|
{
|
|
InitFileArg(argc, argv);
|
|
}
|
|
}
|
|
|
|
void CommandLineParser::InitCommandLine(int argc, const char* const_argv[])
|
|
{
|
|
m_clientOperation = opClientNoOperation; // default
|
|
|
|
std::vector<CString> argv;
|
|
argv.reserve(argc);
|
|
for (int i = 0; i < argc; i++)
|
|
{
|
|
argv.emplace_back(const_argv[i]);
|
|
}
|
|
|
|
// reset getopt
|
|
optind = 0;
|
|
|
|
while (true)
|
|
{
|
|
int c;
|
|
|
|
#ifdef HAVE_GETOPT_LONG
|
|
int option_index = 0;
|
|
c = getopt_long(argc, (char**)argv.data(), short_options, long_options, &option_index);
|
|
#else
|
|
c = getopt(argc, (char**)argv.data(), short_options);
|
|
#endif
|
|
|
|
if (c == -1) break;
|
|
|
|
switch (c)
|
|
{
|
|
case 'c':
|
|
m_configFilename = optarg;
|
|
break;
|
|
case 'n':
|
|
m_configFilename = nullptr;
|
|
m_noConfig = true;
|
|
break;
|
|
case 'h':
|
|
m_printUsage = true;
|
|
return;
|
|
case 'v':
|
|
m_printVersion = true;
|
|
return;
|
|
case 'p':
|
|
m_printOptions = true;
|
|
break;
|
|
case 'o':
|
|
m_optionList.push_back(optarg);
|
|
break;
|
|
case 's':
|
|
m_serverMode = true;
|
|
break;
|
|
case 'D':
|
|
m_serverMode = true;
|
|
m_daemonMode = true;
|
|
break;
|
|
case 'A':
|
|
m_clientOperation = opClientRequestDownload;
|
|
|
|
while (true)
|
|
{
|
|
optind++;
|
|
optarg = optind > argc ? nullptr : (char*)argv[optind-1];
|
|
if (optarg && (!strcasecmp(optarg, "F") || !strcasecmp(optarg, "U")))
|
|
{
|
|
// option ignored (but kept for compatibility)
|
|
}
|
|
else if (optarg && !strcasecmp(optarg, "T"))
|
|
{
|
|
m_addTop = true;
|
|
}
|
|
else if (optarg && !strcasecmp(optarg, "P"))
|
|
{
|
|
m_addPaused = true;
|
|
}
|
|
else if (optarg && !strcasecmp(optarg, "I"))
|
|
{
|
|
optind++;
|
|
if (optind > argc)
|
|
{
|
|
ReportError("Could not parse value of option 'A'");
|
|
return;
|
|
}
|
|
m_addPriority = atoi(argv[optind-1]);
|
|
}
|
|
else if (optarg && !strcasecmp(optarg, "C"))
|
|
{
|
|
optind++;
|
|
if (optind > argc)
|
|
{
|
|
ReportError("Could not parse value of option 'A'");
|
|
return;
|
|
}
|
|
m_addCategory = std::move(argv[optind-1]);
|
|
}
|
|
else if (optarg && !strcasecmp(optarg, "N"))
|
|
{
|
|
optind++;
|
|
if (optind > argc)
|
|
{
|
|
ReportError("Could not parse value of option 'A'");
|
|
return;
|
|
}
|
|
m_addNzbFilename = std::move(argv[optind-1]);
|
|
}
|
|
else if (optarg && !strcasecmp(optarg, "DK"))
|
|
{
|
|
optind++;
|
|
if (optind > argc)
|
|
{
|
|
ReportError("Could not parse value of option 'A'");
|
|
return;
|
|
}
|
|
m_addDupeKey = std::move(argv[optind-1]);
|
|
}
|
|
else if (optarg && !strcasecmp(optarg, "DS"))
|
|
{
|
|
optind++;
|
|
if (optind > argc)
|
|
{
|
|
ReportError("Could not parse value of option 'A'");
|
|
return;
|
|
}
|
|
m_addDupeScore = atoi(argv[optind-1]);
|
|
}
|
|
else if (optarg && !strcasecmp(optarg, "DM"))
|
|
{
|
|
optind++;
|
|
if (optind > argc)
|
|
{
|
|
ReportError("Could not parse value of option 'A'");
|
|
return;
|
|
}
|
|
|
|
const char* dupeMode = argv[optind-1];
|
|
if (!strcasecmp(dupeMode, "score"))
|
|
{
|
|
m_addDupeMode = dmScore;
|
|
}
|
|
else if (!strcasecmp(dupeMode, "all"))
|
|
{
|
|
m_addDupeMode = dmAll;
|
|
}
|
|
else if (!strcasecmp(dupeMode, "force"))
|
|
{
|
|
m_addDupeMode = dmForce;
|
|
}
|
|
else
|
|
{
|
|
ReportError("Could not parse value of option 'A'");
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
optind--;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case 'L':
|
|
optind++;
|
|
optarg = optind > argc ? nullptr : (char*)argv[optind-1];
|
|
if (!optarg || !strncmp(optarg, "-", 1))
|
|
{
|
|
m_clientOperation = opClientRequestListFiles;
|
|
optind--;
|
|
}
|
|
else if (!strcasecmp(optarg, "F") || !strcasecmp(optarg, "FR"))
|
|
{
|
|
m_clientOperation = opClientRequestListFiles;
|
|
}
|
|
else if (!strcasecmp(optarg, "G") || !strcasecmp(optarg, "GR"))
|
|
{
|
|
m_clientOperation = opClientRequestListGroups;
|
|
}
|
|
else if (!strcasecmp(optarg, "O"))
|
|
{
|
|
m_clientOperation = opClientRequestPostQueue;
|
|
}
|
|
else if (!strcasecmp(optarg, "S"))
|
|
{
|
|
m_clientOperation = opClientRequestListStatus;
|
|
}
|
|
else if (!strcasecmp(optarg, "H"))
|
|
{
|
|
m_clientOperation = opClientRequestHistory;
|
|
}
|
|
else if (!strcasecmp(optarg, "HA"))
|
|
{
|
|
m_clientOperation = opClientRequestHistoryAll;
|
|
}
|
|
else
|
|
{
|
|
ReportError("Could not parse value of option 'L'");
|
|
return;
|
|
}
|
|
|
|
if (optarg && (!strcasecmp(optarg, "FR") || !strcasecmp(optarg, "GR")))
|
|
{
|
|
m_matchMode = mmRegEx;
|
|
|
|
optind++;
|
|
if (optind > argc)
|
|
{
|
|
ReportError("Could not parse value of option 'L'");
|
|
return;
|
|
}
|
|
m_editQueueText = std::move(argv[optind-1]);
|
|
}
|
|
break;
|
|
case 'P':
|
|
case 'U':
|
|
optind++;
|
|
optarg = optind > argc ? nullptr : (char*)argv[optind-1];
|
|
if (!optarg || !strncmp(optarg, "-", 1))
|
|
{
|
|
m_clientOperation = c == 'P' ? opClientRequestDownloadPause : opClientRequestDownloadUnpause;
|
|
optind--;
|
|
}
|
|
else if (!strcasecmp(optarg, "D"))
|
|
{
|
|
m_clientOperation = c == 'P' ? opClientRequestDownloadPause : opClientRequestDownloadUnpause;
|
|
}
|
|
else if (!strcasecmp(optarg, "O"))
|
|
{
|
|
m_clientOperation = c == 'P' ? opClientRequestPostPause : opClientRequestPostUnpause;
|
|
}
|
|
else if (!strcasecmp(optarg, "S"))
|
|
{
|
|
m_clientOperation = c == 'P' ? opClientRequestScanPause : opClientRequestScanUnpause;
|
|
}
|
|
else
|
|
{
|
|
ReportError(c == 'P' ? "Could not parse value of option 'P'\n" : "Could not parse value of option 'U'");
|
|
return;
|
|
}
|
|
break;
|
|
case 'R':
|
|
m_clientOperation = opClientRequestSetRate;
|
|
m_setRate = (int)(atof(optarg)*1024);
|
|
break;
|
|
case 'B':
|
|
if (!strcasecmp(optarg, "dump"))
|
|
{
|
|
m_clientOperation = opClientRequestDumpDebug;
|
|
}
|
|
else if (!strcasecmp(optarg, "trace"))
|
|
{
|
|
m_testBacktrace = true;
|
|
}
|
|
else if (!strcasecmp(optarg, "webget"))
|
|
{
|
|
m_webGet = true;
|
|
optind++;
|
|
if (optind > argc)
|
|
{
|
|
ReportError("Could not parse value of option 'B'");
|
|
return;
|
|
}
|
|
optarg = argv[optind-1];
|
|
m_webGetFilename = optarg;
|
|
}
|
|
else if (!strcasecmp(optarg, "verify"))
|
|
{
|
|
m_sigVerify = true;
|
|
optind++;
|
|
if (optind > argc)
|
|
{
|
|
ReportError("Could not parse value of option 'B'");
|
|
return;
|
|
}
|
|
optarg = argv[optind-1];
|
|
m_pubKeyFilename = optarg;
|
|
|
|
optind++;
|
|
if (optind > argc)
|
|
{
|
|
ReportError("Could not parse value of option 'B'");
|
|
return;
|
|
}
|
|
optarg = argv[optind-1];
|
|
m_sigFilename = optarg;
|
|
}
|
|
else
|
|
{
|
|
ReportError("Could not parse value of option 'B'");
|
|
return;
|
|
}
|
|
break;
|
|
case 'G':
|
|
m_clientOperation = opClientRequestLog;
|
|
m_logLines = atoi(optarg);
|
|
if (m_logLines == 0)
|
|
{
|
|
ReportError("Could not parse value of option 'G'");
|
|
return;
|
|
}
|
|
break;
|
|
case 'T':
|
|
m_addTop = true;
|
|
break;
|
|
case 'C':
|
|
m_remoteClientMode = true;
|
|
break;
|
|
case 'E':
|
|
{
|
|
m_clientOperation = opClientRequestEditQueue;
|
|
bool group = !strcasecmp(optarg, "G") || !strcasecmp(optarg, "GN") || !strcasecmp(optarg, "GR");
|
|
bool file = !strcasecmp(optarg, "F") || !strcasecmp(optarg, "FN") || !strcasecmp(optarg, "FR");
|
|
if (!strcasecmp(optarg, "GN") || !strcasecmp(optarg, "FN"))
|
|
{
|
|
m_matchMode = mmName;
|
|
}
|
|
else if (!strcasecmp(optarg, "GR") || !strcasecmp(optarg, "FR"))
|
|
{
|
|
m_matchMode = mmRegEx;
|
|
}
|
|
else
|
|
{
|
|
m_matchMode = mmId;
|
|
};
|
|
bool post = !strcasecmp(optarg, "O");
|
|
bool history = !strcasecmp(optarg, "H");
|
|
if (group || file || post || history)
|
|
{
|
|
optind++;
|
|
if (optind > argc)
|
|
{
|
|
ReportError("Could not parse value of option 'E'");
|
|
return;
|
|
}
|
|
optarg = argv[optind-1];
|
|
}
|
|
|
|
if (post)
|
|
{
|
|
// edit-commands for post-processor-queue
|
|
if (!strcasecmp(optarg, "D"))
|
|
{
|
|
m_editQueueAction = DownloadQueue::eaPostDelete;
|
|
}
|
|
else
|
|
{
|
|
ReportError("Could not parse value of option 'E'");
|
|
return;
|
|
}
|
|
}
|
|
else if (history)
|
|
{
|
|
// edit-commands for history
|
|
if (!strcasecmp(optarg, "D"))
|
|
{
|
|
m_editQueueAction = DownloadQueue::eaHistoryDelete;
|
|
}
|
|
else if (!strcasecmp(optarg, "R"))
|
|
{
|
|
m_editQueueAction = DownloadQueue::eaHistoryReturn;
|
|
}
|
|
else if (!strcasecmp(optarg, "P"))
|
|
{
|
|
m_editQueueAction = DownloadQueue::eaHistoryProcess;
|
|
}
|
|
else if (!strcasecmp(optarg, "A"))
|
|
{
|
|
m_editQueueAction = DownloadQueue::eaHistoryRedownload;
|
|
}
|
|
else if (!strcasecmp(optarg, "O"))
|
|
{
|
|
m_editQueueAction = DownloadQueue::eaHistorySetParameter;
|
|
|
|
optind++;
|
|
if (optind > argc)
|
|
{
|
|
ReportError("Could not parse value of option 'E'");
|
|
return;
|
|
}
|
|
m_editQueueText = std::move(argv[optind-1]);
|
|
|
|
if (!strchr(m_editQueueText, '='))
|
|
{
|
|
ReportError("Could not parse value of option 'E'");
|
|
return;
|
|
}
|
|
}
|
|
else if (!strcasecmp(optarg, "B"))
|
|
{
|
|
m_editQueueAction = DownloadQueue::eaHistoryMarkBad;
|
|
}
|
|
else if (!strcasecmp(optarg, "G"))
|
|
{
|
|
m_editQueueAction = DownloadQueue::eaHistoryMarkGood;
|
|
}
|
|
else if (!strcasecmp(optarg, "S"))
|
|
{
|
|
m_editQueueAction = DownloadQueue::eaHistoryMarkSuccess;
|
|
}
|
|
else
|
|
{
|
|
ReportError("Could not parse value of option 'E'");
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// edit-commands for download-queue
|
|
if (!strcasecmp(optarg, "T"))
|
|
{
|
|
m_editQueueAction = group ? DownloadQueue::eaGroupMoveTop : DownloadQueue::eaFileMoveTop;
|
|
}
|
|
else if (!strcasecmp(optarg, "B"))
|
|
{
|
|
m_editQueueAction = group ? DownloadQueue::eaGroupMoveBottom : DownloadQueue::eaFileMoveBottom;
|
|
}
|
|
else if (!strcasecmp(optarg, "P"))
|
|
{
|
|
m_editQueueAction = group ? DownloadQueue::eaGroupPause : DownloadQueue::eaFilePause;
|
|
}
|
|
else if (!strcasecmp(optarg, "A"))
|
|
{
|
|
m_editQueueAction = group ? DownloadQueue::eaGroupPauseAllPars : DownloadQueue::eaFilePauseAllPars;
|
|
}
|
|
else if (!strcasecmp(optarg, "R"))
|
|
{
|
|
m_editQueueAction = group ? DownloadQueue::eaGroupPauseExtraPars : DownloadQueue::eaFilePauseExtraPars;
|
|
}
|
|
else if (!strcasecmp(optarg, "U"))
|
|
{
|
|
m_editQueueAction = group ? DownloadQueue::eaGroupResume : DownloadQueue::eaFileResume;
|
|
}
|
|
else if (!strcasecmp(optarg, "D"))
|
|
{
|
|
m_editQueueAction = group ? DownloadQueue::eaGroupDelete : DownloadQueue::eaFileDelete;
|
|
}
|
|
else if (!strcasecmp(optarg, "C") || !strcasecmp(optarg, "K") || !strcasecmp(optarg, "CP"))
|
|
{
|
|
// switch "K" is provided for compatibility with v. 0.8.0 and can be removed in future versions
|
|
if (!group)
|
|
{
|
|
ReportError("Category can be set only for groups");
|
|
return;
|
|
}
|
|
m_editQueueAction = !strcasecmp(optarg, "CP") ? DownloadQueue::eaGroupApplyCategory : DownloadQueue::eaGroupSetCategory;
|
|
|
|
optind++;
|
|
if (optind > argc)
|
|
{
|
|
ReportError("Could not parse value of option 'E'");
|
|
return;
|
|
}
|
|
m_editQueueText = std::move(argv[optind-1]);
|
|
}
|
|
else if (!strcasecmp(optarg, "N"))
|
|
{
|
|
if (!group)
|
|
{
|
|
ReportError("Only groups can be renamed");
|
|
return;
|
|
}
|
|
m_editQueueAction = DownloadQueue::eaGroupSetName;
|
|
|
|
optind++;
|
|
if (optind > argc)
|
|
{
|
|
ReportError("Could not parse value of option 'E'");
|
|
return;
|
|
}
|
|
m_editQueueText = std::move(argv[optind-1]);
|
|
}
|
|
else if (!strcasecmp(optarg, "M"))
|
|
{
|
|
if (!group)
|
|
{
|
|
ReportError("Only groups can be merged");
|
|
return;
|
|
}
|
|
m_editQueueAction = DownloadQueue::eaGroupMerge;
|
|
}
|
|
else if (!strcasecmp(optarg, "S"))
|
|
{
|
|
m_editQueueAction = DownloadQueue::eaFileSplit;
|
|
|
|
optind++;
|
|
if (optind > argc)
|
|
{
|
|
ReportError("Could not parse value of option 'E'");
|
|
return;
|
|
}
|
|
m_editQueueText = std::move(argv[optind-1]);
|
|
}
|
|
else if (!strcasecmp(optarg, "O"))
|
|
{
|
|
if (!group)
|
|
{
|
|
ReportError("Post-process parameter can be set only for groups");
|
|
return;
|
|
}
|
|
m_editQueueAction = DownloadQueue::eaGroupSetParameter;
|
|
|
|
optind++;
|
|
if (optind > argc)
|
|
{
|
|
ReportError("Could not parse value of option 'E'");
|
|
return;
|
|
}
|
|
m_editQueueText = std::move(argv[optind-1]);
|
|
|
|
if (!strchr(m_editQueueText, '='))
|
|
{
|
|
ReportError("Could not parse value of option 'E'");
|
|
return;
|
|
}
|
|
}
|
|
else if (!strcasecmp(optarg, "I"))
|
|
{
|
|
if (!group)
|
|
{
|
|
ReportError("Priority can be set only for groups");
|
|
return;
|
|
}
|
|
m_editQueueAction = DownloadQueue::eaGroupSetPriority;
|
|
|
|
optind++;
|
|
if (optind > argc)
|
|
{
|
|
ReportError("Could not parse value of option 'E'");
|
|
return;
|
|
}
|
|
m_editQueueText = std::move(argv[optind-1]);
|
|
|
|
if (atoi(m_editQueueText) == 0 && strcmp("0", m_editQueueText))
|
|
{
|
|
ReportError("Could not parse value of option 'E'");
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_editQueueOffset = atoi(optarg);
|
|
if (m_editQueueOffset == 0)
|
|
{
|
|
ReportError("Could not parse value of option 'E'");
|
|
return;
|
|
}
|
|
m_editQueueAction = group ? DownloadQueue::eaGroupMoveOffset : DownloadQueue::eaFileMoveOffset;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case 'Q':
|
|
m_clientOperation = opClientRequestShutdown;
|
|
break;
|
|
case 'O':
|
|
m_clientOperation = opClientRequestReload;
|
|
break;
|
|
case 'V':
|
|
m_clientOperation = opClientRequestVersion;
|
|
break;
|
|
case 'W':
|
|
m_clientOperation = opClientRequestWriteLog;
|
|
if (!strcasecmp(optarg, "I")) {
|
|
m_writeLogKind = (int)Message::mkInfo;
|
|
}
|
|
else if (!strcasecmp(optarg, "W")) {
|
|
m_writeLogKind = (int)Message::mkWarning;
|
|
}
|
|
else if (!strcasecmp(optarg, "E")) {
|
|
m_writeLogKind = (int)Message::mkError;
|
|
}
|
|
else if (!strcasecmp(optarg, "D")) {
|
|
m_writeLogKind = (int)Message::mkDetail;
|
|
}
|
|
else if (!strcasecmp(optarg, "G")) {
|
|
m_writeLogKind = (int)Message::mkDebug;
|
|
}
|
|
else
|
|
{
|
|
ReportError("Could not parse value of option 'W'");
|
|
return;
|
|
}
|
|
break;
|
|
case 'K':
|
|
// switch "K" is provided for compatibility with v. 0.8.0 and can be removed in future versions
|
|
m_addCategory = optarg;
|
|
break;
|
|
case 'S':
|
|
optind++;
|
|
optarg = optind > argc ? nullptr : (char*)argv[optind-1];
|
|
if (!optarg || !strncmp(optarg, "-", 1))
|
|
{
|
|
m_clientOperation = opClientRequestScanAsync;
|
|
optind--;
|
|
}
|
|
else if (!strcasecmp(optarg, "W"))
|
|
{
|
|
m_clientOperation = opClientRequestScanSync;
|
|
}
|
|
else
|
|
{
|
|
ReportError("Could not parse value of option 'S'");
|
|
return;
|
|
}
|
|
break;
|
|
case '?':
|
|
m_errors = true;
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (m_serverMode && m_clientOperation == opClientRequestDownloadPause)
|
|
{
|
|
m_pauseDownload = true;
|
|
m_clientOperation = opClientNoOperation;
|
|
}
|
|
}
|
|
|
|
void CommandLineParser::PrintUsage(const char* com)
|
|
{
|
|
printf("Usage:\n"
|
|
" %s [switches]\n\n"
|
|
"Switches:\n"
|
|
" -h, --help Print this help-message\n"
|
|
" -v, --version Print version and exit\n"
|
|
" -c, --configfile <file> Filename of configuration-file\n"
|
|
" -n, --noconfigfile Prevent loading of configuration-file\n"
|
|
" (required options must be passed with --option)\n"
|
|
" -p, --printconfig Print configuration and exit\n"
|
|
" -o, --option <name=value> Set or override option in configuration-file\n"
|
|
" -s, --server Start nzbget as a server in console-mode\n"
|
|
#ifndef WIN32
|
|
" -D, --daemon Start nzbget as a server in daemon-mode\n"
|
|
#endif
|
|
" -V, --serverversion Print server's version and exit\n"
|
|
" -Q, --quit Shutdown server\n"
|
|
" -O, --reload Reload config and restart all services\n"
|
|
" -A, --append [<options>] <nzb-file/url> Send file/url to server's\n"
|
|
" download queue\n"
|
|
" <options> are (multiple options must be separated with space):\n"
|
|
" T Add file to the top (beginning) of queue\n"
|
|
" P Pause added files\n"
|
|
" C <name> Assign category to nzb-file\n"
|
|
" N <name> Use this name as nzb-filename\n"
|
|
" I <priority> Set priority (signed integer)\n"
|
|
" DK <dupekey> Set duplicate key (string)\n"
|
|
" DS <dupescore> Set duplicate score (signed integer)\n"
|
|
" DM (score|all|force) Set duplicate mode\n"
|
|
" -C, --connect Attach client to server\n"
|
|
" -L, --list [F|FR|G|GR|O|H|S] [RegEx] Request list of items from server\n"
|
|
" F List individual files and server status (default)\n"
|
|
" FR Like \"F\" but apply regular expression filter\n"
|
|
" G List groups (nzb-files) and server status\n"
|
|
" GR Like \"G\" but apply regular expression filter\n"
|
|
" O List post-processor-queue\n"
|
|
" H List history\n"
|
|
" HA List history, all records (incl. hidden)\n"
|
|
" S Print only server status\n"
|
|
" <RegEx> Regular expression (only with options \"FR\", \"GR\")\n"
|
|
" using POSIX Extended Regular Expression Syntax\n"
|
|
" -P, --pause [D|O|S] Pause server\n"
|
|
" D Pause download queue (default)\n"
|
|
" O Pause post-processor queue\n"
|
|
" S Pause scan of incoming nzb-directory\n"
|
|
" -U, --unpause [D|O|S] Unpause server\n"
|
|
" D Unpause download queue (default)\n"
|
|
" O Unpause post-processor queue\n"
|
|
" S Unpause scan of incoming nzb-directory\n"
|
|
" -R, --rate <speed> Set download rate on server, in KB/s\n"
|
|
" -G, --log <lines> Request last <lines> lines from server's screen-log\n"
|
|
" -W, --write <D|I|W|E|G> \"Text\" Send text to server's log\n"
|
|
" -S, --scan [W] Scan incoming nzb-directory on server\n"
|
|
" W Wait until scan completes (synchronous mode)\n"
|
|
" -E, --edit [F|FN|FR|G|GN|GR|O|H] <action> <IDs/Names/RegExs> Edit items\n"
|
|
" on server\n"
|
|
" F Edit individual files (default)\n"
|
|
" FN Like \"F\" but uses names (as \"group/file\")\n"
|
|
" instead of IDs\n"
|
|
" FR Like \"FN\" but with regular expressions\n"
|
|
" G Edit all files in the group (same nzb-file)\n"
|
|
" GN Like \"G\" but uses group names instead of IDs\n"
|
|
" GR Like \"GN\" but with regular expressions\n"
|
|
" O Edit post-processor-queue\n"
|
|
" H Edit history\n"
|
|
" <action> is one of:\n"
|
|
" - for files (F) and groups (G):\n"
|
|
" <+offset|-offset> Move in queue relative to current position,\n"
|
|
" offset is an integer value\n"
|
|
" T Move to top of queue\n"
|
|
" B Move to bottom of queue\n"
|
|
" D Delete\n"
|
|
" - for files (F) and groups (G):\n"
|
|
" P Pause\n"
|
|
" U Resume (unpause)\n"
|
|
" - for groups (G):\n"
|
|
" A Pause all pars\n"
|
|
" R Pause extra pars\n"
|
|
" I <priority> Set priority (signed integer)\n"
|
|
" C <name> Set category\n"
|
|
" CP <name> Set category and apply post-process parameters\n"
|
|
" N <name> Rename\n"
|
|
" M Merge\n"
|
|
" S <name> Split - create new group from selected files\n"
|
|
" O <name>=<value> Set post-process parameter\n"
|
|
" - for post-jobs (O):\n"
|
|
" D Delete (cancel post-processing)\n"
|
|
" - for history (H):\n"
|
|
" D Delete\n"
|
|
" P Post-process again\n"
|
|
" R Download remaining files\n"
|
|
" A Download again\n"
|
|
" O <name>=<value> Set post-process parameter\n"
|
|
" B Mark as bad\n"
|
|
" G Mark as good\n"
|
|
" S Mark as success\n"
|
|
" <IDs> Comma-separated list of file- or group- ids or\n"
|
|
" ranges of file-ids, e. g.: 1-5,3,10-22\n"
|
|
" <Names> List of names (with options \"FN\" and \"GN\"),\n"
|
|
" e. g.: \"my nzb download%cmyfile.nfo\" \"another nzb\"\n"
|
|
" <RegExs> List of regular expressions (options \"FR\", \"GR\")\n"
|
|
" using POSIX Extended Regular Expression Syntax\n",
|
|
FileSystem::BaseFileName(com),
|
|
PATH_SEPARATOR);
|
|
}
|
|
|
|
void CommandLineParser::InitFileArg(int argc, const char* argv[])
|
|
{
|
|
if (optind >= argc)
|
|
{
|
|
// no nzb-file passed
|
|
if (!m_serverMode && !m_remoteClientMode &&
|
|
(m_clientOperation == opClientNoOperation ||
|
|
m_clientOperation == opClientRequestDownload ||
|
|
m_clientOperation == opClientRequestWriteLog))
|
|
{
|
|
if (m_clientOperation == opClientRequestWriteLog)
|
|
{
|
|
ReportError("Log-text not specified");
|
|
}
|
|
else
|
|
{
|
|
ReportError("Nzb-file or Url not specified");
|
|
}
|
|
}
|
|
}
|
|
else if (m_clientOperation == opClientRequestEditQueue)
|
|
{
|
|
if (m_matchMode == mmId)
|
|
{
|
|
ParseFileIdList(argc, argv, optind);
|
|
}
|
|
else
|
|
{
|
|
ParseFileNameList(argc, argv, optind);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_lastArg = argv[optind];
|
|
|
|
// Check if the file-name is a relative path or an absolute path
|
|
// If the path starts with '/' its an absolute, else relative
|
|
const char* fileName = argv[optind];
|
|
|
|
#ifdef WIN32
|
|
m_argFilename = fileName;
|
|
#else
|
|
if (fileName[0] == '/' || !strncasecmp(fileName, "http://", 6) || !strncasecmp(fileName, "https://", 7))
|
|
{
|
|
m_argFilename = fileName;
|
|
}
|
|
else
|
|
{
|
|
// TEST
|
|
m_argFilename.Reserve(1024 - 1);
|
|
getcwd(m_argFilename, 1024);
|
|
m_argFilename.AppendFmt("/%s", fileName);
|
|
}
|
|
#endif
|
|
|
|
if (m_serverMode || m_remoteClientMode ||
|
|
!(m_clientOperation == opClientNoOperation ||
|
|
m_clientOperation == opClientRequestDownload ||
|
|
m_clientOperation == opClientRequestWriteLog))
|
|
{
|
|
ReportError("Too many arguments");
|
|
}
|
|
}
|
|
}
|
|
|
|
void CommandLineParser::ParseFileIdList(int argc, const char* argv[], int optind)
|
|
{
|
|
m_editQueueIdList.clear();
|
|
|
|
while (optind < argc)
|
|
{
|
|
CString writableFileIdList = argv[optind++];
|
|
|
|
char* optarg = strtok(writableFileIdList, ", ");
|
|
while (optarg)
|
|
{
|
|
int editQueueIdFrom = 0;
|
|
int editQueueIdTo = 0;
|
|
const char* p = strchr(optarg, '-');
|
|
if (p)
|
|
{
|
|
BString<100> buf;
|
|
buf.Set(optarg, p - optarg);
|
|
editQueueIdFrom = atoi(buf);
|
|
editQueueIdTo = atoi(p + 1);
|
|
if (editQueueIdFrom <= 0 || editQueueIdTo <= 0)
|
|
{
|
|
ReportError("invalid list of file IDs");
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
editQueueIdFrom = atoi(optarg);
|
|
if (editQueueIdFrom <= 0)
|
|
{
|
|
ReportError("invalid list of file IDs");
|
|
return;
|
|
}
|
|
editQueueIdTo = editQueueIdFrom;
|
|
}
|
|
|
|
int editQueueIdCount = 0;
|
|
if (editQueueIdTo != 0)
|
|
{
|
|
if (editQueueIdFrom < editQueueIdTo)
|
|
{
|
|
editQueueIdCount = editQueueIdTo - editQueueIdFrom + 1;
|
|
}
|
|
else
|
|
{
|
|
editQueueIdCount = editQueueIdFrom - editQueueIdTo + 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
editQueueIdCount = 1;
|
|
}
|
|
|
|
for (int i = 0; i < editQueueIdCount; i++)
|
|
{
|
|
if (editQueueIdFrom < editQueueIdTo || editQueueIdTo == 0)
|
|
{
|
|
m_editQueueIdList.push_back(editQueueIdFrom + i);
|
|
}
|
|
else
|
|
{
|
|
m_editQueueIdList.push_back(editQueueIdFrom - i);
|
|
}
|
|
}
|
|
|
|
optarg = strtok(nullptr, ", ");
|
|
}
|
|
}
|
|
}
|
|
|
|
void CommandLineParser::ParseFileNameList(int argc, const char* argv[], int optind)
|
|
{
|
|
while (optind < argc)
|
|
{
|
|
m_editQueueNameList.push_back(argv[optind++]);
|
|
}
|
|
}
|
|
|
|
void CommandLineParser::ReportError(const char* errMessage)
|
|
{
|
|
m_errors = true;
|
|
printf("%s\n", errMessage);
|
|
}
|