2
* This file is part of nzbget
4
* Copyright (C) 2013-2014 Andrey Prygunkov <hugbug@users.sourceforge.net>
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21
* $Date: 2014-08-11 00:14:03 +0200 (Mon, 11 Aug 2014) $
40
#include "DownloadInfo.h"
42
#include "FeedFilter.h"
45
FeedFilter::Term::Term()
56
FeedFilter::Term::~Term()
63
bool FeedFilter::Term::Match(FeedItemInfo* pFeedItemInfo)
65
const char* szStrValue = NULL;
66
long long iIntValue = 0;
68
if (!GetFieldData(m_szField, pFeedItemInfo, &szStrValue, &iIntValue))
73
bool bMatch = MatchValue(szStrValue, iIntValue);
75
if (m_bPositive != bMatch)
83
bool FeedFilter::Term::MatchValue(const char* szStrValue, long long iIntValue)
85
double fFloatValue = (double)iIntValue;
88
if (m_eCommand < fcEqual && !szStrValue)
90
snprintf(szIntBuf, 100, "%lld", iIntValue);
91
szIntBuf[100-1] = '\0';
92
szStrValue = szIntBuf;
95
else if (m_eCommand >= fcEqual && szStrValue)
97
fFloatValue = atof(szStrValue);
98
iIntValue = (long long)fFloatValue;
104
return MatchText(szStrValue);
107
return MatchRegex(szStrValue);
110
return m_bFloat ? fFloatValue == m_fFloatParam : iIntValue == m_iIntParam;
113
return m_bFloat ? fFloatValue < m_fFloatParam : iIntValue < m_iIntParam;
116
return m_bFloat ? fFloatValue <= m_fFloatParam : iIntValue <= m_iIntParam;
119
return m_bFloat ? fFloatValue > m_fFloatParam : iIntValue > m_iIntParam;
122
return m_bFloat ? fFloatValue >= m_fFloatParam : iIntValue >= m_iIntParam;
129
bool FeedFilter::Term::MatchText(const char* szStrValue)
131
const char* WORD_SEPARATORS = " !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~";
133
// first check if we should make word-search or substring-search
134
int iParamLen = strlen(m_szParam);
135
bool bSubstr = iParamLen >= 2 && m_szParam[0] == '*' && m_szParam[iParamLen-1] == '*';
138
for (const char* p = m_szParam; *p; p++)
141
if (strchr(WORD_SEPARATORS, ch) && ch != '*' && ch != '?' && ch != '#')
155
// split szStrValue into tokens
156
Tokenizer tok(szStrValue, WORD_SEPARATORS);
157
while (const char* szWord = tok.Next())
159
WildMask mask(m_szParam, m_pRefValues != NULL);
160
bMatch = mask.Match(szWord);
163
FillWildMaskRefValues(szWord, &mask, 0);
173
const char* szFormat = "*%s*";
174
if (iParamLen >= 2 && m_szParam[0] == '*' && m_szParam[iParamLen-1] == '*')
179
else if (iParamLen >= 1 && m_szParam[0] == '*')
184
else if (iParamLen >= 1 && m_szParam[iParamLen-1] == '*')
189
int iMaskLen = strlen(m_szParam) + 2 + 1;
190
char* szMask = (char*)malloc(iMaskLen);
191
snprintf(szMask, iMaskLen, szFormat, m_szParam);
192
szMask[iMaskLen-1] = '\0';
194
WildMask mask(szMask, m_pRefValues != NULL);
195
bMatch = mask.Match(szStrValue);
199
FillWildMaskRefValues(szStrValue, &mask, iRefOffset);
208
bool FeedFilter::Term::MatchRegex(const char* szStrValue)
212
m_pRegEx = new RegEx(m_szParam, m_pRefValues == NULL ? 0 : 100);
215
bool bFound = m_pRegEx->Match(szStrValue);
218
FillRegExRefValues(szStrValue, m_pRegEx);
223
bool FeedFilter::Term::Compile(char* szToken)
225
debug("Token: %s", szToken);
227
char ch = szToken[0];
229
m_bPositive = ch != '-';
230
if (ch == '-' || ch == '+')
236
char ch2= szToken[1];
237
if ((ch == '(' || ch == ')' || ch == '|') && (ch2 == ' ' || ch2 == '\0'))
242
m_eCommand = fcOpeningBrace;
245
m_eCommand = fcClosingBrace;
248
m_eCommand = fcOrOperator;
253
char *szField = NULL;
256
char* szColon = NULL;
257
if (ch != '@' && ch != '$' && ch != '<' && ch != '>' && ch != '=')
259
szColon = strchr(szToken, ':');
265
szToken = szColon + 1;
283
m_eCommand = fcRegex;
288
m_eCommand = fcEqual;
291
else if (ch == '<' && ch2 == '=')
293
m_eCommand = fcLessEqual;
296
else if (ch == '>' && ch2 == '=')
298
m_eCommand = fcGreaterEqual;
308
m_eCommand = fcGreater;
312
debug("%s, Field: %s, Command: %i, Param: %s", (m_bPositive ? "Positive" : "Negative"), szField, m_eCommand, szToken);
314
const char* szStrValue;
316
if (!GetFieldData(szField, NULL, &szStrValue, &iIntValue))
321
if (szField && !ParseParam(szField, szToken))
326
m_szField = szField ? strdup(szField) : NULL;
327
m_szParam = strdup(szToken);
333
* If pFeedItemInfo is NULL, only field name is validated
335
bool FeedFilter::Term::GetFieldData(const char* szField, FeedItemInfo* pFeedItemInfo,
336
const char** StrValue, long long* IntValue)
341
if (!szField || !strcasecmp(szField, "title"))
343
*StrValue = pFeedItemInfo ? pFeedItemInfo->GetTitle() : NULL;
346
else if (!strcasecmp(szField, "filename"))
348
*StrValue = pFeedItemInfo ? pFeedItemInfo->GetFilename() : NULL;
351
else if (!strcasecmp(szField, "category"))
353
*StrValue = pFeedItemInfo ? pFeedItemInfo->GetCategory() : NULL;
356
else if (!strcasecmp(szField, "link") || !strcasecmp(szField, "url"))
358
*StrValue = pFeedItemInfo ? pFeedItemInfo->GetUrl() : NULL;
361
else if (!strcasecmp(szField, "size"))
363
*IntValue = pFeedItemInfo ? pFeedItemInfo->GetSize() : 0;
366
else if (!strcasecmp(szField, "age"))
368
*IntValue = pFeedItemInfo ? time(NULL) - pFeedItemInfo->GetTime() : 0;
371
else if (!strcasecmp(szField, "imdbid"))
373
*IntValue = pFeedItemInfo ? pFeedItemInfo->GetImdbId() : 0;
376
else if (!strcasecmp(szField, "rageid"))
378
*IntValue = pFeedItemInfo ? pFeedItemInfo->GetRageId() : 0;
381
else if (!strcasecmp(szField, "description"))
383
*StrValue = pFeedItemInfo ? pFeedItemInfo->GetDescription() : NULL;
386
else if (!strcasecmp(szField, "season"))
388
*IntValue = pFeedItemInfo ? pFeedItemInfo->GetSeasonNum() : 0;
391
else if (!strcasecmp(szField, "episode"))
393
*IntValue = pFeedItemInfo ? pFeedItemInfo->GetEpisodeNum() : 0;
396
else if (!strcasecmp(szField, "priority"))
398
*IntValue = pFeedItemInfo ? pFeedItemInfo->GetPriority() : 0;
401
else if (!strcasecmp(szField, "dupekey"))
403
*StrValue = pFeedItemInfo ? pFeedItemInfo->GetDupeKey() : NULL;
406
else if (!strcasecmp(szField, "dupescore"))
408
*IntValue = pFeedItemInfo ? pFeedItemInfo->GetDupeScore() : 0;
411
else if (!strcasecmp(szField, "dupestatus"))
413
*StrValue = pFeedItemInfo ? pFeedItemInfo->GetDupeStatus() : NULL;
416
else if (!strncasecmp(szField, "attr-", 5))
420
FeedItemInfo::Attr* pAttr = pFeedItemInfo->GetAttributes()->Find(szField + 5);
421
*StrValue = pAttr ? pAttr->GetValue() : NULL;
429
bool FeedFilter::Term::ParseParam(const char* szField, const char* szParam)
431
if (!strcasecmp(szField, "size"))
433
return ParseSizeParam(szParam);
435
else if (!strcasecmp(szField, "age"))
437
return ParseAgeParam(szParam);
439
else if (m_eCommand >= fcEqual)
441
return ParseNumericParam(szParam);
447
bool FeedFilter::Term::ParseSizeParam(const char* szParam)
449
double fParam = atof(szParam);
452
for (p = szParam; *p && ((*p >= '0' && *p <='9') || *p == '.'); p++) ;
455
if (!strcasecmp(p, "K") || !strcasecmp(p, "KB"))
457
m_iIntParam = (long long)(fParam*1024);
459
else if (!strcasecmp(p, "M") || !strcasecmp(p, "MB"))
461
m_iIntParam = (long long)(fParam*1024*1024);
463
else if (!strcasecmp(p, "G") || !strcasecmp(p, "GB"))
465
m_iIntParam = (long long)(fParam*1024*1024*1024);
474
m_iIntParam = (long long)fParam;
480
bool FeedFilter::Term::ParseAgeParam(const char* szParam)
482
double fParam = atof(szParam);
485
for (p = szParam; *p && ((*p >= '0' && *p <='9') || *p == '.'); p++) ;
488
if (!strcasecmp(p, "m"))
491
m_iIntParam = (long long)(fParam*60);
493
else if (!strcasecmp(p, "h"))
496
m_iIntParam = (long long)(fParam*60*60);
498
else if (!strcasecmp(p, "d"))
501
m_iIntParam = (long long)(fParam*60*60*24);
511
m_iIntParam = (long long)(fParam*60*60*24);
517
bool FeedFilter::Term::ParseNumericParam(const char* szParam)
519
m_fFloatParam = atof(szParam);
520
m_iIntParam = (long long)m_fFloatParam;
521
m_bFloat = strchr(szParam, '.');
524
for (p = szParam; *p && ((*p >= '0' && *p <='9') || *p == '.') ; p++) ;
533
void FeedFilter::Term::FillWildMaskRefValues(const char* szStrValue, WildMask* pMask, int iRefOffset)
540
for (int i = iRefOffset; i < pMask->GetMatchCount(); i++)
542
int iLen = pMask->GetMatchLen(i);
543
char* szValue = (char*)malloc(iLen + 1);
544
strncpy(szValue, szStrValue + pMask->GetMatchStart(i), iLen);
545
szValue[iLen] = '\0';
547
m_pRefValues->push_back(szValue);
551
void FeedFilter::Term::FillRegExRefValues(const char* szStrValue, RegEx* pRegEx)
558
for (int i = 1; i < pRegEx->GetMatchCount(); i++)
560
int iLen = pRegEx->GetMatchLen(i);
561
char* szValue = (char*)malloc(iLen + 1);
562
strncpy(szValue, szStrValue + pRegEx->GetMatchStart(i), iLen);
563
szValue[iLen] = '\0';
565
m_pRefValues->push_back(szValue);
570
FeedFilter::Rule::Rule()
572
m_eCommand = frAccept;
579
m_szAddDupeKey = NULL;
582
m_eDupeMode = dmScore;
585
m_bHasCategory = false;
586
m_bHasPriority = false;
587
m_bHasAddPriority = false;
589
m_bHasDupeScore = false;
590
m_bHasAddDupeScore = false;
591
m_bHasDupeKey = false;
592
m_bHasAddDupeKey = false;
593
m_bHasDupeMode = false;
594
m_bHasRageId = false;
595
m_bHasSeries = false;
596
m_bPatCategory = false;
597
m_bPatDupeKey = false;
598
m_bPatAddDupeKey = false;
599
m_szPatCategory = NULL;
600
m_szPatDupeKey = NULL;
601
m_szPatAddDupeKey = NULL;
604
FeedFilter::Rule::~Rule()
608
free(m_szAddDupeKey);
611
free(m_szPatCategory);
612
free(m_szPatDupeKey);
613
free(m_szPatAddDupeKey);
615
for (TermList::iterator it = m_Terms.begin(); it != m_Terms.end(); it++)
620
for (RefValues::iterator it = m_RefValues.begin(); it != m_RefValues.end(); it++)
626
void FeedFilter::Rule::Compile(char* szRule)
628
debug("Compiling rule: %s", szRule);
632
char* szFilter3 = Util::Trim(szRule);
634
char* szTerm = CompileCommand(szFilter3);
640
if (m_eCommand == frComment)
645
szTerm = Util::Trim(szTerm);
647
for (char* p = szTerm; *p && m_bIsValid; p++)
653
m_bIsValid = CompileTerm(szTerm);
655
while (*szTerm == ' ') szTerm++;
660
m_bIsValid = m_bIsValid && CompileTerm(szTerm);
662
if (m_bIsValid && m_bPatCategory)
664
m_szPatCategory = m_szCategory;
667
if (m_bIsValid && m_bPatDupeKey)
669
m_szPatDupeKey = m_szDupeKey;
672
if (m_bIsValid && m_bPatAddDupeKey)
674
m_szPatAddDupeKey = m_szAddDupeKey;
675
m_szAddDupeKey = NULL;
679
/* Checks if the rule starts with command and compiles it.
680
* Returns a pointer to the next (first) term or NULL in a case of compilation error.
682
char* FeedFilter::Rule::CompileCommand(char* szRule)
684
if (!strncasecmp(szRule, "A:", 2) || !strncasecmp(szRule, "Accept:", 7) ||
685
!strncasecmp(szRule, "A(", 2) || !strncasecmp(szRule, "Accept(", 7))
687
m_eCommand = frAccept;
688
szRule += szRule[1] == ':' || szRule[1] == '(' ? 2 : 7;
690
else if (!strncasecmp(szRule, "O(", 2) || !strncasecmp(szRule, "Options(", 8))
692
m_eCommand = frOptions;
693
szRule += szRule[1] == ':' || szRule[1] == '(' ? 2 : 8;
695
else if (!strncasecmp(szRule, "R:", 2) || !strncasecmp(szRule, "Reject:", 7))
697
m_eCommand = frReject;
698
szRule += szRule[1] == ':' || szRule[1] == '(' ? 2 : 7;
700
else if (!strncasecmp(szRule, "Q:", 2) || !strncasecmp(szRule, "Require:", 8))
702
m_eCommand = frRequire;
703
szRule += szRule[1] == ':' || szRule[1] == '(' ? 2 : 8;
705
else if (*szRule == '#')
707
m_eCommand = frComment;
716
if ((m_eCommand == frAccept || m_eCommand == frOptions) && szRule[-1] == '(')
718
szRule = CompileOptions(szRule);
724
char* FeedFilter::Rule::CompileOptions(char* szRule)
726
char* p = strchr(szRule, ')');
733
// split command into tokens
735
Tokenizer tok(szRule, ",", true);
736
while (char* szOption = tok.Next())
738
const char* szValue = "";
739
char* szColon = strchr(szOption, ':');
743
szValue = Util::Trim(szColon + 1);
746
if (!strcasecmp(szOption, "category") || !strcasecmp(szOption, "cat") || !strcasecmp(szOption, "c"))
748
m_bHasCategory = true;
750
m_szCategory = strdup(szValue);
751
m_bPatCategory = strstr(szValue, "${");
753
else if (!strcasecmp(szOption, "pause") || !strcasecmp(szOption, "p"))
756
m_bPause = !*szValue || !strcasecmp(szValue, "yes") || !strcasecmp(szValue, "y");
757
if (!m_bPause && !(!strcasecmp(szValue, "no") || !strcasecmp(szValue, "n")))
763
else if (!strcasecmp(szOption, "priority") || !strcasecmp(szOption, "pr") || !strcasecmp(szOption, "r"))
765
if (!strchr("0123456789-+", *szValue))
770
m_bHasPriority = true;
771
m_iPriority = atoi(szValue);
773
else if (!strcasecmp(szOption, "priority+") || !strcasecmp(szOption, "pr+") || !strcasecmp(szOption, "r+"))
775
if (!strchr("0123456789-+", *szValue))
780
m_bHasAddPriority = true;
781
m_iAddPriority = atoi(szValue);
783
else if (!strcasecmp(szOption, "dupescore") || !strcasecmp(szOption, "ds") || !strcasecmp(szOption, "s"))
785
if (!strchr("0123456789-+", *szValue))
790
m_bHasDupeScore = true;
791
m_iDupeScore = atoi(szValue);
793
else if (!strcasecmp(szOption, "dupescore+") || !strcasecmp(szOption, "ds+") || !strcasecmp(szOption, "s+"))
795
if (!strchr("0123456789-+", *szValue))
800
m_bHasAddDupeScore = true;
801
m_iAddDupeScore = atoi(szValue);
803
else if (!strcasecmp(szOption, "dupekey") || !strcasecmp(szOption, "dk") || !strcasecmp(szOption, "k"))
805
m_bHasDupeKey = true;
807
m_szDupeKey = strdup(szValue);
808
m_bPatDupeKey = strstr(szValue, "${");
810
else if (!strcasecmp(szOption, "dupekey+") || !strcasecmp(szOption, "dk+") || !strcasecmp(szOption, "k+"))
812
m_bHasAddDupeKey = true;
813
free(m_szAddDupeKey);
814
m_szAddDupeKey = strdup(szValue);
815
m_bPatAddDupeKey = strstr(szValue, "${");
817
else if (!strcasecmp(szOption, "dupemode") || !strcasecmp(szOption, "dm") || !strcasecmp(szOption, "m"))
819
m_bHasDupeMode = true;
820
if (!strcasecmp(szValue, "score") || !strcasecmp(szValue, "s"))
822
m_eDupeMode = dmScore;
824
else if (!strcasecmp(szValue, "all") || !strcasecmp(szValue, "a"))
828
else if (!strcasecmp(szValue, "force") || !strcasecmp(szValue, "f"))
830
m_eDupeMode = dmForce;
838
else if (!strcasecmp(szOption, "rageid"))
842
m_szRageId = strdup(szValue);
844
else if (!strcasecmp(szOption, "series"))
848
m_szSeries = strdup(szValue);
851
// for compatibility with older version we support old commands too
852
else if (!strcasecmp(szOption, "paused") || !strcasecmp(szOption, "unpaused"))
855
m_bPause = !strcasecmp(szOption, "paused");
857
else if (strchr("0123456789-+", *szOption))
859
m_bHasPriority = true;
860
m_iPriority = atoi(szOption);
864
m_bHasCategory = true;
866
m_szCategory = strdup(szOption);
879
bool FeedFilter::Rule::CompileTerm(char* szTerm)
881
Term* pTerm = new Term();
882
pTerm->SetRefValues(m_bPatCategory || m_bPatDupeKey || m_bPatAddDupeKey ? &m_RefValues : NULL);
883
if (pTerm->Compile(szTerm))
885
m_Terms.push_back(pTerm);
895
bool FeedFilter::Rule::Match(FeedItemInfo* pFeedItemInfo)
897
for (RefValues::iterator it = m_RefValues.begin(); it != m_RefValues.end(); it++)
903
if (!MatchExpression(pFeedItemInfo))
910
ExpandRefValues(pFeedItemInfo, &m_szCategory, m_szPatCategory);
914
ExpandRefValues(pFeedItemInfo, &m_szDupeKey, m_szPatDupeKey);
916
if (m_bPatAddDupeKey)
918
ExpandRefValues(pFeedItemInfo, &m_szAddDupeKey, m_szPatAddDupeKey);
924
bool FeedFilter::Rule::MatchExpression(FeedItemInfo* pFeedItemInfo)
926
char* expr = (char*)malloc(m_Terms.size() + 1);
929
for (TermList::iterator it = m_Terms.begin(); it != m_Terms.end(); it++, index++)
932
switch (pTerm->GetCommand())
947
expr[index] = pTerm->Match(pFeedItemInfo) ? 'T' : 'F';
953
// reduce result tree to one element (may be longer if expression has syntax errors)
954
for (int iOldLen = 0, iNewLen = strlen(expr); iNewLen != iOldLen; iOldLen = iNewLen, iNewLen = strlen(expr))
956
// NOTE: there are no operator priorities.
957
// the order of operators "OR" and "AND" is not defined, they can be checked in any order.
958
// "OR" and "AND" should not be mixed in one group; instead braces should be used to define priorities.
959
Util::ReduceStr(expr, "TT", "T");
960
Util::ReduceStr(expr, "TF", "F");
961
Util::ReduceStr(expr, "FT", "F");
962
Util::ReduceStr(expr, "FF", "F");
963
Util::ReduceStr(expr, "||", "|");
964
Util::ReduceStr(expr, "(|", "(");
965
Util::ReduceStr(expr, "|)", ")");
966
Util::ReduceStr(expr, "T|T", "T");
967
Util::ReduceStr(expr, "T|F", "T");
968
Util::ReduceStr(expr, "F|T", "T");
969
Util::ReduceStr(expr, "F|F", "F");
970
Util::ReduceStr(expr, "(T)", "T");
971
Util::ReduceStr(expr, "(F)", "F");
974
bool bMatch = *expr && *expr == 'T' && expr[1] == '\0';
979
void FeedFilter::Rule::ExpandRefValues(FeedItemInfo* pFeedItemInfo, char** pDestStr, char* pPatStr)
983
*pDestStr = strdup(pPatStr);
984
char* curvalue = *pDestStr;
987
while (char* dollar = strstr(curvalue, "${"))
995
char* end = strchr(dollar, '}');
1001
int varlen = (int)(end - dollar - 2);
1003
int maxlen = varlen < 100 ? varlen : 100;
1004
strncpy(variable, dollar + 2, maxlen);
1005
variable[maxlen] = '\0';
1007
const char* varvalue = GetRefValue(pFeedItemInfo, variable);
1013
int newlen = strlen(varvalue);
1014
char* newvalue = (char*)malloc(strlen(curvalue) - varlen - 3 + newlen + 1);
1015
strncpy(newvalue, curvalue, dollar - curvalue);
1016
strncpy(newvalue + (dollar - curvalue), varvalue, newlen);
1017
strcpy(newvalue + (dollar - curvalue) + newlen, end + 1);
1019
curvalue = newvalue;
1020
*pDestStr = curvalue;
1024
const char* FeedFilter::Rule::GetRefValue(FeedItemInfo* pFeedItemInfo, const char* szVarName)
1026
if (!strcasecmp(szVarName, "season"))
1028
pFeedItemInfo->GetSeasonNum(); // needed to parse title
1029
return pFeedItemInfo->GetSeason() ? pFeedItemInfo->GetSeason() : "";
1031
else if (!strcasecmp(szVarName, "episode"))
1033
pFeedItemInfo->GetEpisodeNum(); // needed to parse title
1034
return pFeedItemInfo->GetEpisode() ? pFeedItemInfo->GetEpisode() : "";
1037
int iIndex = atoi(szVarName) - 1;
1038
if (iIndex >= 0 && iIndex < (int)m_RefValues.size())
1040
return m_RefValues[iIndex];
1046
FeedFilter::FeedFilter(const char* szFilter)
1051
FeedFilter::~FeedFilter()
1053
for (RuleList::iterator it = m_Rules.begin(); it != m_Rules.end(); it++)
1059
void FeedFilter::Compile(const char* szFilter)
1061
debug("Compiling filter: %s", szFilter);
1063
char* szFilter2 = strdup(szFilter);
1064
char* szRule = szFilter2;
1066
for (char* p = szRule; *p; p++)
1072
CompileRule(szRule);
1077
CompileRule(szRule);
1082
void FeedFilter::CompileRule(char* szRule)
1084
Rule* pRule = new Rule();
1085
m_Rules.push_back(pRule);
1086
pRule->Compile(szRule);
1089
void FeedFilter::Match(FeedItemInfo* pFeedItemInfo)
1092
for (RuleList::iterator it = m_Rules.begin(); it != m_Rules.end(); it++)
1096
if (pRule->IsValid())
1098
bool bMatch = pRule->Match(pFeedItemInfo);
1099
switch (pRule->GetCommand())
1105
pFeedItemInfo->SetMatchStatus(FeedItemInfo::msAccepted);
1106
pFeedItemInfo->SetMatchRule(index);
1107
ApplyOptions(pRule, pFeedItemInfo);
1108
if (pRule->GetCommand() == frAccept)
1118
pFeedItemInfo->SetMatchStatus(FeedItemInfo::msRejected);
1119
pFeedItemInfo->SetMatchRule(index);
1127
pFeedItemInfo->SetMatchStatus(FeedItemInfo::msRejected);
1128
pFeedItemInfo->SetMatchRule(index);
1139
pFeedItemInfo->SetMatchStatus(FeedItemInfo::msIgnored);
1140
pFeedItemInfo->SetMatchRule(0);
1143
void FeedFilter::ApplyOptions(Rule* pRule, FeedItemInfo* pFeedItemInfo)
1145
if (pRule->HasPause())
1147
pFeedItemInfo->SetPauseNzb(pRule->GetPause());
1149
if (pRule->HasCategory())
1151
pFeedItemInfo->SetAddCategory(pRule->GetCategory());
1153
if (pRule->HasPriority())
1155
pFeedItemInfo->SetPriority(pRule->GetPriority());
1157
if (pRule->HasAddPriority())
1159
pFeedItemInfo->SetPriority(pFeedItemInfo->GetPriority() + pRule->GetAddPriority());
1161
if (pRule->HasDupeScore())
1163
pFeedItemInfo->SetDupeScore(pRule->GetDupeScore());
1165
if (pRule->HasAddDupeScore())
1167
pFeedItemInfo->SetDupeScore(pFeedItemInfo->GetDupeScore() + pRule->GetAddDupeScore());
1169
if (pRule->HasRageId() || pRule->HasSeries())
1171
pFeedItemInfo->BuildDupeKey(pRule->GetRageId(), pRule->GetSeries());
1173
if (pRule->HasDupeKey())
1175
pFeedItemInfo->SetDupeKey(pRule->GetDupeKey());
1177
if (pRule->HasAddDupeKey())
1179
pFeedItemInfo->AppendDupeKey(pRule->GetAddDupeKey());
1181
if (pRule->HasDupeMode())
1183
pFeedItemInfo->SetDupeMode(pRule->GetDupeMode());