sfeed_web.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. #include <stdio.h>
  2. #include <strings.h>
  3. #include "util.h"
  4. #include "xml.h"
  5. /* string and size */
  6. #define STRP(s) s,sizeof(s)-1
  7. static XMLParser parser;
  8. static int isbasetag, islinktag, ishrefattr, istypeattr;
  9. static char linkhref[4096], linktype[256], basehref[4096];
  10. static void
  11. printvalue(const char *s)
  12. {
  13. for (; *s; s++)
  14. if (!ISCNTRL((unsigned char)*s))
  15. putchar(*s);
  16. }
  17. static void
  18. xmltagstart(XMLParser *p, const char *t, size_t tl)
  19. {
  20. isbasetag = islinktag = 0;
  21. if (!strcasecmp(t, "base")) {
  22. isbasetag = 1;
  23. } else if (!strcasecmp(t, "link")) {
  24. islinktag = 1;
  25. linkhref[0] = '\0';
  26. linktype[0] = '\0';
  27. }
  28. }
  29. static void
  30. xmltagstartparsed(XMLParser *p, const char *t, size_t tl, int isshort)
  31. {
  32. struct uri baseuri, linkuri, u;
  33. char buf[4096];
  34. int r = -1;
  35. if (!islinktag)
  36. return;
  37. if (strncasecmp(linktype, STRP("application/atom")) &&
  38. strncasecmp(linktype, STRP("application/xml")) &&
  39. strncasecmp(linktype, STRP("application/rss")))
  40. return;
  41. /* parse base URI each time: it can change. */
  42. if (basehref[0] &&
  43. uri_parse(linkhref, &linkuri) != -1 && !linkuri.proto[0] &&
  44. uri_parse(basehref, &baseuri) != -1 &&
  45. uri_makeabs(&u, &linkuri, &baseuri) != -1 && u.proto[0])
  46. r = uri_format(buf, sizeof(buf), &u);
  47. if (r >= 0 && (size_t)r < sizeof(buf))
  48. printvalue(buf);
  49. else
  50. printvalue(linkhref);
  51. putchar('\t');
  52. printvalue(linktype);
  53. putchar('\n');
  54. }
  55. static void
  56. xmlattrstart(XMLParser *p, const char *t, size_t tl, const char *a, size_t al)
  57. {
  58. ishrefattr = istypeattr = 0;
  59. if (!isbasetag && !islinktag)
  60. return;
  61. if (!strcasecmp(a, "href")) {
  62. ishrefattr = 1;
  63. if (isbasetag)
  64. basehref[0] = '\0';
  65. else if (islinktag)
  66. linkhref[0] = '\0';
  67. } else if (!strcasecmp(a, "type") && islinktag) {
  68. istypeattr = 1;
  69. linktype[0] = '\0';
  70. }
  71. }
  72. static void
  73. xmlattr(XMLParser *p, const char *t, size_t tl, const char *n, size_t nl,
  74. const char *v, size_t vl)
  75. {
  76. if (isbasetag && ishrefattr) {
  77. strlcat(basehref, v, sizeof(basehref));
  78. } else if (islinktag) {
  79. if (ishrefattr)
  80. strlcat(linkhref, v, sizeof(linkhref));
  81. else if (istypeattr)
  82. strlcat(linktype, v, sizeof(linktype));
  83. }
  84. }
  85. static void
  86. xmlattrentity(XMLParser *p, const char *t, size_t tl, const char *a, size_t al,
  87. const char *v, size_t vl)
  88. {
  89. char buf[16];
  90. int len;
  91. if (!ishrefattr && !istypeattr)
  92. return;
  93. /* try to translate entity, else just pass as data to
  94. * xmlattr handler. */
  95. if ((len = xml_entitytostr(v, buf, sizeof(buf))) > 0)
  96. xmlattr(p, t, tl, a, al, buf, (size_t)len);
  97. else
  98. xmlattr(p, t, tl, a, al, v, vl);
  99. }
  100. int
  101. main(int argc, char *argv[])
  102. {
  103. if (pledge("stdio", NULL) == -1)
  104. err(1, "pledge");
  105. if (argc > 1)
  106. strlcpy(basehref, argv[1], sizeof(basehref));
  107. parser.xmlattr = xmlattr;
  108. parser.xmlattrentity = xmlattrentity;
  109. parser.xmlattrstart = xmlattrstart;
  110. parser.xmltagstart = xmltagstart;
  111. parser.xmltagstartparsed = xmltagstartparsed;
  112. /* NOTE: getnext is defined in xml.h for inline optimization */
  113. xml_parse(&parser);
  114. checkfileerror(stdin, "<stdin>", 'r');
  115. checkfileerror(stdout, "<stdout>", 'w');
  116. return 0;
  117. }