PRIVATE int parseFeed(rss_feeds *feeds, const char* feedstr) { char *line = NULL, *option = NULL, *param = NULL; char *saveptr; char *str = NULL; rss_feed* feed = NULL; int result = SUCCESS; /* be optimistic */ str = shorten(feedstr); line = strtok_r(str, AM_DELIMITER, &saveptr); while (line) { if(!feed) { feed = feed_new(); assert(feed && "feed_new() failed!"); } if(parseSubOption(line, &option, ¶m) == 0) { if(!strncmp(option, "url", 3)) { feed->url = shorten(param); } else if(!strncmp(option, "cookies", 6)) { feed->cookies = shorten(param); } else { dbg_printf(P_ERROR, "Unknown suboption '%s'!", option); } am_free(option); am_free(param); } else { dbg_printf(P_ERROR, "Invalid suboption string: '%s'!", line); } line = strtok_r(NULL, AM_DELIMITER, &saveptr); } if(feed && feed->url) { /* Maybe the cookies are encoded within the URL */ if(feed->cookies == NULL) { parseCookiesFromURL(feed); } feed->id = listCount(*feeds); feed_add(feed, feeds); } else { dbg_printf(P_ERROR, "Invalid feed: '%s'", str); result = FAILURE; } am_free(str); return result; }
PRIVATE int parseFilter(am_filters *patlist, const char* match) { char *line = NULL, *option = NULL, *param = NULL; char *saveptr; char *str = NULL; am_filter filter = NULL; int result = SUCCESS; /* be optimistic */ str = shorten(match); line = strtok_r(str, AM_DELIMITER, &saveptr); while (line) { if(!filter) { filter = filter_new(); assert(filter && "filter_new() failed!"); } if(parseSubOption(line, &option, ¶m) == 0) { if(!strncmp(option, "pattern", 7)) { filter->pattern = shorten(param); } else if(!strncmp(option, "useragent", 9)) { filter->agent = shorten(param); } else { dbg_printf(P_ERROR, "Unknown suboption '%s'!", option); } am_free(option); am_free(param); } else { dbg_printf(P_ERROR, "Invalid suboption string: '%s'!", line); } line = strtok_r(NULL, AM_DELIMITER, &saveptr); } if(filter && filter->pattern) { filter_add(filter, patlist); } else { dbg_printf(P_ERROR, "Invalid filter: '%s'", str); result = FAILURE; } am_free(str); return result; }
PRIVATE simple_list parseMultiOption(const char *str) { int tmp_pos; uint32_t line_pos = 0; uint32_t len = strlen(str); simple_list options = NULL; char tmp[MAX_PARAM_LEN]; int last_dbl_quote_pos; int8_t parse_error = 0; int32_t current_line_pos = 0; if(len == 0) { dbg_printf(P_ERROR, "[parseMultiOption] empty input string!"); return NULL; } while(line_pos < len) { memset(&tmp, 0, sizeof(tmp)); // Skip any initial whitespace while (line_pos < len && isspace(str[line_pos])) { ++line_pos; } tmp_pos = 0; parse_error = 0; last_dbl_quote_pos = -1; while(line_pos < len && str[line_pos] != '\0') { if(str[line_pos] == '\"') { last_dbl_quote_pos = tmp_pos; } else if(str[line_pos] == '\n') { // Text is broken over multiple lines if(str[line_pos - 1] == '\\' || str[line_pos - 1] == '+') { // skip newline line_pos++; // skip whitespace at the beginning of the next line while (line_pos < len && isspace(str[line_pos])) { ++line_pos; } if(str[line_pos] == '\"' && last_dbl_quote_pos != -1) { // Reset the string index to the position of the last double-quote, and properly null-terminate it tmp_pos = last_dbl_quote_pos; tmp[tmp_pos] = '\0'; // Skip the double-quote on the new line as well line_pos++; } else { tmp[tmp_pos] = '\0'; dbg_printf(P_ERROR, "[parseMultiOption] Parsing error at line '%s'", &tmp[current_line_pos]); parse_error = 1; break; } } else { // If the character before the newline is not a backslash ('\'), consider this suboption complete break; } current_line_pos = tmp_pos; } tmp[tmp_pos++] = str[line_pos++]; } if(parse_error) { break; } /* A suboption is finished, end it with a null terminator */ tmp[tmp_pos] = '\0'; /* store the line in our list */ if(tmp_pos != 0) { suboption_t* i = parseSubOption(tmp); if(i != NULL) { addItem(i, &options); } else { dbg_printf(P_ERROR, "Invalid suboption string: '%s'", tmp); } } } return options; }