sub.c - sub - subscene.com subtitle search
 (HTM) git clone git://git.codemadness.org/sub
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       sub.c (3649B)
       ---
            1 #include <sys/types.h>
            2 
            3 #include <ctype.h>
            4 #include <errno.h>
            5 #include <stdio.h>
            6 #include <stdlib.h>
            7 #include <string.h>
            8 #include <strings.h>
            9 #ifdef __OpenBSD__
           10 #include <unistd.h>
           11 #else
           12 #define pledge(a,b) 0
           13 #endif
           14 
           15 #include "util.h"
           16 #include "xml.h"
           17 
           18 struct sub {
           19         int issub;
           20         char title[256];
           21         char lang[256];
           22         int hi;
           23         int files;
           24         char author[256];
           25         char authorurl[256];
           26         char description[256];
           27         char url[4096];
           28 };
           29 
           30 static XMLParser parser; /* XML parser state */
           31 static struct sub sub;
           32 static char curclass[64];
           33 static char spanclass[64];
           34 
           35 static int
           36 istag(const char *s1, const char *s2)
           37 {
           38         return !strcasecmp(s1, s2);
           39 }
           40 
           41 static int
           42 isattr(const char *s1, const char *s2)
           43 {
           44         return !strcasecmp(s1, s2);
           45 }
           46 
           47 static void
           48 xml_handler_data(XMLParser *p, const char *data, size_t datalen)
           49 {
           50         char *s = "";
           51         char buf[1024];
           52         size_t len;
           53 
           54         if (!curclass[0])
           55                 return;
           56 
           57         /* skip leading space */
           58         for (s = (char *)data; *s && isspace((unsigned char)*s); s++)
           59                 ;
           60         strlcpy(buf, s, sizeof(buf));
           61         for (s = buf; *s; s++) {
           62                 if (*s == '\r' || *s == '\n')
           63                         *s = ' ';
           64         }
           65         /* trim remaining space */
           66         len = strlen(buf);
           67         for (; len > 0; len--) {
           68                 if (!isspace((unsigned char)buf[len - 1]))
           69                         break;
           70                 buf[len - 1] = '\0';
           71         }
           72 
           73         s = buf;
           74         if (!*s)
           75                 return;
           76         if (strcmp(curclass, "a1") == 0) {
           77                 /* link */
           78                 if (strcmp(spanclass, "") == 0)
           79                         strlcpy(sub.title, s, sizeof(sub.title));
           80                 else
           81                         strlcpy(sub.lang, s, sizeof(sub.lang));
           82         } else if (strcmp(curclass, "a3") == 0) {
           83                 /* files */
           84                 sub.files = atoi(s);
           85         } else if (strcmp(curclass, "a41") == 0) {
           86                 /* hearing impaired? */
           87                 sub.hi = 1;
           88         } else if (strcmp(curclass, "a5") == 0) {
           89                 /* author / user profile */
           90                 strlcpy(sub.author, s, sizeof(sub.author));
           91         } else if (strcmp(curclass, "a6") == 0) {
           92                 /* description */
           93                 strlcpy(sub.description, s, sizeof(sub.description));
           94         }
           95 }
           96 
           97 static void
           98 xml_handler_start_element(XMLParser *p, const char *tag, size_t taglen)
           99 {
          100         (void)p;
          101         (void)taglen;
          102 
          103         if (istag(tag, "tr"))
          104                 memset(&sub, 0, sizeof(sub));
          105 }
          106 
          107 static void
          108 xml_handler_end_element(XMLParser *p, const char *tag, size_t taglen,
          109         int isshort)
          110 {
          111         (void)p;
          112         (void)taglen;
          113         (void)isshort;
          114 
          115         if (istag(tag, "tr") && sub.issub == 1) {
          116                 printf("LANG:%s\tTITLE:%s\tURL:https://subscene.com%s\tHI:%d\tFILES:%d\tAUTHOR:%s\n",
          117                        sub.lang, sub.title, sub.url, sub.hi, sub.files, sub.author);
          118         } else if (istag(tag, "td")) {
          119                 curclass[0] = '\0';
          120         } else if (istag(tag, "span")) {
          121                 spanclass[0] = '\0';
          122         }
          123 }
          124 
          125 static void
          126 xml_handler_attr(XMLParser *p, const char *tag, size_t taglen,
          127         const char *name, size_t namelen, const char *value, size_t valuelen)
          128 {
          129         (void)p;
          130         (void)taglen;
          131         (void)namelen;
          132         (void)valuelen;
          133 
          134         if (istag(tag, "td")) {
          135                 if (isattr(name, "class")) {
          136                         strlcpy(curclass, value, sizeof(curclass));
          137                         /* link */
          138                         if (strcmp(value, "a1") == 0)
          139                                 sub.issub = 1;
          140                 }
          141         } else if (istag(tag, "span")) {
          142                 if (strcmp(curclass, "a1") == 0) {
          143                         if (isattr(name, "class"))
          144                                 strlcpy(spanclass, value, sizeof(spanclass));
          145                 }
          146         } else if (istag(tag, "a")) {
          147                 /* subtitle / author profile url */
          148                 if (strcmp(name, "href") == 0) {
          149                         if ((strcmp(curclass, "a1") == 0))
          150                                 strlcpy(sub.url, value, sizeof(sub.url));
          151                         else if ((strcmp(curclass, "a5") == 0))
          152                                 strlcpy(sub.authorurl, value, sizeof(sub.authorurl));
          153                 }
          154         }
          155 }
          156 
          157 int
          158 main(void)
          159 {
          160         if (pledge("stdio", NULL) < 0) {
          161                 fprintf(stderr, "pledge: %s\n", strerror(errno));
          162                 return 1;
          163         }
          164 
          165         parser.xmltagstart = xml_handler_start_element;
          166         parser.xmltagend = xml_handler_end_element;
          167         parser.xmlattr = xml_handler_attr;
          168         parser.xmldata = xml_handler_data;
          169 
          170         parser.getnext = getchar;
          171 
          172         xml_parse(&parser);
          173 
          174         return 0;
          175 }