Der Code erklaert sich von selbst ;)
feed.h:
1 struct feed_entry 2 { 3 char *title; 4 char *link; 5 char *published; 6 char *updated; 7 char *id; 8 char *author; 9 char *author_name; 10 char *author_email; 11 char *summary; 12 }; 13 14 struct feed_handler 15 { 16 char *url; 17 void *feed_function; 18 void *userdata; 19 struct feed_handler *next; 20 }; 21 22 extern void feed_single_parse(char *url, void *feed_function, void 23 *userdata); 24 extern void feed_free_entry(struct feed_entry *fe); 25 extern struct feed_handler *feed_add(struct feed_handler *fh, char *url, 26 void *feed_function, void *userdata); 27 extern void feed_multi_parse(struct feed_handler *fh); 28 extern void feed_cleanup(struct feed_handler *fh);
feed.c:
1 #include <stdio.h> 2 #include <string.h> 3 #include <strings.h> 4 #include <curl/curl.h> 5 #include <libxml/parser.h> 6 #include <libxml/xmlerror.h> 7 8 #include "feed.h" 9 10 11 enum _feed_progress 12 { 13 NONE, 14 FEED_AUTHOR, 15 FEED_TITLE, 16 FEED_ID, 17 FEED_UPDATED, 18 ENTRY_BEGIN, 19 ENTRY, 20 TITLE, 21 LINK, 22 PUBLISHED, 23 UPDATED, 24 ID, 25 AUTHOR_BEGIN, 26 AUTHOR, 27 AUTHOR_NAME, 28 AUTHOR_EMAIL, 29 AUTHOR_END, 30 SUMMARY, 31 ENTRY_END 32 }; 33 34 struct _feed_userdata 35 { 36 enum _feed_progress feed_entry_progress; 37 struct feed_entry *feed_entry; 38 void (*feed_function)(void*, void*); 39 void *userdata; 40 }; 41 42 struct _multi_handler 43 { 44 xmlParserCtxtPtr ctxt; 45 CURL *hnd; 46 struct _feed_userdata *fu; 47 struct _multi_handler *next; 48 }; 49 50 51 static char *__join_together(char *a, char *b, int len_b) 52 { 53 int len = len_b+1; 54 int len_a = 0; 55 int i; 56 char *txt; 57 58 if (a != NULL) 59 len_a = strlen(a); 60 61 len += len_a; 62 63 txt = malloc(sizeof(char)*len); 64 65 for (i = 0; i < len_a; i++) 66 txt[i] = a[i]; 67 68 for (i = 0; i < len_b; i++) 69 txt[i+len_a] = b[i]; 70 71 txt[len-1] = '\0'; 72 73 if (a != NULL) 74 free(a); 75 76 return txt; 77 } 78 79 80 char *__extract_attribute(int nb_attributes, const xmlChar ** attributes, 81 char *attribute, char *a) 82 { 83 for (int i = 0; i < nb_attributes; i++) 84 if (!strcmp((char*)attributes[i*5], attribute)) 85 return __join_together(a, (char*)attributes[(i*5)+3], attributes[(i*5) 86 +4] - attributes[(i*5)+3]); 87 88 return NULL; 89 } 90 size_t _chunk_parse(void *ptr, size_t size, size_t nmemb, xmlParserCtxtPtr 91 ctxt) 92 { 93 char *txt = ptr; 94 95 xmlParseChunk(ctxt, txt, size*nmemb, 0); 96 97 return nmemb*size; 98 } 99 100 101 void _set_chnd(CURL *hnd, char *url, void *cbfunction, void *userdata) 102 { 103 curl_easy_setopt(hnd, CURLOPT_INFILESIZE_LARGE, (curl_off_t)-1); 104 curl_easy_setopt(hnd, CURLOPT_URL, url); 105 curl_easy_setopt(hnd, CURLOPT_NOPROGRESS, 1); 106 curl_easy_setopt(hnd, CURLOPT_FAILONERROR, 0); 107 curl_easy_setopt(hnd, CURLOPT_USERAGENT, "libmessage"); 108 curl_easy_setopt(hnd, CURLOPT_RESUME_FROM_LARGE, (curl_off_t)0); 109 curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50); 110 curl_easy_setopt(hnd, CURLOPT_SSLVERSION, 0); 111 curl_easy_setopt(hnd, CURLOPT_TIMECONDITION, 0); 112 curl_easy_setopt(hnd, CURLOPT_TIMEVALUE, 0); 113 curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, NULL); 114 curl_easy_setopt(hnd, CURLOPT_CONNECTTIMEOUT, 0); 115 curl_easy_setopt(hnd, CURLOPT_HTTPAUTH, 1); 116 curl_easy_setopt(hnd, CURLOPT_ENCODING, NULL); 117 curl_easy_setopt(hnd, CURLOPT_IPRESOLVE, 0); 118 curl_easy_setopt(hnd, CURLOPT_IGNORE_CONTENT_LENGTH, 0); 119 curl_easy_setopt(hnd, CURLOPT_POSTREDIR, 0); 120 curl_easy_setopt(hnd, CURLOPT_WRITEFUNCTION, cbfunction); 121 curl_easy_setopt(hnd, CURLOPT_WRITEDATA, userdata); 122 123 } 124 125 int _get_feed(char *url, void *cbfunction, void *userdata) 126 { 127 CURLcode ret; 128 129 curl_global_init(CURL_GLOBAL_ALL); 130 131 CURL *hnd = curl_easy_init(); 132 133 _set_chnd(hnd, url, cbfunction, userdata); 134 135 ret = curl_easy_perform(hnd); 136 curl_easy_cleanup(hnd); 137 138 curl_global_cleanup(); 139 return (int)ret; 140 141 } 142 143 void _feed_charactersSAX(void *userdata, const xmlChar *characters, int len) 144 { 145 char *ch = (char*)characters; 146 struct _feed_userdata *fu = userdata; 147 148 #ifdef STRICT 149 if (fu->feed_entry_progress != NONE && fu->feed_entry == NULL) 150 { 151 exit(1); 152 } 153 #endif 154 /* 155 for (int i = 0; i < len; i++) 156 printf("%c", ch[i]); 157 printf("\n"); 158 */ 159 if (fu->feed_entry_progress == TITLE) 160 fu->feed_entry->title = __join_together(fu->feed_entry->title, ch, len); 161 else if (fu->feed_entry_progress == PUBLISHED) 162 fu->feed_entry->published = __join_together(fu->feed_entry->published, 163 ch, len); 164 else if (fu->feed_entry_progress == UPDATED) 165 fu->feed_entry->updated = __join_together(fu->feed_entry->updated, ch, 166 len); 167 else if (fu->feed_entry_progress == ID) 168 fu->feed_entry->id = __join_together(fu->feed_entry->id, ch, len); 169 else if (fu->feed_entry_progress == SUMMARY) 170 fu->feed_entry->summary = __join_together(fu->feed_entry->summary, ch, 171 len); 172 else if (fu->feed_entry_progress == LINK) 173 fu->feed_entry->link = __join_together(fu->feed_entry->link, ch, len); 174 175 else if (fu->feed_entry_progress == AUTHOR) 176 fu->feed_entry->author = __join_together(fu->feed_entry->author, ch, 177 len); 178 else if (fu->feed_entry_progress == AUTHOR_NAME) 179 fu->feed_entry->author_name = __join_together(fu->feed_entry-> 180 author_name, ch, len); 181 else if (fu->feed_entry_progress == AUTHOR_EMAIL) 182 fu->feed_entry->author_email= __join_together(fu->feed_entry-> 183 author_email, ch, len); 184 185 } 186 187 void _feed_startElementSAX(void *userdata, const xmlChar *characters, 188 const xmlChar * prefix, 189 const xmlChar * URI, 190 int nb_namespaces, 191 const xmlChar ** namespaces, 192 int nb_attributes, 193 int nb_defaulted, 194 const xmlChar ** attributes ) 195 { 196 char *ch = (char*)characters; 197 struct _feed_userdata *fu = userdata; 198 199 //printf("-------------<%s>---------------\n", ch); 200 201 if (!strncasecmp(ch, "entry", 6) || !strncasecmp(ch, "item", 5)) 202 { 203 //printf("entry opened\n"); 204 fu->feed_entry = malloc(sizeof(struct feed_entry)); 205 memset(fu->feed_entry, 0, sizeof(struct feed_entry)); 206 fu->feed_entry_progress = ENTRY; 207 } 208 209 if (fu->feed_entry_progress < ENTRY_END && fu->feed_entry_progress > 210 ENTRY_BEGIN) 211 { 212 if (!strncasecmp(ch, "title", 6)) 213 fu->feed_entry_progress = TITLE; 214 else if (!strncasecmp(ch, "link", 5)) 215 { 216 fu->feed_entry_progress = LINK; 217 fu->feed_entry->link = __extract_attribute(nb_attributes, 218 attributes, "href", fu->feed_entry->link); 219 } 220 else if (!strncasecmp(ch, "published", 10)) 221 fu->feed_entry_progress = PUBLISHED; 222 else if (!strncasecmp(ch, "updated", 8)) 223 fu->feed_entry_progress = UPDATED; 224 else if (!strncasecmp(ch, "id", 3)) 225 fu->feed_entry_progress = ID; 226 else if (!strncasecmp(ch, "author", 7)) 227 fu->feed_entry_progress = AUTHOR; 228 else if (!strncasecmp(ch, "summary", 8) || !strncasecmp(ch, 229 "description", 12)) 230 fu->feed_entry_progress = SUMMARY; 231 232 if (fu->feed_entry_progress < AUTHOR_END && fu->feed_entry_progress > 233 AUTHOR_BEGIN) 234 { 235 if (!strncasecmp(ch, "name", 5)) 236 { 237 fu->feed_entry_progress = AUTHOR_NAME; 238 if (fu->feed_entry->author != NULL) 239 { 240 free(fu->feed_entry->author); 241 fu->feed_entry->author = NULL; 242 } 243 244 } 245 if (!strncasecmp(ch, "email", 6)) 246 { 247 fu->feed_entry_progress = AUTHOR_EMAIL; 248 if (fu->feed_entry->author != NULL) 249 { 250 free(fu->feed_entry->author); 251 fu->feed_entry->author = NULL; 252 } 253 } 254 } 255 } 256 257 } 258 void _feed_endElementSAX(void *userdata, const xmlChar *characters, 259 const xmlChar * prefix, 260 const xmlChar * URI ) 261 { 262 char *ch = (char*)characters; 263 struct _feed_userdata *fu = userdata; 264 265 266 if (fu->feed_entry_progress < ENTRY_END && fu->feed_entry_progress > 267 ENTRY_BEGIN) 268 { 269 if (!strncasecmp(ch, "entry", 6) || !strncasecmp(ch, "item", 5)) 270 { 271 fu->feed_function(fu->feed_entry, fu->userdata); 272 fu->feed_entry_progress = ENTRY_END; 273 } 274 else if (!strncasecmp(ch, "author", 7)) 275 fu->feed_entry_progress = AUTHOR_END; 276 else 277 fu->feed_entry_progress = ENTRY; 278 279 } 280 if (fu->feed_entry_progress < AUTHOR_END && fu->feed_entry_progress > 281 AUTHOR_BEGIN) 282 fu->feed_entry_progress = AUTHOR_BEGIN; 283 } 284 285 286 void feed_single_parse(char *url, void *feed_function, void *userdata) 287 { 288 struct _feed_userdata fu; 289 xmlParserCtxtPtr ctxt; 290 xmlSAXHandler xsh; 291 memset(&xsh, 0, sizeof(xmlSAXHandler)); 292 293 fu.feed_entry_progress = NONE; 294 fu.feed_entry = NULL; 295 fu.feed_function = feed_function; 296 fu.userdata = userdata; 297 298 xsh.initialized = XML_SAX2_MAGIC; 299 xsh.characters = _feed_charactersSAX; 300 xsh.startElementNs = _feed_startElementSAX; 301 xsh.endElementNs = _feed_endElementSAX; 302 303 ctxt = xmlCreatePushParserCtxt(&xsh, &fu, NULL, 0, NULL); 304 305 _get_feed(url, _chunk_parse, ctxt); 306 307 xmlParseChunk(ctxt, "", 0, 1); 308 309 xmlFreeParserCtxt(ctxt); 310 311 if (fu.feed_entry_progress != ENTRY_END && fu.feed_entry != NULL) 312 fu.feed_function(fu.feed_entry, fu.userdata); 313 } 314 315 extern struct feed_handler *feed_add(struct feed_handler *fh, char *url, 316 void *feed_function, void *userdata) 317 { 318 struct feed_handler *fhn = malloc(sizeof(struct feed_handler)); 319 320 fhn->url = url; 321 fhn->feed_function = feed_function; 322 fhn->userdata = userdata; 323 fhn->next = NULL; 324 325 if (fh == NULL) 326 return fhn; 327 328 while (fh->next != NULL) 329 fh = fh->next; 330 fh->next = fhn; 331 332 return NULL; 333 } 334 335 extern void feed_cleanup(struct feed_handler *fh) 336 { 337 struct feed_handler *fhn; 338 339 while (fh->next) 340 { 341 fhn = fh->next; 342 free(fh); 343 fh = fhn; 344 345 } 346 347 free(fh); 348 } 349 350 extern void feed_multi_parse(struct feed_handler *fh) 351 { 352 struct _multi_handler *mh_tmp, *mh; 353 xmlSAXHandler xsh; 354 int handles = 1; 355 356 357 CURL *mhnd = curl_multi_init(); 358 359 360 memset(&xsh, 0, sizeof(xmlSAXHandler)); 361 xsh.initialized = XML_SAX2_MAGIC; 362 xsh.characters = _feed_charactersSAX; 363 xsh.startElementNs = _feed_startElementSAX; 364 xsh.endElementNs = _feed_endElementSAX; 365 366 mh = malloc(sizeof(struct _multi_handler)); 367 mh_tmp = mh; 368 369 // wenn kaputt, dann mh und fh vereinen 370 371 while (fh != NULL) 372 { 373 mh->next = NULL; 374 375 mh->fu = malloc(sizeof(struct _feed_userdata)); 376 mh->fu->feed_entry_progress = NONE; 377 mh->fu->feed_entry = NULL; 378 mh->fu->feed_function = fh->feed_function; 379 mh->fu->userdata = fh->userdata; 380 381 mh->ctxt = xmlCreatePushParserCtxt(&xsh, mh->fu, NULL, 0, NULL); 382 383 mh->hnd = curl_easy_init(); 384 _set_chnd(mh->hnd, fh->url, _chunk_parse, mh->ctxt); 385 386 curl_multi_add_handle(mhnd, mh->hnd); 387 388 fh = fh->next; 389 if (mh->next == NULL && fh != NULL) // keine Chance den memleaks 390 mh->next = malloc(sizeof(struct _multi_handler)); 391 mh = mh->next; 392 } 393 394 395 // now, do curl 396 while (handles != 0) 397 curl_multi_perform(mhnd, &handles); 398 399 400 // now clean up 401 mh = mh_tmp; 402 403 while (mh != NULL) 404 { 405 xmlParseChunk(mh->ctxt, "", 0, 1); 406 xmlFreeParserCtxt(mh->ctxt); 407 if (mh->fu->feed_entry_progress != ENTRY_END && mh->fu->feed_entry != 408 NULL) 409 mh->fu->feed_function(mh->fu->feed_entry, mh->fu->userdata); 410 411 free(mh->fu); 412 413 curl_easy_cleanup(mh->hnd); 414 415 mh_tmp = mh; 416 mh = mh->next; 417 free(mh_tmp); 418 } 419 420 curl_multi_cleanup(mhnd); 421 422 } 423 424 static inline void _feed_free_ifyoucan(void *p) 425 { 426 if (p != NULL) 427 free(p); 428 } 429 430 extern void feed_free_entry(struct feed_entry *fe) 431 { 432 //printf("title\n"); 433 _feed_free_ifyoucan(fe->title); 434 //printf("link\n"); 435 _feed_free_ifyoucan(fe->link); 436 //printf("published\n"); 437 _feed_free_ifyoucan(fe->published); 438 //printf("updated\n"); 439 _feed_free_ifyoucan(fe->updated); 440 //printf("id\n"); 441 _feed_free_ifyoucan(fe->id); 442 //printf("author\n"); 443 _feed_free_ifyoucan(fe->author); 444 //printf("author_name\n"); 445 _feed_free_ifyoucan(fe->author_name); 446 //printf("author_email\n"); 447 _feed_free_ifyoucan(fe->author_email); 448 //printf("summary\n"); 449 _feed_free_ifyoucan(fe->summary); 450 451 _feed_free_ifyoucan(fe); 452 }
opml.h:
1 #include <libxml/parser.h> 2 3 struct _opml_userdata 4 { 5 void (*opml_function)(void*, void*); 6 void *userdata; 7 }; 8 9 10 struct opml_handler 11 { 12 xmlParserCtxtPtr ctxt; 13 struct _opml_userdata *ou; 14 }; 15 16 struct opml_outline 17 { 18 char *title; 19 char *text; 20 char *feedurl; 21 char *siteurl; 22 }; 23 24 extern struct opml_handler* opml_create(void *opml_function, void *userdata) 25 ; 26 extern void opml_feed(struct opml_handler *oh, char *txt, int len); 27 extern void opml_destroy(struct opml_handler *oh); 28 extern void opml_outline_destroy(struct opml_outline *ou);
opml.c:
1 #include <stdio.h> 2 #include <string.h> 3 #include <strings.h> 4 #include <libxml/parser.h> 5 #include <libxml/xmlerror.h> 6 #include "opml.h" 7 8 9 static char *__join_together(char *a, char *b, int len_b) 10 { 11 int len = len_b+1; 12 int len_a = 0; 13 int i; 14 char *txt; 15 16 if (a != NULL) 17 len_a = strlen(a); 18 19 len += len_a; 20 21 txt = malloc(sizeof(char)*len); 22 23 for (i = 0; i < len_a; i++) 24 txt[i] = a[i]; 25 26 for (i = 0; i < len_b; i++) 27 txt[i+len_a] = b[i]; 28 29 txt[len-1] = '\0'; 30 31 if (a != NULL) 32 free(a); 33 34 return txt; 35 } 36 37 void _opml_startElementSAX(void *userdata, const xmlChar *characters, 38 const xmlChar * prefix, 39 const xmlChar * URI, 40 int nb_namespaces, 41 const xmlChar ** namespaces, 42 int nb_attributes, 43 int nb_defaulted, 44 const xmlChar ** attributes ) 45 { 46 int i; 47 struct opml_outline *oo = malloc(sizeof(struct opml_outline)); 48 struct _opml_userdata *ou = userdata; 49 memset(oo, 0, sizeof(struct opml_outline)); 50 51 for (i = 0; i < nb_attributes; i++) 52 { 53 if (!strncasecmp((char*)attributes[i*5], "title", 6)) 54 oo->title = __join_together(oo->title, (char*)attributes[(i*5)+3], 55 attributes[(i*5)+4] - attributes[(i*5)+3]); 56 else if (!strncasecmp((char*)attributes[i*5], "text", 5)) 57 oo->text = __join_together(oo->text, (char*)attributes[(i*5)+3], 58 attributes[(i*5)+4] - attributes[(i*5)+3]); 59 else if (!strncasecmp((char*)attributes[i*5], "xmlUrl", 7)) 60 oo->feedurl = __join_together(oo->feedurl, (char*)attributes[(i*5)+ 61 3], attributes[(i*5)+4] - attributes[(i*5)+3]); 62 else if (!strncasecmp((char*)attributes[i*5], "htmlUrl", 7)) 63 oo->siteurl = __join_together(oo->siteurl, (char*)attributes[(i*5)+ 64 3], attributes[(i*5)+4] - attributes[(i*5)+3]); 65 66 } 67 68 ou->opml_function(oo, ou->userdata); 69 70 } 71 72 void _opml_endElementSAX(void *userdata, const xmlChar *characters, 73 const xmlChar * prefix, 74 const xmlChar * URI ) 75 { 76 } 77 78 void _opml_charactersSAX(void *userdata, const xmlChar *characters, int len) 79 { 80 } 81 82 extern void opml_outline_destroy(struct opml_outline *oo) 83 { 84 if (oo == NULL) 85 return; 86 87 if (oo->title != NULL) 88 free(oo->title); 89 if (oo->text != NULL) 90 free(oo->text); 91 if (oo->feedurl != NULL) 92 free(oo->feedurl); 93 if (oo->siteurl != NULL) 94 free(oo->siteurl); 95 96 free(oo); 97 } 98 99 100 extern struct opml_handler* opml_create(void *opml_function, void *userdata) 101 { 102 struct opml_handler *oh = malloc(sizeof(struct opml_handler)); 103 104 xmlSAXHandler xsh; 105 memset(&xsh, 0, sizeof(xmlSAXHandler)); 106 107 struct _opml_userdata *ou = malloc(sizeof(struct _opml_userdata)); 108 ou->opml_function = opml_function; 109 ou->userdata = userdata; 110 111 xsh.initialized = XML_SAX2_MAGIC; 112 xsh.characters = _opml_charactersSAX; 113 xsh.startElementNs = _opml_startElementSAX; 114 xsh.endElementNs = _opml_endElementSAX; 115 116 oh->ou = ou; 117 oh->ctxt = xmlCreatePushParserCtxt(&xsh, ou, NULL, 0, NULL); 118 119 120 return oh; 121 } 122 123 extern void opml_destroy(struct opml_handler *oh) 124 { 125 xmlParseChunk(oh->ctxt, "", 0, 1); 126 xmlFreeParserCtxt(oh->ctxt); 127 free(oh->ou); 128 free(oh); 129 } 130 131 132 extern void opml_feed(struct opml_handler *oh, char *txt, int len) 133 { 134 xmlParseChunk(oh->ctxt, txt, len, 0); 135 }
Und hier ein Beispiel wie ihr die feed-lib benutzt - feedtest.c:
1 #include <stdio.h> 2 #include "feed.h" 3 4 void show_feed1(struct feed_entry *fe, void *userdata) 5 { 6 printf("feed1\n"); 7 printf(">> title: %s\n", fe->title); 8 printf(">> link: %s\n", fe->link); 9 printf(">> published: %s\n", fe->published); 10 printf(">> updated: %s\n", fe->updated); 11 printf(">> author: %s\n", fe->author); 12 printf(">> author_name: %s\n", fe->author_name); 13 printf(">> author_email: %s\n", fe->author_email); 14 printf(">> id: %s\n", fe->id); 15 printf(">> summary: %s\n", fe->summary); 16 printf(">> userdata: %s\n", (char*)userdata); 17 18 printf("\n"); 19 feed_free_entry(fe); 20 } 21 22 void show_feed2(struct feed_entry *fe, void *userdata) 23 { 24 printf("feed2\n"); 25 printf(">> title: %s\n", fe->title); 26 printf(">> link: %s\n", fe->link); 27 printf(">> published: %s\n", fe->published); 28 printf(">> updated: %s\n", fe->updated); 29 printf(">> author: %s\n", fe->author); 30 printf(">> author_name: %s\n", fe->author_name); 31 printf(">> author_email: %s\n", fe->author_email); 32 printf(">> id: %s\n", fe->id); 33 printf(">> summary: %s\n", fe->summary); 34 printf(">> userdata: %s\n", (char*)userdata); 35 36 printf("\n"); 37 feed_free_entry(fe); 38 } 39 40 void show_feed3(struct feed_entry *fe, void *userdata) 41 { 42 printf("feed3\n"); 43 printf(">> title: %s\n", fe->title); 44 printf(">> link: %s\n", fe->link); 45 printf(">> published: %s\n", fe->published); 46 printf(">> updated: %s\n", fe->updated); 47 printf(">> author: %s\n", fe->author); 48 printf(">> author_name: %s\n", fe->author_name); 49 printf(">> author_email: %s\n", fe->author_email); 50 printf(">> id: %s\n", fe->id); 51 printf(">> summary: %s\n", fe->summary); 52 printf(">> userdata: %s\n", (char*)userdata); 53 54 printf("\n"); 55 feed_free_entry(fe); 56 } 57 58 int test_single_parse() 59 { 60 feed_single_parse("http://www.heise.de/newsticker/heise-feed.xml", 61 show_feed1, NULL); 62 printf("------------------\n"); 63 feed_single_parse("http://rss.golem.de/rss.php?feed=ATOM1.0", show_feed2, 64 NULL); 65 printf("------RSS---------\n"); 66 feed_single_parse("http://news.google. 67 de/news?pz=1&cf=all&ned=de&hl=de&topic=h&num=3&output=rs 68 s", show_feed3, NULL); 69 printf("------RSS---------\n"); 70 feed_single_parse("http://rss.golem.de/rss.php?feed=RSS1.0", show_feed1, 71 "userdata"); 72 73 return 0; 74 } 75 76 77 int main() 78 { 79 80 struct feed_handler *fh; 81 fh = feed_add(NULL, "http://rss.golem.de/rss.php?feed=RSS1.0", show_feed1, 82 "userdata"); 83 feed_add(fh, "http://www.heise.de/newsticker/heise-atom.xml", show_feed2, 84 NULL); 85 feed_add(fh, "http://news.google. 86 de/news?pz=1&cf=all&ned=de&hl=de&topic=h&num=3&output=rss", 87 show_feed3, NULL); 88 feed_add(fh, "http://dammit.lt/feed/atom/", show_feed1, NULL); 89 90 feed_multi_parse(fh); 91 92 feed_cleanup(fh); 93 94 95 test_single_parse(); 96 return 0; 97 }
Und hier noch ein Beispiel fuer opml - opmltest.c:
1 #include <stdio.h> 2 #include <string.h> 3 #include "opml.h" 4 #include "feed.h" 5 6 struct oo_list 7 { 8 struct opml_outline *oo; 9 struct oo_list *next; 10 }; 11 12 struct opml_userdata 13 { 14 struct feed_handler *fh; 15 struct oo_list *oo_list; 16 }; 17 18 19 void show_feed(struct feed_entry *fe, void *userdata) 20 { 21 printf("feed1\n"); 22 printf(">> title: %s\n", fe->title); 23 printf(">> link: %s\n", fe->link); 24 printf(">> published: %s\n", fe->published); 25 printf(">> updated: %s\n", fe->updated); 26 printf(">> author: %s\n", fe->author); 27 printf(">> author_name: %s\n", fe->author_name); 28 printf(">> author_email: %s\n", fe->author_email); 29 printf(">> id: %s\n", fe->id); 30 printf(">> summary: %s\n", fe->summary); 31 printf(">> userdata: %s\n", (char*)userdata); 32 33 printf("\n"); 34 feed_free_entry(fe); 35 } 36 37 38 void opml_printout(struct opml_outline *oo, void *userdata) 39 { 40 struct oo_list *oo_list = ((struct opml_userdata*)userdata)->oo_list; 41 struct feed_handler *fh = ((struct opml_userdata*)userdata)->fh; 42 printf("---------------\n"); 43 printf("title: %s\n", oo->title); 44 printf("text: %s\n", oo->text); 45 printf("feedurl: %s\n", oo->feedurl); 46 printf("siteurl: %s\n", oo->siteurl); 47 48 49 while (oo_list->next != NULL) 50 oo_list = oo_list->next; 51 oo_list->next = malloc(sizeof(struct oo_list)); 52 oo_list = oo_list->next; 53 oo_list->next = NULL; 54 oo_list->oo = oo; 55 56 57 feed_add(fh, oo->feedurl, show_feed, NULL); 58 59 } 60 61 int main() 62 { 63 FILE *fp; 64 char buf[64]; 65 struct opml_handler *oh; 66 struct opml_userdata ou; 67 struct oo_list *oo_list = malloc(sizeof(struct oo_list)); 68 struct oo_list *oo_list_tmp; 69 oo_list->next = NULL; 70 oo_list->oo = NULL; 71 72 struct feed_handler *fh; 73 fh = feed_add(NULL, NULL, show_feed, NULL); 74 ou.fh = fh; 75 ou.oo_list = oo_list; 76 oh = opml_create(opml_printout, &ou); 77 78 79 fp = fopen("feeds.opml", "r"); 80 81 while (!feof(fp)) 82 { 83 fgets(buf, 64, fp); 84 opml_feed(oh, buf, strlen(buf)); 85 } 86 87 fclose(fp); 88 89 feed_multi_parse(fh); 90 91 while (oo_list->next != NULL) 92 { 93 oo_list_tmp = oo_list->next; 94 opml_outline_destroy(oo_list->oo); 95 free(oo_list); 96 oo_list = oo_list_tmp; 97 } 98 opml_outline_destroy(oo_list->oo); 99 free(oo_list); 100 101 102 opml_destroy(oh); 103 feed_cleanup(fh); 104 }
Und hier noch das Makefile:
CC=/usr/bin/gcc
CFLAGS=-O2 -g -Wall
all: feedtest opmltest
feed.o: feed.c
$(CC) $(CFLAGS) -o feed.o -Wall -std=c99 -fPIC feed.c -I /usr/include/libxml2/ -c
opml.o: opml.c
$(CC) $(CFLAGS) -o opml.o -Wall -std=c99 -fPIC opml.c -I /usr/include/libxml2/ -c
feedtest: feed.o feedtest.c
$(CC) $(CFLAGS) -std=c99 -lxml2 -lcurl -o feedtest feedtest.c feed.o
opmltest: opml.o feed.o opmltest.c
$(CC) $(CFLAGS) -std=c99 -lxml2 -lcurl -o opmltest opmltest.c opml.o feed.o -I /usr/include/libxml2/
clean:
rm -f feedtest feed.o opmltest opml.o
