00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifdef HAVE_CONFIG_H
00020 #include <config.h>
00021 #else
00022 # error Use configure; make; make install
00023 #endif
00024
00025 #include "mrss.h"
00026 #include "mrss_internal.h"
00027
00028 static void
00029 __mrss_parser_rss_image (xmlDocPtr doc, xmlNodePtr cur, mrss_t * data)
00030 {
00031 char *c;
00032
00033 for (cur = cur->children; cur; cur = cur->next)
00034 {
00035 if (cur->type == XML_ELEMENT_NODE)
00036 {
00037
00038 if (!xmlStrcmp (cur->name, (xmlChar *) "title")
00039 && !data->image_title
00040 && (c =
00041 (char *) xmlNodeListGetString (doc, cur->xmlChildrenNode,
00042 1)))
00043 data->image_title = c;
00044
00045
00046 else if (!xmlStrcmp (cur->name, (xmlChar *) "url")
00047 && !data->image_url
00048 && (c =
00049 (char *) xmlNodeListGetString (doc,
00050 cur->xmlChildrenNode,
00051 1)))
00052 data->image_url = c;
00053
00054
00055 else if (!xmlStrcmp (cur->name, (xmlChar *) "link")
00056 && !data->image_link
00057 && (c =
00058 (char *) xmlNodeListGetString (doc,
00059 cur->xmlChildrenNode,
00060 1)))
00061 data->image_link = c;
00062
00063
00064 else if (!xmlStrcmp (cur->name, (xmlChar *) "width")
00065 && !data->image_width
00066 && (c =
00067 (char *) xmlNodeListGetString (doc,
00068 cur->xmlChildrenNode,
00069 1)))
00070 data->image_width = atoi (c);
00071
00072
00073 else if (!xmlStrcmp (cur->name, (xmlChar *) "height")
00074 && !data->image_height
00075 && (c =
00076 (char *) xmlNodeListGetString (doc,
00077 cur->xmlChildrenNode,
00078 1)))
00079 data->image_height = atoi (c);
00080
00081
00082 else if (!xmlStrcmp (cur->name, (xmlChar *) "description")
00083 && !data->image_description
00084 && (c =
00085 (char *) xmlNodeListGetString (doc,
00086 cur->xmlChildrenNode,
00087 1)))
00088 data->image_description = c;
00089 }
00090 }
00091 }
00092
00093 static void
00094 __mrss_parser_rss_textinput (xmlDocPtr doc, xmlNodePtr cur, mrss_t * data)
00095 {
00096 char *c;
00097
00098 for (cur = cur->children; cur; cur = cur->next)
00099 {
00100 if (cur->type == XML_ELEMENT_NODE)
00101 {
00102
00103 if (!xmlStrcmp (cur->name, (xmlChar *) "title")
00104 && !data->textinput_title
00105 && (c =
00106 (char *) xmlNodeListGetString (doc, cur->xmlChildrenNode,
00107 1)))
00108 data->textinput_title = c;
00109
00110
00111 else if (!xmlStrcmp (cur->name, (xmlChar *) "description")
00112 && !data->textinput_description
00113 && (c =
00114 (char *) xmlNodeListGetString (doc,
00115 cur->xmlChildrenNode,
00116 1)))
00117 data->textinput_description = c;
00118
00119
00120 else if (!xmlStrcmp (cur->name, (xmlChar *) "name")
00121 && !data->textinput_name
00122 && (c =
00123 (char *) xmlNodeListGetString (doc,
00124 cur->xmlChildrenNode,
00125 1)))
00126 data->textinput_name = c;
00127
00128
00129 else if (!xmlStrcmp (cur->name, (xmlChar *) "link")
00130 && !data->textinput_link
00131 && (c =
00132 (char *) xmlNodeListGetString (doc,
00133 cur->xmlChildrenNode,
00134 1)))
00135 data->textinput_link = c;
00136 }
00137 }
00138 }
00139
00140 static void
00141 __mrss_parser_rss_skipHours (xmlDocPtr doc, xmlNodePtr cur, mrss_t * data)
00142 {
00143 char *c;
00144
00145 for (cur = cur->children; cur; cur = cur->next)
00146 {
00147 if (cur->type == XML_ELEMENT_NODE)
00148 {
00149 if (!xmlStrcmp (cur->name, (xmlChar *) "hour")
00150 && (c =
00151 (char *) xmlNodeListGetString (doc, cur->xmlChildrenNode,
00152 1)))
00153 {
00154 mrss_hour_t *hour;
00155
00156 if (!(hour = (mrss_hour_t *) malloc (sizeof (mrss_hour_t))))
00157 {
00158 free (c);
00159 return;
00160 }
00161
00162 memset (hour, 0, sizeof (mrss_hour_t));
00163 hour->element = MRSS_ELEMENT_SKIPHOURS;
00164 hour->hour = c;
00165
00166 if (!data->skipHours)
00167 data->skipHours = hour;
00168 else
00169 {
00170 mrss_hour_t *tmp;
00171
00172 tmp = data->skipHours;
00173
00174 while (tmp->next)
00175 tmp = tmp->next;
00176 tmp->next = hour;
00177 }
00178 }
00179 }
00180 }
00181 }
00182
00183 static void
00184 __mrss_parser_rss_skipDays (xmlDocPtr doc, xmlNodePtr cur, mrss_t * data)
00185 {
00186 char *c;
00187
00188 for (cur = cur->children; cur; cur = cur->next)
00189 {
00190 if (cur->type == XML_ELEMENT_NODE)
00191 {
00192 if (!xmlStrcmp (cur->name, (xmlChar *) "day")
00193 && (c =
00194 (char *) xmlNodeListGetString (doc, cur->xmlChildrenNode,
00195 1)))
00196 {
00197 mrss_day_t *day;
00198
00199 if (!(day = (mrss_day_t *) malloc (sizeof (mrss_day_t))))
00200 {
00201 free (c);
00202 return;
00203 }
00204
00205 memset (day, 0, sizeof (mrss_day_t));
00206 day->element = MRSS_ELEMENT_SKIPDAYS;
00207 day->day = c;
00208
00209 if (!data->skipDays)
00210 data->skipDays = day;
00211 else
00212 {
00213 mrss_day_t *tmp;
00214
00215 tmp = data->skipDays;
00216
00217 while (tmp->next)
00218 tmp = tmp->next;
00219 tmp->next = day;
00220 }
00221 }
00222 }
00223 }
00224 }
00225
00226 static void
00227 __mrss_parser_rss_item (xmlDocPtr doc, xmlNodePtr cur, mrss_t * data)
00228 {
00229 char *c;
00230 char *attr;
00231 mrss_item_t *item;
00232
00233 if (!(item = (mrss_item_t *) malloc (sizeof (mrss_item_t))))
00234 return;
00235
00236 memset (item, 0, sizeof (mrss_item_t));
00237 item->element = MRSS_ELEMENT_ITEM;
00238
00239 for (cur = cur->children; cur; cur = cur->next)
00240 {
00241 if (cur->type == XML_ELEMENT_NODE)
00242 {
00243
00244 if (!xmlStrcmp (cur->name, (xmlChar *) "title")
00245 && !item->title
00246 && (c =
00247 (char *) xmlNodeListGetString (doc, cur->xmlChildrenNode,
00248 1)))
00249 item->title = c;
00250
00251
00252 else if (!xmlStrcmp (cur->name, (xmlChar *) "link")
00253 && !item->link
00254 && (c =
00255 (char *) xmlNodeListGetString (doc,
00256 cur->xmlChildrenNode,
00257 1)))
00258 item->link = c;
00259
00260
00261 else if (!xmlStrcmp (cur->name, (xmlChar *) "description")
00262 && !item->description
00263 && (c =
00264 (char *) xmlNodeListGetString (doc,
00265 cur->xmlChildrenNode,
00266 1)))
00267 item->description = c;
00268
00269
00270 else if (!xmlStrcmp (cur->name, (xmlChar *) "source")
00271 && !item->source
00272 && (c =
00273 (char *) xmlNodeListGetString (doc,
00274 cur->xmlChildrenNode,
00275 1)))
00276 {
00277 item->source = c;
00278
00279 if ((attr = (char *) xmlGetProp (cur, (xmlChar *) "url")))
00280 item->source_url = attr;
00281 }
00282
00283
00284 else if (!xmlStrcmp (cur->name, (xmlChar *) "enclosure")
00285 && !item->enclosure
00286 && (c =
00287 (char *) xmlNodeListGetString (doc,
00288 cur->xmlChildrenNode,
00289 1)))
00290 {
00291 item->enclosure = c;
00292
00293 if ((attr = (char *) xmlGetProp (cur, (xmlChar *) "url")))
00294 item->enclosure_url = attr;
00295
00296 if ((attr = (char *) xmlGetProp (cur, (xmlChar *) "length")))
00297 item->enclosure_length = atoi (attr);
00298
00299 if ((attr = (char *) xmlGetProp (cur, (xmlChar *) "type")))
00300 item->enclosure_type = attr;
00301 }
00302
00303
00304 else if (!xmlStrcmp (cur->name, (xmlChar *) "category")
00305 && (c =
00306 (char *) xmlNodeListGetString (doc,
00307 cur->xmlChildrenNode,
00308 1)))
00309 {
00310 mrss_category_t *category;
00311
00312 if (!
00313 (category =
00314 (mrss_category_t *) malloc (sizeof (mrss_category_t))))
00315 return;
00316
00317 memset (category, 0, sizeof (mrss_category_t));
00318
00319 category->element = MRSS_ELEMENT_CATEGORY;
00320 category->category = c;
00321
00322 if ((attr = (char *) xmlGetProp (cur, (xmlChar *) "domain")))
00323 category->domain = attr;
00324
00325 if (!item->category)
00326 item->category = category;
00327 else
00328 {
00329 mrss_category_t *tmp;
00330
00331 tmp = item->category;
00332 while (tmp->next)
00333 tmp = tmp->next;
00334 tmp->next = category;
00335 }
00336 }
00337
00338
00339 else if (!xmlStrcmp (cur->name, (xmlChar *) "author")
00340 && !item->author
00341 && (c =
00342 (char *) xmlNodeListGetString (doc,
00343 cur->xmlChildrenNode,
00344 1)))
00345 item->author = c;
00346
00347
00348 else if (!xmlStrcmp (cur->name, (xmlChar *) "comments")
00349 && !item->comments
00350 && (c =
00351 (char *) xmlNodeListGetString (doc,
00352 cur->xmlChildrenNode,
00353 1)))
00354 item->comments = c;
00355
00356
00357 else if (!xmlStrcmp (cur->name, (xmlChar *) "guid")
00358 && !item->guid
00359 && (c =
00360 (char *) xmlNodeListGetString (doc,
00361 cur->xmlChildrenNode,
00362 1)))
00363 {
00364 item->guid = c;
00365
00366 if ((attr =
00367 (char *) xmlGetProp (cur, (xmlChar *) "isPermaLink"))
00368 && !strcmp (attr, "false"))
00369 item->guid_isPermaLink = 0;
00370 else
00371 item->guid_isPermaLink = 1;
00372
00373 }
00374
00375
00376 else if (!xmlStrcmp (cur->name, (xmlChar *) "pubDate")
00377 && !item->pubDate
00378 && (c =
00379 (char *) xmlNodeListGetString (doc,
00380 cur->xmlChildrenNode,
00381 1)))
00382 item->pubDate = c;
00383
00384 }
00385 }
00386
00387
00388 if (!data->item)
00389 data->item = item;
00390 else
00391 {
00392 mrss_item_t *tmp;
00393
00394 tmp = data->item;
00395
00396 while (tmp->next)
00397 tmp = tmp->next;
00398 tmp->next = item;
00399 }
00400 }
00401
00402 static mrss_error_t
00403 __mrss_parser_rss (mrss_version_t v, xmlDocPtr doc, xmlNodePtr cur,
00404 mrss_t ** ret)
00405 {
00406 mrss_t *data;
00407 char *c, *attr;
00408
00409 if (!(data = (mrss_t *) malloc (sizeof (mrss_t))))
00410 return MRSS_ERR_POSIX;
00411
00412 memset (data, 0, sizeof (mrss_t));
00413 data->element = MRSS_ELEMENT_CHANNEL;
00414 data->version = v;
00415
00416 while (cur && xmlStrcmp (cur->name, (xmlChar *) "channel"))
00417 cur = cur->next;
00418
00419 if (!cur)
00420 {
00421 free (data);
00422 return MRSS_ERR_PARSER;
00423 }
00424
00425 for (cur = cur->children; cur; cur = cur->next)
00426 {
00427 if (cur->type == XML_ELEMENT_NODE)
00428 {
00429
00430 if (!xmlStrcmp (cur->name, (xmlChar *) "title") && !data->title &&
00431 (c =
00432 (char *) xmlNodeListGetString (doc, cur->xmlChildrenNode, 1)))
00433 data->title = c;
00434
00435
00436 else if (!xmlStrcmp (cur->name, (xmlChar *) "description")
00437 && !data->description
00438 && (c =
00439 (char *) xmlNodeListGetString (doc,
00440 cur->xmlChildrenNode,
00441 1)))
00442 data->description = c;
00443
00444
00445 else if (!xmlStrcmp (cur->name, (xmlChar *) "link") && !data->link
00446 && (c =
00447 (char *) xmlNodeListGetString (doc,
00448 cur->xmlChildrenNode,
00449 1)))
00450 data->link = c;
00451
00452
00453 else if (!xmlStrcmp (cur->name, (xmlChar *) "language")
00454 && !data->language
00455 && (c =
00456 (char *) xmlNodeListGetString (doc,
00457 cur->xmlChildrenNode,
00458 1)))
00459 data->language = c;
00460
00461
00462 else if (!xmlStrcmp (cur->name, (xmlChar *) "rating")
00463 && !data->rating
00464 && (c =
00465 (char *) xmlNodeListGetString (doc,
00466 cur->xmlChildrenNode,
00467 1)))
00468 data->rating = c;
00469
00470
00471 else if (!xmlStrcmp (cur->name, (xmlChar *) "copyright")
00472 && !data->copyright
00473 && (c =
00474 (char *) xmlNodeListGetString (doc,
00475 cur->xmlChildrenNode,
00476 1)))
00477 data->copyright = c;
00478
00479
00480 else if (!xmlStrcmp (cur->name, (xmlChar *) "pubDate")
00481 && !data->pubDate
00482 && (c =
00483 (char *) xmlNodeListGetString (doc,
00484 cur->xmlChildrenNode,
00485 1)))
00486 data->pubDate = c;
00487
00488
00489 else if (!xmlStrcmp (cur->name, (xmlChar *) "lastBuildDate")
00490 && !data->lastBuildDate
00491 && (c =
00492 (char *) xmlNodeListGetString (doc,
00493 cur->xmlChildrenNode,
00494 1)))
00495 data->lastBuildDate = c;
00496
00497
00498 else if (!xmlStrcmp (cur->name, (xmlChar *) "docs") && !data->docs
00499 && (c =
00500 (char *) xmlNodeListGetString (doc,
00501 cur->xmlChildrenNode,
00502 1)))
00503 data->docs = c;
00504
00505
00506 else if (!xmlStrcmp (cur->name, (xmlChar *) "managingeditor")
00507 && !data->managingeditor
00508 && (c =
00509 (char *) xmlNodeListGetString (doc,
00510 cur->xmlChildrenNode,
00511 1)))
00512 data->managingeditor = c;
00513
00514
00515 else if (!xmlStrcmp (cur->name, (xmlChar *) "webMaster")
00516 && !data->webMaster
00517 && (c =
00518 (char *) xmlNodeListGetString (doc,
00519 cur->xmlChildrenNode,
00520 1)))
00521 data->webMaster = c;
00522
00523
00524 else if (!xmlStrcmp (cur->name, (xmlChar *) "image"))
00525 __mrss_parser_rss_image (doc, cur, data);
00526
00527
00528 else if (!xmlStrcmp (cur->name, (xmlChar *) "textinput"))
00529 __mrss_parser_rss_textinput (doc, cur, data);
00530
00531
00532 else if (!xmlStrcmp (cur->name, (xmlChar *) "skipHours"))
00533 __mrss_parser_rss_skipHours (doc, cur, data);
00534
00535
00536 else if (!xmlStrcmp (cur->name, (xmlChar *) "skipDays"))
00537 __mrss_parser_rss_skipDays (doc, cur, data);
00538
00539
00540 else if (!xmlStrcmp (cur->name, (xmlChar *) "item"))
00541 __mrss_parser_rss_item (doc, cur, data);
00542
00543
00544 else if (!xmlStrcmp (cur->name, (xmlChar *) "category")
00545 && (c =
00546 (char *) xmlNodeListGetString (doc,
00547 cur->xmlChildrenNode,
00548 1)))
00549 {
00550 mrss_category_t *category;
00551
00552 if (!
00553 (category =
00554 (mrss_category_t *) malloc (sizeof (mrss_category_t))))
00555 {
00556 mrss_free ((mrss_generic_t *) data);
00557 return MRSS_ERR_POSIX;
00558 }
00559
00560 memset (category, 0, sizeof (mrss_category_t));
00561
00562 category->element = MRSS_ELEMENT_CATEGORY;
00563 category->category = c;
00564
00565 if ((attr = (char *) xmlGetProp (cur, (xmlChar *) "domain")))
00566 category->domain = attr;
00567
00568 if (!data->category)
00569 data->category = category;
00570 else
00571 {
00572 mrss_category_t *tmp;
00573
00574 tmp = data->category;
00575 while (tmp->next)
00576 tmp = tmp->next;
00577 tmp->next = category;
00578 }
00579 }
00580
00581
00582 else if (!xmlStrcmp (cur->name, (xmlChar *) "cloud")
00583 && !data->cloud
00584 && (c =
00585 (char *) xmlNodeListGetString (doc,
00586 cur->xmlChildrenNode,
00587 1)))
00588 {
00589 data->cloud = c;
00590
00591 if ((attr = (char *) xmlGetProp (cur, (xmlChar *) "domain"))
00592 && !data->cloud_domain)
00593 data->cloud_domain = attr;
00594
00595 if ((attr = (char *) xmlGetProp (cur, (xmlChar *) "port"))
00596 && !data->cloud_port)
00597 data->cloud_port = atoi (attr);
00598
00599 if ((attr =
00600 (char *) xmlGetProp (cur, (xmlChar *) "registerProcedure"))
00601 && !data->cloud_registerProcedure)
00602 data->cloud_registerProcedure = attr;
00603
00604 if ((attr = (char *) xmlGetProp (cur, (xmlChar *) "protocol"))
00605 && !data->cloud_protocol)
00606 data->cloud_protocol = attr;
00607 }
00608
00609
00610 else if (!xmlStrcmp (cur->name, (xmlChar *) "generator")
00611 && !data->generator
00612 && (c =
00613 (char *) xmlNodeListGetString (doc,
00614 cur->xmlChildrenNode,
00615 1)))
00616 data->generator = c;
00617
00618
00619 else if (!xmlStrcmp (cur->name, (xmlChar *) "ttl")
00620 && !data->ttl
00621 && (c =
00622 (char *) xmlNodeListGetString (doc,
00623 cur->xmlChildrenNode,
00624 1)))
00625 data->ttl = atoi (c);
00626
00627 }
00628 }
00629
00630 *ret = data;
00631
00632 return MRSS_OK;
00633 }
00634
00635 static mrss_error_t
00636 __mrss_parser (xmlDocPtr doc, mrss_t ** ret)
00637 {
00638 mrss_error_t r = MRSS_ERR_VERSION;
00639 xmlNodePtr cur;
00640 char *c;
00641
00642 if (!(cur = xmlDocGetRootElement (doc)))
00643 {
00644 xmlFreeDoc (doc);
00645 return MRSS_ERR_PARSER;
00646 }
00647
00648 if (!xmlStrcmp (cur->name, (xmlChar *) "rss"))
00649 {
00650 if ((c = (char *) xmlGetProp (cur, (xmlChar *) "version")))
00651 {
00652
00653 if (!strcmp (c, "0.91"))
00654 r =
00655 __mrss_parser_rss (MRSS_VERSION_0_91, doc, cur->children, ret);
00656
00657
00658 else if (!strcmp (c, "0.92"))
00659 r =
00660 __mrss_parser_rss (MRSS_VERSION_0_92, doc, cur->children, ret);
00661
00662
00663 else if (!strcmp (c, "2.0"))
00664 r = __mrss_parser_rss (MRSS_VERSION_2_0, doc, cur->children, ret);
00665
00666 else
00667 r = MRSS_ERR_VERSION;
00668 }
00669
00670 else
00671 r = MRSS_ERR_VERSION;
00672 }
00673
00674 else
00675 r = MRSS_ERR_PARSER;
00676
00677 xmlFreeDoc (doc);
00678 return r;
00679 }
00680
00681
00682
00683 mrss_error_t
00684 mrss_parse_url (char *url, mrss_t ** ret)
00685 {
00686 __mrss_download_t *download;
00687 xmlDocPtr doc;
00688 mrss_error_t err;
00689
00690 if (!url || !ret)
00691 return MRSS_ERR_DATA;
00692
00693 if (!(download = __mrss_download_file (url)))
00694 return MRSS_ERR_POSIX;
00695
00696 if (!(doc = xmlParseMemory (download->mm, download->size)))
00697 {
00698 free (download->mm);
00699 free (download);
00700 return MRSS_ERR_PARSER;
00701 }
00702
00703 if (!(err = __mrss_parser (doc, ret)))
00704 {
00705 if (!((*ret)->file = strdup (url)))
00706 {
00707 *ret = NULL;
00708 return MRSS_ERR_POSIX;
00709 }
00710
00711 (*ret)->size = download->size;
00712 }
00713
00714 free (download->mm);
00715 free (download);
00716
00717 return err;
00718 }
00719
00720 mrss_error_t
00721 mrss_parse_file (char *file, mrss_t ** ret)
00722 {
00723 xmlDocPtr doc;
00724 mrss_error_t err;
00725 struct stat st;
00726
00727 if (!file || !ret)
00728 return MRSS_ERR_DATA;
00729
00730 if (lstat (file, &st))
00731 return MRSS_ERR_POSIX;
00732
00733 if (!(doc = xmlParseFile (file)))
00734 return MRSS_ERR_PARSER;
00735
00736 if (!(err = __mrss_parser (doc, ret)))
00737 {
00738 if (!((*ret)->file = strdup (file)))
00739 {
00740 *ret = NULL;
00741 return MRSS_ERR_POSIX;
00742 }
00743
00744 (*ret)->size = st.st_size;
00745 }
00746
00747 return err;
00748 }
00749
00750 mrss_error_t
00751 mrss_parse_buffer (char *buffer, size_t size, mrss_t ** ret)
00752 {
00753 xmlDocPtr doc;
00754 mrss_error_t err;
00755
00756 if (!buffer || !size || !ret)
00757 return MRSS_ERR_DATA;
00758
00759 if (!(doc = xmlParseMemory (buffer, size)))
00760 return MRSS_ERR_PARSER;
00761
00762 if (!(err = __mrss_parser (doc, ret)))
00763 (*ret)->size = size;
00764
00765 return err;
00766 }
00767
00768