/** * rss_parser_load_from_file: * @self: a #RssParser * @filename: the path to the file to parse * @error: a location for a newly created #GError * * Parses the file found at @filename as an rss file. You can retrieve * the parsed document with rss_parser_get_document(). * * Returns: TRUE if the parse was successful */ gboolean rss_parser_load_from_file (RssParser *self, gchar *filename, GError **error) { mrss_t *mrss; mrss_error_t res; g_signal_emit (self, parser_signals[PARSE_START], 0); /* parse the buffer */ res = mrss_parse_file (filename, &mrss); /* if there was an error parsing, set the error and return false */ if (MRSS_OK != res) { if (error) { g_set_error (error, RSS_PARSER_ERROR, RSS_PARSER_ERROR_INVALID_DATA, "Could not parse file contents"); } return FALSE; } /* keep a copy of our parsed document */ self->priv->document = rss_parser_parse (self, mrss); /* free our mrss data */ mrss_free (mrss); g_signal_emit (self, parser_signals[PARSE_END], 0); return TRUE; }
rss_t* load_rss(gchar* feed_url, GError** err){ mrss_t *feed; mrss_error_t ret; mrss_item_t *item; CURLcode code; ret = mrss_parse_url_with_options_and_error(feed_url, &feed, NULL, &code); if(ret){ if(ret == MRSS_ERR_DOWNLOAD){ g_set_error(err, rss_quark(), RSS_ERR_CURL, "mrss_curl_strerror: %s\n", mrss_curl_strerror(code)); } else{ g_set_error(err, rss_quark(), RSS_ERR_MRSS, "mrss_strerror: %s\n", mrss_strerror(ret)); } return NULL; } rss_t* rss = (rss_t*) malloc(sizeof(rss_t)); if(rss == NULL){ g_set_error(err, rss_quark(), RSS_ERR_MEMORY_ALLOC, "malloc: Failed to alloc memory for read the rss_t* structure.\n"); return NULL; } rss->chapters = NULL; for(item = feed->item, rss->chap_len = 0; item != NULL; item = item->next, rss->chap_len++){ rss->chapters = (chapter_t**) realloc( rss->chapters, (rss->chap_len + 1) * sizeof(chapter_t*) ); if(rss->chapters == NULL){ g_set_error(err, rss_quark(), RSS_ERR_MEMORY_ALLOC, "malloc: Failed to alloc memory for read the chapter_t** structure.\n"); return NULL; } rss->chapters[rss->chap_len] = (chapter_t*) malloc(sizeof(chapter_t)); if(rss->chapters[rss->chap_len] == NULL){ g_set_error(err, rss_quark(), RSS_ERR_MEMORY_ALLOC, "malloc: Failed to alloc memory for read the chapter_t* structure.\n"); return NULL; } rss->chapters[rss->chap_len]->title = g_strdup(item->title); rss->chapters[rss->chap_len]->url = g_strdup(item->enclosure_url); rss->chapters[rss->chap_len]->type = g_strdup(item->enclosure_type); rss->chapters[rss->chap_len]->size = item->enclosure_length; } mrss_free(feed); return rss; }
mrss_error_t mrss_parse_url_auth(char *url, mrss_t ** ret, char *userpass, long int authtype) { __mrss_download_t *download; nxml_t *doc; mrss_error_t err; if (!url || !ret) { return MRSS_ERR_DATA; } if (!(download = __mrss_download_file_auth(url, __mrss_timeout, userpass, authtype))) { return MRSS_ERR_POSIX; } if (nxml_new(&doc) != NXML_OK) { return MRSS_ERR_POSIX; } if (nxml_parse_buffer(doc, download->mm, download->size) != NXML_OK) { free(download->mm); free(download); nxml_free(doc); return MRSS_ERR_PARSER; } if (!(err = __mrss_parser(doc, ret))) { if (!((*ret)->file = strdup(url))) { free(download->mm); free(download); mrss_free(*ret); nxml_free(doc); return MRSS_ERR_POSIX; } (*ret)->size = download->size; } free(download->mm); free(download); nxml_free(doc); return err; }
mrss_error_t mrss_parse_file (char *file, mrss_t ** ret) { nxml_t *doc; mrss_error_t err; struct stat st; if (!file || !ret) return MRSS_ERR_DATA; if (lstat (file, &st)) return MRSS_ERR_POSIX; if (nxml_new (&doc) != NXML_OK) return MRSS_ERR_POSIX; if (nxml_parse_file (doc, file) != NXML_OK) { nxml_free (doc); return MRSS_ERR_PARSER; } if (!(err = __mrss_parser (doc, ret))) { if (!((*ret)->file = strdup (file))) { nxml_free (doc); mrss_free (*ret); return MRSS_ERR_POSIX; } (*ret)->size = st.st_size; } nxml_free (doc); return err; }
int main(int argc, char *argv[]) { char **url = NULL; int n_url = 0, cur_url = 0; int check_interval = 15 * 60; mrss_t **data_prev = NULL; mrss_t **data_cur = NULL; int data_size; char *proxy = NULL, *proxy_auth = NULL; int sw; int verbose = 0; char show_timestamp = 0, show_link = 0, show_description = 0, show_pubdate = 0, show_author = 0, show_comments = 0; char strip_html = 0, no_error_exit = 0; char one_shot = 0; char no_heading = 0; int bytes_limit = 0; time_t last_changed = (time_t)0; char continue_on_error = 0, dummy; int show_n = -1; long int max_age = -1; char *heading = NULL; mrss_options_t mot; char *auth = NULL; char *current_encoding = NULL; char reverse = 0; iconv_t converter = 0; memset(&mot, 0x00, sizeof(mot)); while((sw = getopt(argc, argv, "A:Z:1b:PHztldrpacu:Ni:n:x:y:vVh")) != -1) { switch(sw) { case 'A': auth = optarg; break; case 'Z': heading = optarg; break; case 'N': no_heading = 1; break; case '1': one_shot = 1; break; case 'b': bytes_limit = atoi(optarg); if (bytes_limit <= 0) { printf("-b requires a number > 0\n"); return 1; } break; case 'P': no_error_exit = 1; break; case 'H': strip_html = 1; break; case 'n': show_n = atoi(optarg); if (show_n < 0) { printf("-n requires an positive value\n"); return 1; } else if (show_n > 50) printf("Initially showing more then 50 items, must be one hell of an rss feed!\n"); break; #if 0 case 'o': dummy = optarg[strlen(optarg) - 1]; max_age = atoi(optarg); if (max_age < 0) { printf("-o requires an positive value\n"); return 1; } if (dummy == 's') max_age *= 1; else if (dummy == 'M') max_age *= 60; else if (dummy == 'h') max_age *= 3600; else if (dummy == 'd') max_age *= 86400; else if (dummy == 'm') max_age *= 86400 * 31; else if (dummy == 'y') max_age *= 86400 * 365.25; else if (isalpha(dummy)) { printf("'%c' is a not recognized multiplier\n", dummy); return 1; } break; #endif case 'z': continue_on_error = 1; break; case 't': show_timestamp = 1; break; case 'l': show_link = 1; break; case 'd': show_description = 1; break; case 'r': reverse = 1; break; case 'p': show_pubdate = 1; break; case 'a': show_author = 1; break; case 'c': show_comments = 1; break; case 'u': url = (char **)realloc(url, sizeof(char *) * (n_url + 1)); if (!url) { fprintf(stderr, "Cannot allocate memory\n"); return 2; } url[n_url++] = optarg; break; case 'i': check_interval = atoi(optarg); break; case 'x': proxy = optarg; break; case 'y': proxy_auth = optarg; break; case 'v': verbose++; break; case 'V': version(); return 1; case 'h': default: usage(); return 1; } } mot.timeout = check_interval; mot.proxy = proxy; mot.proxy_authentication = proxy_auth; mot.user_agent = "rsstail " VERSION ", (C) 2006-2013 by [email protected]"; mot.authentication = auth; if (n_url == 0) { fprintf(stderr, "Please give the URL of the RSS feed to check with the '-u' parameter.\n"); return 1; } data_size = sizeof(mrss_t *) * n_url; data_prev = (mrss_t **)malloc(data_size); data_cur = (mrss_t **)malloc(data_size); if (!data_prev || !data_cur) { fprintf(stderr, "Cannot allocate memory\n"); return 2; } memset(data_prev, 0x00, data_size); memset(data_cur , 0x00, data_size); setlocale(LC_ALL, ""); current_encoding = nl_langinfo(CODESET); if (verbose) { int loop; printf("Monitoring RSS feeds:\n"); for(loop=0; loop<n_url; loop++) printf("\t%s\n", url[loop]); printf("Check interval: %d\n", check_interval); printf("Output current_encoding: %s\n", current_encoding); } for(;;) { mrss_error_t err_read; mrss_item_t *item_cur = NULL; mrss_item_t *first_item[n_url]; mrss_item_t *tmp_first_item; time_t cur_last_changed; int n_shown = 0; if (verbose) printf("Retrieving RSS feed '%s'...\n", url[cur_url]); if ((err_read = mrss_get_last_modified_with_options(url[cur_url], &cur_last_changed, &mot)) != MRSS_OK) { if (err_read == MRSS_ERR_POSIX) { if (errno == EINPROGRESS) { fprintf(stderr, "Time-out while connecting to RSS feed, continuing\n"); goto goto_next_url; } } fprintf(stderr, "Error reading RSS feed: %s\n", mrss_strerror(err_read)); if (no_error_exit) goto goto_next_url; else return 2; } if (cur_last_changed == last_changed && cur_last_changed != 0) { if (verbose) printf("Feed did not change since last check.\n"); goto goto_next_url; } else if (verbose > 2) { printf("Feed change detected, %s", ctime(&cur_last_changed)); } last_changed = cur_last_changed; if ((err_read = mrss_parse_url_with_options(url[cur_url], &data_cur[cur_url], &mot)) != MRSS_OK) { if (err_read == MRSS_ERR_POSIX) { if (errno == EINPROGRESS) { fprintf(stderr, "Time-out while connecting to RSS feed, continuing\n"); goto goto_next_url; } } else if (err_read == MRSS_ERR_PARSER && continue_on_error) { fprintf(stderr, "Error reading RSS feed: %s\n", mrss_strerror(err_read)); goto goto_next_url; } fprintf(stderr, "Error reading RSS feed: %s\n", mrss_strerror(err_read)); if (no_error_exit) goto goto_next_url; else return 2; } if (verbose) printf("Creating converter %s -> %s\n", data_cur[cur_url] -> encoding, current_encoding); converter = iconv_open(current_encoding, data_cur[cur_url] -> encoding); if (converter == (iconv_t) -1) { fprintf(stderr, "Error creating converter: %s \n", strerror(errno)); return 2; } item_cur = data_cur[cur_url] -> item; if (reverse) { if (verbose) printf("Reversing...\n"); mrss_item_t *rev_item_cur = NULL; mrss_item_t *rev_item_last = NULL; for (;;) { rev_item_last = rev_item_cur; rev_item_cur = item_cur; if (item_cur -> next) { item_cur = item_cur -> next; rev_item_cur -> next = rev_item_last; } else { rev_item_cur -> next = rev_item_last; break; } } } tmp_first_item = item_cur; while(item_cur) { if ((data_prev[cur_url] && is_new_record(first_item[cur_url], item_cur) != -1) || (!data_prev[cur_url])) { #if 0 if (/* pubdate */ < max_age && max_age != -1) continue; #endif if ((!data_prev[cur_url]) && n_shown >= show_n && show_n != -1) { item_cur = item_cur -> next; continue; } n_shown++; if ((show_link + show_description + show_pubdate + show_author + show_comments ) > 1) printf("\n"); if (show_timestamp) { time_t now = time(NULL); struct tm *now_tm = localtime(&now); printf("%04d/%02d/%02d %02d:%02d:%02d ", now_tm -> tm_year + 1900, now_tm -> tm_mon + 1, now_tm -> tm_mday, now_tm -> tm_hour, now_tm -> tm_min, now_tm -> tm_sec); } if (heading) { printf(" %s", heading); } if (item_cur -> title != NULL) { char *title = my_convert(converter, item_cur -> title); if (title) { printf("%s%s\n", no_heading?" ":"Title: ", title); free(title); } } if (show_link && item_cur -> link != NULL) { char *link = my_convert(converter, item_cur -> link); if(link) { printf("%s%s\n", no_heading?" ":"Link: ", item_cur -> link); free(link); } } if (show_description && item_cur -> description != NULL) { if (strip_html) { char *stripped = remove_html_tags(item_cur -> description); if (bytes_limit != 0 && bytes_limit < strlen(stripped)) stripped[bytes_limit] = 0x00; char *description = my_convert(converter, stripped); if (description) { printf("%s%s\n", no_heading?" ":"Description: ", description); free(description); } free(stripped); } else { if (bytes_limit != 0 && bytes_limit < strlen(item_cur -> description)) (item_cur -> description)[bytes_limit] = 0x00; char *description = my_convert(converter, item_cur -> description); if (description) { printf("%s%s\n", no_heading?" ":"Description: ", description); free(description); } } } if (show_pubdate && item_cur -> pubDate != NULL) printf("%s%s\n", no_heading?" ":"Pub.date: ", item_cur -> pubDate); if (show_author && item_cur -> author != NULL){ char *author = my_convert(converter, item_cur -> author); if (author) { printf("%s%s\n", no_heading?" ":"Author: ", author); free(author); } } if (show_comments && item_cur -> comments != NULL) { if (bytes_limit != 0 && bytes_limit < strlen(item_cur -> comments)) (item_cur -> comments)[bytes_limit] = 0x00; char *comments = my_convert(converter, item_cur -> comments); if (comments) { printf("%s%s\n", no_heading?" ":"Comments: ", item_cur -> comments); free(comments); } } } item_cur = item_cur -> next; } if (data_prev[cur_url]) { mrss_error_t err_free = mrss_free(data_prev[cur_url]); if (err_free != MRSS_OK) { fprintf(stderr, "Error freeing up memory: %s\n", mrss_strerror(err_read)); if (no_error_exit) goto goto_next_url; else return 2; } } data_prev[cur_url] = data_cur[cur_url]; data_cur[cur_url] = NULL; first_item[cur_url] = tmp_first_item; goto_next_url: if (converter) { iconv_close (converter); converter = 0; } cur_url++; if (cur_url == n_url) cur_url = 0; fflush(stdout); if (one_shot) break; if (verbose > 2) printf("Sleeping...\n"); sleep(check_interval / n_url); } return 0; }
static mrss_error_t __mrss_parser_rss (mrss_version_t v, nxml_t * doc, nxml_data_t * cur, mrss_t ** ret) { mrss_t *data; char *c, *attr; if (!(data = (mrss_t *) malloc (sizeof (mrss_t)))) return MRSS_ERR_POSIX; memset (data, 0, sizeof (mrss_t)); data->element = MRSS_ELEMENT_CHANNEL; data->allocated = 1; data->version = v; if (doc->encoding && !(data->encoding = strdup (doc->encoding))) { mrss_free (data); return MRSS_ERR_POSIX; } if (data->version == MRSS_VERSION_1_0) { nxml_data_t *cur_channel = NULL; while (cur) { if (!strcmp (cur->value, "channel")) cur_channel = cur; else if (!strcmp (cur->value, "image")) __mrss_parser_rss_image (doc, cur, data); else if (!strcmp (cur->value, "textinput")) __mrss_parser_rss_textinput (doc, cur, data); else if (!strcmp (cur->value, "item")) __mrss_parser_rss_item (doc, cur, data); cur = cur->next; } cur = cur_channel; } else { while (cur && strcmp (cur->value, "channel")) cur = cur->next; } if (!cur) { mrss_free (data); return MRSS_ERR_PARSER; } if (data->version == MRSS_VERSION_1_0) { if ((attr = nxmle_find_attribute (cur, "about", NULL))) data->about = attr; } for (cur = cur->children; cur; cur = cur->next) { if (cur->type == NXML_TYPE_ELEMENT) { /* title */ if (!strcmp (cur->value, "title") && !data->title && (c = nxmle_get_string (cur, NULL))) data->title = c; /* description */ else if (!strcmp (cur->value, "description") && !data->description && (c = nxmle_get_string (cur, NULL))) data->description = c; /* link */ else if (!strcmp (cur->value, "link") && !data->link && (c = nxmle_get_string (cur, NULL))) data->link = c; /* language */ else if (!strcmp (cur->value, "language") && !data->language && (c = nxmle_get_string (cur, NULL))) data->language = c; /* rating */ else if (!strcmp (cur->value, "rating") && !data->rating && (c = nxmle_get_string (cur, NULL))) data->rating = c; /* copyright */ else if (!strcmp (cur->value, "copyright") && !data->copyright && (c = nxmle_get_string (cur, NULL))) data->copyright = c; /* pubDate */ else if (!strcmp (cur->value, "pubDate") && !data->pubDate && (c = nxmle_get_string (cur, NULL))) data->pubDate = c; /* lastBuildDate */ else if (!strcmp (cur->value, "lastBuildDate") && !data->lastBuildDate && (c = nxmle_get_string (cur, NULL))) data->lastBuildDate = c; /* docs */ else if (!strcmp (cur->value, "docs") && !data->docs && (c = nxmle_get_string (cur, NULL))) data->docs = c; /* managingeditor */ else if (!strcmp (cur->value, "managingeditor") && !data->managingeditor && (c = nxmle_get_string (cur, NULL))) data->managingeditor = c; /* webMaster */ else if (!strcmp (cur->value, "webMaster") && !data->webMaster && (c = nxmle_get_string (cur, NULL))) data->webMaster = c; /* image */ else if (!strcmp (cur->value, "image")) __mrss_parser_rss_image (doc, cur, data); /* textinput */ else if (!strcmp (cur->value, "textinput")) __mrss_parser_rss_textinput (doc, cur, data); /* skipHours */ else if (!strcmp (cur->value, "skipHours")) __mrss_parser_rss_skipHours (doc, cur, data); /* skipDays */ else if (!strcmp (cur->value, "skipDays")) __mrss_parser_rss_skipDays (doc, cur, data); /* item */ else if (!strcmp (cur->value, "item")) __mrss_parser_rss_item (doc, cur, data); /* category */ else if (!strcmp (cur->value, "category") && (c = nxmle_get_string (cur, NULL))) { mrss_category_t *category; if (! (category = (mrss_category_t *) malloc (sizeof (mrss_category_t)))) { mrss_free ((mrss_generic_t *) data); free (c); return MRSS_ERR_POSIX; } memset (category, 0, sizeof (mrss_category_t)); category->element = MRSS_ELEMENT_CATEGORY; category->allocated = 1; category->category = c; if ((attr = nxmle_find_attribute (cur, "domain", NULL))) category->domain = attr; if (!data->category) data->category = category; else { mrss_category_t *tmp; tmp = data->category; while (tmp->next) tmp = tmp->next; tmp->next = category; } } /* enclosure */ else if (!strcmp (cur->value, "cloud") && !data->cloud) { data->cloud = nxmle_get_string (cur, NULL); if (!data->cloud_domain && (attr = nxmle_find_attribute (cur, "domain", NULL))) data->cloud_domain = attr; if (!data->cloud_port && (attr = nxmle_find_attribute (cur, "port", NULL))) data->cloud_port = atoi (attr); if (!data->cloud_registerProcedure && (attr = nxmle_find_attribute (cur, "registerProcedure", NULL))) data->cloud_registerProcedure = attr; if (!data->cloud_protocol && (attr = nxmle_find_attribute (cur, "protocol", NULL))) data->cloud_protocol = attr; } /* generator */ else if (!strcmp (cur->value, "generator") && !data->generator && (c = nxmle_get_string (cur, NULL))) data->generator = c; /* ttl */ else if (!strcmp (cur->value, "ttl") && !data->ttl && (c = nxmle_get_string (cur, NULL))) { data->ttl = atoi (c); free (c); } } } *ret = data; return MRSS_OK; }
int main (int argc, char **argv) { mrss_t *data; mrss_error_t ret; char *buffer; int i; data = NULL; fprintf (stdout, "New data... "); ret = mrss_new (&data); check (ret); fprintf (stdout, "Set some values... "); ret = mrss_set (data, MRSS_FLAG_VERSION, MRSS_VERSION_2_0, MRSS_FLAG_TITLE, "a title", MRSS_FLAG_DESCRIPTION, "a description", MRSS_FLAG_LINK, "a link", MRSS_FLAG_LANGUAGE, "it_IT", MRSS_FLAG_RATING, "rating", MRSS_FLAG_COPYRIGHT, "the copyright", MRSS_FLAG_PUBDATE, "today", MRSS_FLAG_LASTBUILDDATE, "yesterday", MRSS_FLAG_DOCS, "http://autistici.org/bakunin", MRSS_FLAG_MANAGINGEDITOR, "vim", MRSS_FLAG_WEBMASTER, "b", MRSS_FLAG_GENERATOR, "none!", MRSS_FLAG_TTL, 255, MRSS_FLAG_IMAGE_TITLE, "title of the image", MRSS_FLAG_IMAGE_URL, "http://autistici.org/bakunin/img.png", MRSS_FLAG_IMAGE_LINK, "http://autistici.org/bakunin/", MRSS_FLAG_IMAGE_WIDTH, 1000, MRSS_FLAG_IMAGE_HEIGHT, 2000, MRSS_FLAG_IMAGE_DESCRIPTION, "no image description", MRSS_FLAG_TEXTINPUT_TITLE, "textinput title", MRSS_FLAG_TEXTINPUT_DESCRIPTION, "textinput description", MRSS_FLAG_TEXTINPUT_NAME, "textinput name", MRSS_FLAG_TEXTINPUT_LINK, "http://autistici.org/bakunin", MRSS_FLAG_CLOUD, "Cloud!", MRSS_FLAG_CLOUD_DOMAIN, "autistici.org", MRSS_FLAG_CLOUD_PORT, 8080, MRSS_FLAG_CLOUD_PATH, "/bakunin/rss", MRSS_FLAG_CLOUD_REGISTERPROCEDURE, "none", MRSS_FLAG_CLOUD_PROTOCOL, "gopher", MRSS_FLAG_END); check (ret); for (i = 0; i < 10; i++) { mrss_hour_t *hour = NULL; char s[1024]; fprintf (stdout, "New skipHours element... "); ret = mrss_new_subdata (data, MRSS_ELEMENT_SKIPHOURS, &hour); check (ret); snprintf (s, sizeof (s), "Element %d", i); fprintf (stdout, "Set skipHours value... "); ret = mrss_set (hour, MRSS_FLAG_HOUR, s, MRSS_FLAG_END); check (ret); } for (i = 0; i < 10; i++) { mrss_day_t *day = NULL; char s[1024]; fprintf (stdout, "New skipDays element... "); ret = mrss_new_subdata (data, MRSS_ELEMENT_SKIPDAYS, &day); check (ret); snprintf (s, sizeof (s), "Element %d", i); fprintf (stdout, "Set skipDays value... "); ret = mrss_set (day, MRSS_FLAG_DAY, s, MRSS_FLAG_END); check (ret); } for (i = 0; i < 10; i++) { mrss_category_t *category = NULL; char s1[1024]; char s2[1024]; fprintf (stdout, "New category element... "); ret = mrss_new_subdata (data, MRSS_ELEMENT_CATEGORY, &category); check (ret); snprintf (s1, sizeof (s1), "Element %d", i); snprintf (s2, sizeof (s2), "Domain %d", i); fprintf (stdout, "Set category values... "); ret = mrss_set (category, MRSS_FLAG_CATEGORY, s1, MRSS_FLAG_CATEGORY_DOMAIN, s2, MRSS_FLAG_END); check (ret); } for (i = 0; i < 10; i++) { mrss_tag_t *tag = NULL; char s1[1024]; char s2[1024]; char s3[1024]; fprintf (stdout, "New tag element... "); ret = mrss_new_subdata (data, MRSS_ELEMENT_TAG, &tag); check (ret); snprintf (s1, sizeof (s1), "Element %d", i); snprintf (s2, sizeof (s2), "element_%d", i); snprintf (s3, sizeof (s3), "http://www.something.net/"); fprintf (stdout, "Set tag value... "); ret = mrss_set (tag, MRSS_FLAG_TAG_NAME, s2, MRSS_FLAG_TAG_VALUE, s1, MRSS_FLAG_TAG_NS, s3, MRSS_FLAG_END); check (ret); } for (i = 0; i < 10; i++) { mrss_item_t *item = NULL; int j; fprintf (stdout, "New item element... "); ret = mrss_new_subdata (data, MRSS_ELEMENT_ITEM, &item); check (ret); fprintf (stdout, "Set item values... "); ret = mrss_set (item, MRSS_FLAG_ITEM_TITLE, "item title", MRSS_FLAG_ITEM_LINK, "item link", MRSS_FLAG_ITEM_DESCRIPTION, "item description", MRSS_FLAG_ITEM_AUTHOR, "item author", MRSS_FLAG_ITEM_COMMENTS, "item comments", MRSS_FLAG_ITEM_PUBDATE, "item pubdate", MRSS_FLAG_ITEM_GUID, "item guid", MRSS_FLAG_ITEM_GUID_ISPERMALINK, 1 /* 0 is false */ , MRSS_FLAG_ITEM_SOURCE, "item source", MRSS_FLAG_ITEM_SOURCE_URL, "item source url", MRSS_FLAG_ITEM_ENCLOSURE, "item enclosure", MRSS_FLAG_ITEM_ENCLOSURE_URL, "item enclosure url", MRSS_FLAG_ITEM_ENCLOSURE_LENGTH, 1234, MRSS_FLAG_ITEM_ENCLOSURE_TYPE, "item enclosure type", MRSS_FLAG_END); for (j = 0; j < 10; j++) { mrss_category_t *category = NULL; char s1[1024]; char s2[1024]; fprintf (stdout, "New category element... "); ret = mrss_new_subdata (item, MRSS_ELEMENT_CATEGORY, &category); check (ret); snprintf (s1, sizeof (s1), "Element %d", j); snprintf (s2, sizeof (s2), "Domain %d", j); fprintf (stdout, "Set category values... "); ret = mrss_set (category, MRSS_FLAG_CATEGORY, s1, MRSS_FLAG_CATEGORY_DOMAIN, s2, MRSS_FLAG_END); check (ret); } for (i = 0; i < 10; i++) { mrss_tag_t *tag = NULL; char s1[1024]; char s2[1024]; char s3[1024]; int j; fprintf (stdout, "New tag element... "); ret = mrss_new_subdata (item, MRSS_ELEMENT_TAG, &tag); check (ret); snprintf (s1, sizeof (s1), "Element %d", i); snprintf (s2, sizeof (s2), "element_%d", i); snprintf (s3, sizeof (s3), "http://www.something%d.net/", i); fprintf (stdout, "Set tag value... "); ret = mrss_set (tag, MRSS_FLAG_TAG_NAME, s2, MRSS_FLAG_TAG_VALUE, s1, MRSS_FLAG_TAG_NS, s3, MRSS_FLAG_END); check (ret); for (j = 0; j < 10; j++) { mrss_attribute_t *attribute = NULL; char s1[1024]; char s2[1024]; char s3[1024]; fprintf (stdout, "New attribute element... "); ret = mrss_new_subdata (tag, MRSS_ELEMENT_ATTRIBUTE, &attribute); check (ret); snprintf (s1, sizeof (s1), "Element %d", j); snprintf (s2, sizeof (s2), "element_%d", j); snprintf (s3, sizeof (s3), "http://www.something%d.net/", j); fprintf (stdout, "Set attribute value... "); ret = mrss_set (attribute, MRSS_FLAG_ATTRIBUTE_NAME, s2, MRSS_FLAG_ATTRIBUTE_VALUE, s1, MRSS_FLAG_ATTRIBUTE_NS, s3, MRSS_FLAG_END); check (ret); } } check (ret); } buffer = NULL; fprintf (stdout, "Create the RSS in memory... "); ret = mrss_write_buffer (data, &buffer); check (ret); puts (buffer); free (buffer); mrss_free (data); return 0; }
/* todo: save podcast episodes to db rather than loading them every time */ char *load_episodes() { int i; int podcast_uris_num; char **podcast_uris = select_podcasts(&podcast_uris_num); mrss_t *feed; mrss_item_t *episode; mrss_tag_t *other_tags; json_t *jsn_podcasts_obj = json_object(); json_t *jsn_podcasts_arr = json_array(); for (i = 0; i < podcast_uris_num; i++) { mrss_parse_url_with_options_and_error(podcast_uris[i], &feed, NULL, NULL); json_t *jsn_podcast_obj = json_object(); json_object_set_new(jsn_podcast_obj, "title", json_string(feed->title)); json_t *jsn_episodes_arr = json_array(); episode = feed->item; while (episode) { struct tm tm_publish; time_t time_now, time_publish; memset(&tm_publish, 0, sizeof(struct tm)); time(&time_now); /* episode->pubDate is formated like e.g. Sat, 30 Jul 2016 00:00:00 +0200 when parsing the datetime string only year, month and day will be used for windows something like e.g. char month[4]; int day, year; sscanf(episode->pubDate, "%*s %d %s %d %*d:%*d:%*d %*s", &day, month, &year); could be used instead of relying on strptime */ /* time string format like "Sat, 06 Aug 2016 08:14:24 +0200" */ if (strptime(episode->pubDate, "%a, %0d %b %Y %T %z", &tm_publish) != NULL) { double time_diff = difftime(time_now, mktime(&tm_publish)); if (time_diff / 86400.0 > 30.0) { break; } } /* time string format like "Sat, 30 Jul 2016 01:00:00 GMT" */ else if (strptime(episode->pubDate, "%a, %0d %b %Y %T %Z", &tm_publish) != NULL) { double time_diff = difftime(time_now, mktime(&tm_publish)); if (time_diff / 86400.0 > 30.0) { break; } } else { printf("unsopported time format: %s\n", episode->pubDate); break; } json_t *jsn_episode_obj = json_object(); json_object_set_new(jsn_episode_obj, "title", json_string(episode->title)); json_object_set_new(jsn_episode_obj, "description", json_string(episode->description)); json_object_set_new(jsn_episode_obj, "stream_uri", json_string(episode->enclosure_url)); if (episode->other_tags) { other_tags = episode->other_tags; while (other_tags) { if (strcmp(other_tags->name, "duration") == 0) { json_object_set_new(jsn_episode_obj, "duration", json_string(other_tags->value)); } other_tags = other_tags->next; } } episode = episode->next; json_array_append_new(jsn_episodes_arr, jsn_episode_obj); } mrss_free(feed); json_object_set_new(jsn_podcast_obj, "episodes", jsn_episodes_arr); json_array_append_new(jsn_podcasts_arr, jsn_podcast_obj); free(podcast_uris[i]); } free(podcast_uris); json_object_set_new(jsn_podcasts_obj, "podcasts", jsn_podcasts_arr); return json_dumps(jsn_podcasts_obj, JSON_COMPACT); }
static mrss_error_t __mrss_parser_atom (nxml_t * doc, nxml_data_t * cur, mrss_t ** ret) { mrss_t *data; char *c = NULL; if (!(data = malloc (sizeof (mrss_t)))) return MRSS_ERR_POSIX; memset (data, 0, sizeof (mrss_t)); data->element = MRSS_ELEMENT_CHANNEL; data->allocated = 1; data->version = MRSS_VERSION_ATOM_1_0; if (doc->encoding && !(data->encoding = strdup (doc->encoding))) { mrss_free (data); return MRSS_ERR_POSIX; } if (!data->language && (c = nxmle_find_attribute (cur, "xml:lang", NULL))) data->language = c; if ((c = nxmle_find_attribute (cur, "version", NULL))) { if (!strcmp (c, "0.3")) data->version = MRSS_VERSION_ATOM_0_3; free (c); } for (cur = cur->children; cur; cur = cur->next) { if (cur->type == NXML_TYPE_ELEMENT) { /* title -> title */ if (!strcmp (cur->value, "title") && !data->title && (c = nxmle_get_string (cur, NULL))) data->title = c; /* subtitle -> description */ else if (!strcmp (cur->value, "subtitle") && data->version == MRSS_VERSION_ATOM_1_0 && !data->description && (c = nxmle_get_string (cur, NULL))) data->description = c; /* tagline -> description (Atom 0.3) */ else if (!strcmp (cur->value, "tagline") && data->version == MRSS_VERSION_ATOM_0_3 && !data->description && (c = nxmle_get_string (cur, NULL))) data->description = c; /* link href -> link */ else if (!strcmp (cur->value, "link") && !data->link && (c = nxmle_find_attribute (cur, "href", NULL))) data->link = c; /* id -> id */ else if (!strcmp (cur->value, "id") && !data->id && (c = nxmle_get_string (cur, NULL))) data->id = c; /* rights -> copyright */ else if (!strcmp (cur->value, "rights") && !data->copyright && (c = nxmle_get_string (cur, NULL))) data->copyright = c; /* updated -> lastBuildDate */ else if (!strcmp (cur->value, "updated") && (c = nxmle_get_string (cur, NULL))) { data->lastBuildDate = __mrss_atom_prepare_date (data, c); free (c); } /* author -> managingeditor */ else if (!strcmp (cur->value, "author")) __mrss_parser_atom_author (cur, &data->managingeditor, &data->managingeditor_email, &data->managingeditor_uri); /* contributor */ else if (!strcmp (cur->value, "contributor")) __mrss_parser_atom_author (cur, &data->contributor, &data->contributor_email, &data->contributor_uri); /* generator -> generator */ else if (!strcmp (cur->value, "generator") && !data->generator && (c = nxmle_get_string (cur, NULL))) { char *attr; data->generator = c; if ((attr = nxmle_find_attribute (cur, "uri", NULL))) data->generator_uri = attr; if ((attr = nxmle_find_attribute (cur, "version", NULL))) data->generator_version = attr; } /* icon -> image_url */ else if (!strcmp (cur->value, "icon") && !data->image_url && (c = nxmle_get_string (cur, NULL))) data->image_url = c; /* logo -> image_logo */ else if (!strcmp (cur->value, "logo") && !data->image_logo && (c = nxmle_get_string (cur, NULL))) data->image_logo = c; /* category */ else if (!strcmp (cur->value, "category")) __mrss_parser_atom_category (cur, &data->category); /* entry -> item */ else if (!strcmp (cur->value, "entry")) __mrss_parser_atom_entry (doc, cur, data); else { mrss_tag_t *tag; if ((tag = __mrss_parse_tag (doc, cur))) __mrss_parse_tag_insert (&data->other_tags, tag); } } } *ret = data; return MRSS_OK; }
static mrss_tag_t * __mrss_parse_tag (nxml_t * doc, nxml_data_t * cur) { mrss_tag_t *tag; mrss_attribute_t *attribute; nxml_attr_t *nxml_attr; if (!(tag = (mrss_tag_t *) calloc (1, sizeof (mrss_tag_t)))) return NULL; tag->element = MRSS_ELEMENT_TAG; tag->allocated = 1; if (!(tag->name = strdup (cur->value))) { mrss_free (tag); return NULL; } if (cur->ns && cur->ns->ns && !(tag->ns = strdup (cur->ns->ns))) { mrss_free (tag); return NULL; } for (nxml_attr = cur->attributes; nxml_attr; nxml_attr = nxml_attr->next) { if (! (attribute = (mrss_attribute_t *) calloc (1, sizeof (mrss_attribute_t)))) return NULL; attribute->element = MRSS_ELEMENT_ATTRIBUTE; attribute->allocated = 1; if (!(attribute->name = strdup (nxml_attr->name))) { mrss_free (tag); return NULL; } if (!(attribute->value = strdup (nxml_attr->value))) { mrss_free (tag); return NULL; } if (nxml_attr->ns && nxml_attr->ns->ns && !(attribute->ns = strdup (nxml_attr->ns->ns))) { mrss_free (tag); return NULL; } if (!tag->attributes) tag->attributes = attribute; else { mrss_attribute_t *tmp = tag->attributes; while (tmp->next) tmp = tmp->next; tmp->next = attribute; } } for (cur = cur->children; cur; cur = cur->next) { if (cur->type == NXML_TYPE_TEXT) { if (!tag->value && !(tag->value = strdup (cur->value))) { mrss_free (tag); return NULL; } } else if (cur->type == NXML_TYPE_ELEMENT) { mrss_tag_t *child = __mrss_parse_tag (doc, cur); if (child) __mrss_parse_tag_insert (&tag->children, child); } } return tag; }
mrss_error_t mrss_parse_url_with_options_and_error (char *url, mrss_t ** ret, mrss_options_t * options, CURLcode * code) { nxml_t *doc; mrss_error_t err; char *buffer; size_t size; if (!url || !ret) return MRSS_ERR_DATA; if (nxml_new (&doc) != NXML_OK) return MRSS_ERR_POSIX; if (options) { if (options->timeout >= 0) nxml_set_timeout (doc, options->timeout); if (options->proxy) nxml_set_proxy (doc, options->proxy, options->proxy_authentication); if (options->authentication) nxml_set_authentication (doc, options->authentication); if (options->user_agent) nxml_set_user_agent (doc, options->user_agent); nxml_set_certificate (doc, options->certfile, options->password, options->cacert, options->verifypeer); } if (!(buffer = __mrss_download_file (doc, url, &size, &err, code))) return err; if (nxml_parse_buffer (doc, buffer, size) != NXML_OK) { free (buffer); nxml_free (doc); return MRSS_ERR_PARSER; } if (!(err = __mrss_parser (doc, ret))) { if (!((*ret)->file = strdup (url))) { free (buffer); mrss_free (*ret); nxml_free (doc); return MRSS_ERR_POSIX; } (*ret)->size = size; } free (buffer); nxml_free (doc); return err; }