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 __mrss_write_string(void (*func)(void *, char *,...), void *obj, char *str) {
00029 int i;
00030 int len;
00031 char buf[1024];
00032 int j;
00033
00034 #define __NXML_CHECK_BUF \
00035 if(j==sizeof(buf)-1) { buf[j]=0; func(obj, "%s",buf); j=0; }
00036
00037 if (!str)
00038 return;
00039
00040 len = strlen (str);
00041
00042 for (j = i = 0; i < len; i++)
00043 {
00044 if (str[i] == '\r')
00045 continue;
00046
00047 else if (str[i] == '<')
00048 {
00049 buf[j++] = '&';
00050 __NXML_CHECK_BUF;
00051 buf[j++] = 'l';
00052 __NXML_CHECK_BUF;
00053 buf[j++] = 't';
00054 __NXML_CHECK_BUF;
00055 buf[j++] = ';';
00056 __NXML_CHECK_BUF;
00057 }
00058
00059 else if (str[i] == '>')
00060 {
00061 buf[j++] = '&';
00062 __NXML_CHECK_BUF;
00063 buf[j++] = 'g';
00064 __NXML_CHECK_BUF;
00065 buf[j++] = 't';
00066 __NXML_CHECK_BUF;
00067 buf[j++] = ';';
00068 __NXML_CHECK_BUF;
00069 }
00070
00071 else if (str[i] == '&')
00072 {
00073 buf[j++] = '&';
00074 __NXML_CHECK_BUF;
00075 buf[j++] = 'a';
00076 __NXML_CHECK_BUF;
00077 buf[j++] = 'm';
00078 __NXML_CHECK_BUF;
00079 buf[j++] = 'p';
00080 __NXML_CHECK_BUF;
00081 buf[j++] = ';';
00082 __NXML_CHECK_BUF;
00083 }
00084
00085 else if (str[i] == '\'')
00086 {
00087 buf[j++] = '&';
00088 __NXML_CHECK_BUF;
00089 buf[j++] = 'a';
00090 __NXML_CHECK_BUF;
00091 buf[j++] = 'p';
00092 __NXML_CHECK_BUF;
00093 buf[j++] = 'o';
00094 __NXML_CHECK_BUF;
00095 buf[j++] = 's';
00096 __NXML_CHECK_BUF;
00097 buf[j++] = ';';
00098 __NXML_CHECK_BUF;
00099 }
00100
00101 else if (str[i] == '\'')
00102 {
00103 buf[j++] = '&';
00104 __NXML_CHECK_BUF;
00105 buf[j++] = 'q';
00106 __NXML_CHECK_BUF;
00107 buf[j++] = 'u';
00108 __NXML_CHECK_BUF;
00109 buf[j++] = 'o';
00110 __NXML_CHECK_BUF;
00111 buf[j++] = 't';
00112 __NXML_CHECK_BUF;
00113 buf[j++] = ';';
00114 __NXML_CHECK_BUF;
00115 }
00116
00117 else
00118 {
00119 buf[j++] = str[i];
00120 __NXML_CHECK_BUF;
00121 }
00122 }
00123
00124 if (j)
00125 {
00126 buf[j] = 0;
00127 func (obj, "%s", buf);
00128 j = 0;
00129 }
00130 }
00131
00132 static mrss_error_t
00133 __mrss_write_real (mrss_t * mrss, void (*func) (void *, char *, ...),
00134 void *obj)
00135 {
00136 mrss_item_t *item;
00137 mrss_category_t *category;
00138
00139 func (obj, "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>\n"
00140 "<rss version=\"");
00141
00142 switch (mrss->version)
00143 {
00144 case MRSS_VERSION_0_91:
00145 func (obj, "0.91");
00146 break;
00147
00148 case MRSS_VERSION_0_92:
00149 func (obj, "0.92");
00150 break;
00151
00152 case MRSS_VERSION_2_0:
00153 func (obj, "2.0");
00154 break;
00155 }
00156
00157 func (obj, "\">\n");
00158
00159 func (obj, " <channel>\n");
00160
00161 if (mrss->title)
00162 {
00163 func (obj, " <title>");
00164 __mrss_write_string (func, obj, mrss->title);
00165 func (obj, "</title>\n");
00166 }
00167
00168 if (mrss->description)
00169 {
00170 func (obj, " <description>");
00171 __mrss_write_string (func, obj, mrss->description);
00172 func (obj, "</description>\n");
00173 }
00174
00175 if (mrss->link)
00176 {
00177 func (obj, " <link>");
00178 __mrss_write_string (func, obj, mrss->link);
00179 func (obj, "</link>\n");
00180 }
00181
00182 if (mrss->language)
00183 {
00184 func (obj, " <language>");
00185 __mrss_write_string (func, obj, mrss->language);
00186 func (obj, "</language>\n");
00187 }
00188
00189 if (mrss->rating)
00190 {
00191 func (obj, " <rating>");
00192 __mrss_write_string (func, obj, mrss->rating);
00193 func (obj, "</rating>\n");
00194 }
00195
00196 if (mrss->copyright)
00197 {
00198 func (obj, " <copyright>");
00199 __mrss_write_string (func, obj, mrss->copyright);
00200 func (obj, "</copyright>\n");
00201 }
00202
00203 if (mrss->pubDate)
00204 {
00205 func (obj, " <pubDate>");
00206 __mrss_write_string (func, obj, mrss->pubDate);
00207 func (obj, "</pubDate>\n");
00208 }
00209
00210 if (mrss->lastBuildDate)
00211 {
00212 func (obj, " <lastBuildDate>");
00213 __mrss_write_string (func, obj, mrss->lastBuildDate);
00214 func (obj, "</lastBuildDate>\n");
00215 }
00216
00217 if (mrss->docs)
00218 {
00219 func (obj, " <docs>");
00220 __mrss_write_string (func, obj, mrss->docs);
00221 func (obj, "</docs>\n");
00222 }
00223
00224 if (mrss->managingeditor)
00225 {
00226 func (obj, " <managingeditor>");
00227 __mrss_write_string (func, obj, mrss->managingeditor);
00228 func (obj, "</managingeditor>\n");
00229 }
00230
00231 if (mrss->webMaster)
00232 {
00233 func (obj, " <webMaster>");
00234 __mrss_write_string (func, obj, mrss->webMaster);
00235 func (obj, "</webMaster>\n");
00236 }
00237
00238 if (mrss->version == MRSS_VERSION_2_0)
00239 {
00240 if (mrss->generator)
00241 {
00242 func (obj, " <generator>");
00243 __mrss_write_string (func, obj, mrss->generator);
00244 func (obj, "</generator>\n");
00245 }
00246
00247 if (mrss->ttl)
00248 func (obj, " <ttl>%d</ttl>\n", mrss->ttl);
00249 }
00250
00251 if (mrss->image_title || mrss->image_url || mrss->image_link
00252 || mrss->image_width || mrss->image_height || mrss->description)
00253 {
00254
00255 func (obj, " <image>\n");
00256
00257 if (mrss->image_title)
00258 {
00259 func (obj, " <title>");
00260 __mrss_write_string (func, obj, mrss->image_title);
00261 func (obj, "</title>\n");
00262 }
00263
00264 if (mrss->image_url)
00265 {
00266 func (obj, " <url>");
00267 __mrss_write_string (func, obj, mrss->image_url);
00268 func (obj, "</url>\n");
00269 }
00270
00271 if (mrss->image_link)
00272 {
00273 func (obj, " <link>");
00274 __mrss_write_string (func, obj, mrss->image_link);
00275 func (obj, "</link>\n");
00276 }
00277
00278 if (mrss->image_width)
00279 func (obj, " <width>%d</width>\n", mrss->image_width);
00280
00281 if (mrss->image_height)
00282 func (obj, " <height>%d</height>\n", mrss->image_height);
00283
00284 if (mrss->image_description)
00285 {
00286 func (obj, " <description>");
00287 __mrss_write_string (func, obj, mrss->image_description);
00288 func (obj, "</description>\n");
00289 }
00290
00291 func (obj, " </image>\n");
00292 }
00293
00294 if (mrss->textinput_title || mrss->textinput_description
00295 || mrss->textinput_name || mrss->textinput_link)
00296 {
00297
00298 func (obj, " <textinput>\n");
00299
00300 if (mrss->textinput_title)
00301 {
00302 func (obj, " <title>");
00303 __mrss_write_string (func, obj, mrss->textinput_title);
00304 func (obj, "</title>\n");
00305 }
00306
00307 if (mrss->textinput_description)
00308 {
00309 func (obj, " <description>");
00310 __mrss_write_string (func, obj, mrss->textinput_description);
00311 func (obj, "</description>\n");
00312 }
00313
00314 if (mrss->textinput_name)
00315 {
00316 func (obj, " <name>");
00317 __mrss_write_string (func, obj, mrss->textinput_name);
00318 func (obj, "</name>\n");
00319 }
00320
00321 if (mrss->textinput_link)
00322 {
00323 func (obj, " <link>");
00324 __mrss_write_string (func, obj, mrss->textinput_link);
00325 func (obj, "</link>\n");
00326 }
00327
00328 func (obj, " </textinput>\n");
00329 }
00330
00331 if ((mrss->version == MRSS_VERSION_0_92
00332 || mrss->version == MRSS_VERSION_2_0) && mrss->cloud)
00333 {
00334 func (obj, " <cloud");
00335
00336 if (mrss->cloud_domain)
00337 {
00338 func (obj, " domain=\"");
00339 __mrss_write_string (func, obj, mrss->cloud_domain);
00340 func (obj, "\"");
00341 }
00342
00343 if (mrss->cloud_port)
00344 func (obj, " port=\"%d\"", mrss->cloud_port);
00345
00346 if (mrss->cloud_path)
00347 {
00348 func (obj, " path=\"");
00349 __mrss_write_string (func, obj, mrss->cloud_path);
00350 func (obj, "\"");
00351 }
00352
00353 if (mrss->cloud_registerProcedure)
00354 {
00355 func (obj, " registerProcedure=\"");
00356 __mrss_write_string (func, obj, mrss->cloud_registerProcedure);
00357 func (obj, "\"");
00358 }
00359
00360 if (mrss->cloud_protocol)
00361 {
00362 func (obj, " protocol=\"");
00363 __mrss_write_string (func, obj, mrss->cloud_protocol);
00364 func (obj, "\"");
00365 }
00366
00367 func (obj, ">%s</cloud>\n", mrss->cloud);
00368 }
00369
00370 if (mrss->skipHours)
00371 {
00372 mrss_hour_t *hour;
00373
00374 func (obj, " <skipHours>\n");
00375
00376 hour = mrss->skipHours;
00377 while (hour)
00378 {
00379 func (obj, " <hour>");
00380 __mrss_write_string (func, obj, hour->hour);
00381 func (obj, "</hour>\n");
00382
00383 hour = hour->next;
00384 }
00385
00386 func (obj, " </skipHours>\n");
00387 }
00388
00389 if (mrss->skipDays)
00390 {
00391 mrss_day_t *day;
00392
00393 func (obj, " <skipDays>\n");
00394
00395 day = mrss->skipDays;
00396 while (day)
00397 {
00398 func (obj, " <day>");
00399 __mrss_write_string (func, obj, day->day);
00400 func (obj, "</day>\n");
00401 day = day->next;
00402 }
00403
00404 func (obj, " </skipDays>\n");
00405 }
00406
00407 if ((mrss->version == MRSS_VERSION_0_92
00408 || mrss->version == MRSS_VERSION_2_0) && mrss->category)
00409 {
00410 category = mrss->category;
00411 while (category)
00412 {
00413 func (obj, " <category");
00414
00415 if (category->domain)
00416 {
00417 func (obj, " domain=\"");
00418 __mrss_write_string (func, obj, category->domain);
00419 func (obj, "\"");
00420 }
00421
00422 func (obj, ">");
00423 __mrss_write_string (func, obj, category->category);
00424 func (obj, "</category>\n");
00425
00426 category = category->next;
00427 }
00428 }
00429
00430 item = mrss->item;
00431 while (item)
00432 {
00433 func (obj, " <item>\n");
00434
00435 if (item->title)
00436 {
00437 func (obj, " <title>");
00438 __mrss_write_string (func, obj, item->title);
00439 func (obj, "</title>\n");
00440 }
00441
00442 if (item->link)
00443 {
00444 func (obj, " <link>");
00445 __mrss_write_string (func, obj, item->link);
00446 func (obj, "</link>\n");
00447 }
00448
00449 if (item->description)
00450 {
00451 func (obj, " <description>");
00452 __mrss_write_string (func, obj, item->description);
00453 func (obj, "</description>\n");
00454 }
00455
00456 if (mrss->version == MRSS_VERSION_2_0)
00457 {
00458 if (item->author)
00459 {
00460 func (obj, " <author>");
00461 __mrss_write_string (func, obj, item->author);
00462 func (obj, "</author>\n");
00463 }
00464
00465 if (item->comments)
00466 {
00467 func (obj, " <comments>");
00468 __mrss_write_string (func, obj, item->comments);
00469 func (obj, "</comments>\n");
00470 }
00471
00472 if (item->pubDate)
00473 {
00474 func (obj, " <pubDate>");
00475 __mrss_write_string (func, obj, item->pubDate);
00476 func (obj, "</pubDate>\n");
00477 }
00478
00479 if (item->guid)
00480 {
00481 func (obj, " <guid isPermaLink=\"%s\">");
00482 __mrss_write_string (func, obj, item->guid);
00483 func (obj, "</guid>\n");
00484 }
00485
00486 }
00487
00488 if (mrss->version == MRSS_VERSION_2_0
00489 || mrss->version == MRSS_VERSION_0_92)
00490 {
00491 if (item->source)
00492 {
00493 func (obj, " <source");
00494
00495 if (item->source_url)
00496 {
00497 func (obj, " url=\"");
00498 __mrss_write_string (func, obj, item->source_url);
00499 func (obj, "\"");
00500 }
00501
00502 func (obj, ">");
00503 __mrss_write_string (func, obj, item->source);
00504 func (obj, "</source>\n");
00505 }
00506
00507 if (item->enclosure)
00508 {
00509 func (obj, " <enclosure");
00510
00511 if (item->enclosure_url)
00512 {
00513 func (obj, " url=\"");
00514 __mrss_write_string (func, obj, item->enclosure_url);
00515 func (obj, "\"");
00516 }
00517
00518 if (item->enclosure_length)
00519 func (obj, " length=\"%d\"", item->enclosure_length);
00520
00521 if (item->enclosure_type)
00522 {
00523 func (obj, " type=\"");
00524 __mrss_write_string (func, obj, item->enclosure_type);
00525 func (obj, "\"");
00526 }
00527
00528 func (obj, ">");
00529 __mrss_write_string (func, obj, item->enclosure);
00530 func (obj, "</enclosure>\n");
00531
00532 }
00533
00534 category = item->category;
00535 while (category)
00536 {
00537 func (obj, " <category");
00538
00539 if (category->domain)
00540 {
00541 func (obj, " domain=\"");
00542 __mrss_write_string (func, obj, category->domain);
00543 func (obj, "\"");
00544 }
00545
00546 func (obj, ">");
00547 __mrss_write_string (func, obj, category->category);
00548 func (obj, "</category>\n");
00549
00550 category = category->next;
00551 }
00552 }
00553
00554 func (obj, " </item>\n");
00555
00556 item = item->next;
00557 }
00558
00559 func (obj, " </channel>\n");
00560 func (obj, "</rss>\n");
00561
00562 return MRSS_OK;
00563 }
00564
00565 static void
00566 __mrss_file_write (void *obj, char *str, ...)
00567 {
00568 va_list va;
00569
00570 va_start (va, str);
00571 vfprintf ((FILE *) obj, str, va);
00572 va_end (va);
00573 }
00574
00575 static void
00576 __mrss_buffer_write (void *obj, char *str, ...)
00577 {
00578 va_list va;
00579 char s[4096];
00580 int len;
00581 char **buffer = (char **) obj;
00582
00583 va_start (va, str);
00584 len = vsnprintf (s, sizeof (s), str, va);
00585 va_end (va);
00586
00587 if (!*buffer)
00588 {
00589 if (!(*buffer = (char *) malloc (sizeof (char) * (len + 1))))
00590 return;
00591
00592 strncpy (*buffer, s, len);
00593 }
00594 else
00595 {
00596 if (!(*buffer = (char *) realloc (*buffer,
00597 sizeof (char) * (strlen (*buffer) +
00598 len + 1))))
00599 return;
00600 strncat (*buffer, s, len);
00601 }
00602 }
00603
00604
00605
00606 mrss_error_t
00607 mrss_write_file (mrss_t * mrss, char *file)
00608 {
00609 FILE *fl;
00610 mrss_error_t ret;
00611
00612 if (!mrss || !file)
00613 return MRSS_ERR_DATA;
00614
00615 if (!(fl = fopen (file, "wb")))
00616 return MRSS_ERR_POSIX;
00617
00618 ret = __mrss_write_real (mrss, __mrss_file_write, fl);
00619 fclose (fl);
00620
00621 return ret;
00622 }
00623
00624 mrss_error_t
00625 mrss_write_buffer (mrss_t * mrss, char **buffer)
00626 {
00627 if (!mrss || !buffer)
00628 return MRSS_ERR_DATA;
00629
00630 return __mrss_write_real (mrss, __mrss_buffer_write, buffer);
00631 }
00632
00633