sub.c - sub - subscene.com subtitle search | |
git clone git://git.codemadness.org/sub | |
Log | |
Files | |
Refs | |
README | |
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\tH… | |
117 sub.lang, sub.title, sub.url, sub.hi, sub.files, … | |
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 valu… | |
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(spancla… | |
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… | |
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 } |