Build a filter structure given a filter pattern. The value in "pat" * is not null-terminated. "rule" is either held or freed, so the * caller should not free it. */
| 160 | * is not null-terminated. "rule" is either held or freed, so the |
| 161 | * caller should not free it. */ |
| 162 | static void add_rule(filter_rule_list *listp, const char *pat, unsigned int pat_len, |
| 163 | filter_rule *rule, int xflags) |
| 164 | { |
| 165 | const char *cp; |
| 166 | unsigned int pre_len, suf_len, slash_cnt = 0; |
| 167 | char *mention_rule_suffix; |
| 168 | |
| 169 | if (DEBUG_GTE(FILTER, 1) && pat_len && (pat[pat_len-1] == ' ' || pat[pat_len-1] == '\t')) |
| 170 | mention_rule_suffix = " -- CAUTION: trailing whitespace!"; |
| 171 | else |
| 172 | mention_rule_suffix = DEBUG_GTE(FILTER, 2) ? "" : NULL; |
| 173 | if (mention_rule_suffix) { |
| 174 | rprintf(FINFO, "[%s] add_rule(%s%.*s%s)%s%s\n", |
| 175 | who_am_i(), get_rule_prefix(rule, pat, 0, NULL), |
| 176 | (int)pat_len, pat, (rule->rflags & FILTRULE_DIRECTORY) ? "/" : "", |
| 177 | listp->debug_type, mention_rule_suffix); |
| 178 | } |
| 179 | |
| 180 | /* These flags also indicate that we're reading a list that |
| 181 | * needs to be filtered now, not post-filtered later. */ |
| 182 | if (xflags & (XFLG_ANCHORED2ABS|XFLG_ABS_IF_SLASH) |
| 183 | && (rule->rflags & FILTRULES_SIDES) |
| 184 | == (am_sender ? FILTRULE_RECEIVER_SIDE : FILTRULE_SENDER_SIDE)) { |
| 185 | /* This filter applies only to the other side. Drop it. */ |
| 186 | free_filter(rule); |
| 187 | return; |
| 188 | } |
| 189 | |
| 190 | if (pat_len > 1 && pat[pat_len-1] == '/') { |
| 191 | pat_len--; |
| 192 | rule->rflags |= FILTRULE_DIRECTORY; |
| 193 | } |
| 194 | |
| 195 | for (cp = pat; cp < pat + pat_len; cp++) { |
| 196 | if (*cp == '/') |
| 197 | slash_cnt++; |
| 198 | } |
| 199 | |
| 200 | if (!(rule->rflags & (FILTRULE_ABS_PATH | FILTRULE_MERGE_FILE)) |
| 201 | && ((xflags & (XFLG_ANCHORED2ABS|XFLG_ABS_IF_SLASH) && *pat == '/') |
| 202 | || (xflags & XFLG_ABS_IF_SLASH && slash_cnt))) { |
| 203 | rule->rflags |= FILTRULE_ABS_PATH; |
| 204 | if (*pat == '/') |
| 205 | pre_len = dirbuf_len - module_dirlen - 1; |
| 206 | else |
| 207 | pre_len = 0; |
| 208 | } else |
| 209 | pre_len = 0; |
| 210 | |
| 211 | /* The daemon wants dir-exclude rules to get an appended "/" + "***". */ |
| 212 | if (xflags & XFLG_DIR2WILD3 |
| 213 | && BITS_SETnUNSET(rule->rflags, FILTRULE_DIRECTORY, FILTRULE_INCLUDE)) { |
| 214 | rule->rflags &= ~FILTRULE_DIRECTORY; |
| 215 | suf_len = sizeof SLASH_WILD3_SUFFIX - 1; |
| 216 | } else |
| 217 | suf_len = 0; |
| 218 | |
| 219 | rule->pattern = new_array(char, pre_len + pat_len + suf_len + 1); |
no test coverage detected