root/temp/parse.c

Revision 14, 8.3 kB (checked in by inz, 2 years ago)

Fixed this.

Line 
1 #include <stdlib.h>
2 #include <unistd.h>
3 #include <string.h>
4 #include <fcntl.h>
5 #include <stdio.h>
6 #include <glib.h>
7 #include <curl/curl.h>
8
9 typedef size_t (*MaemoRequestDataFunc)(void *data,
10                 size_t size,
11                 size_t nmemb,
12                 void *user_data);
13
14 const char *rel_wanted = "EditURI";
15
16 enum State {
17         TAG = 1 << 0,
18         LINK = 1 << 1,
19         REL = 1 << 2,
20         HREF = 1 << 3,
21         SQUOT = 1 << 4,
22         DQUOT = 1 << 5,
23         COMM = 1 << 6,
24         STYLE = 1 << 7,
25         FINISHED = 1 << 8,
26 };
27
28 static size_t _read_data(void *ptr, size_t size, size_t nmemb, void *user_data);
29 static gboolean _curl_multi_perform(GIOChannel *chan, GIOCondition cond, gpointer data);
30
31 struct request {
32         char buffer[1024];
33         size_t offset;
34         CURL *curl_req;
35         CURLM *curl_mult;
36         char *start_tag;
37         char *start_rel;
38         char *start_href;
39         char *last_space;
40         char *rel;
41         char *href;
42         enum State state;
43 };
44
45 struct request *maemo_blog_request_new(const char *url) {
46         struct request *retval;
47         fd_set set_read, set_write, set_execp;
48         int max_fd, i;
49
50         retval = g_new0(struct request, 1);
51
52         retval->curl_req = curl_easy_init();
53         retval->curl_mult = curl_multi_init();
54
55         curl_easy_setopt(retval->curl_req, CURLOPT_URL, url);
56         curl_easy_setopt(retval->curl_req, CURLOPT_FOLLOWLOCATION, 1);
57         curl_easy_setopt(retval->curl_req, CURLOPT_WRITEDATA, retval);
58         curl_easy_setopt(retval->curl_req, CURLOPT_WRITEFUNCTION, _read_data);
59         curl_multi_add_handle(retval->curl_mult, retval->curl_req);
60
61         while (CURLM_CALL_MULTI_PERFORM ==
62                         curl_multi_perform(retval->curl_mult, &i));
63
64         if (!i) {
65                 curl_multi_cleanup(retval->curl_mult);
66                 curl_easy_cleanup(retval->curl_req);
67                 g_free(retval);
68                 return NULL;
69         }
70
71         FD_ZERO(&set_read);
72         FD_ZERO(&set_write);
73         FD_ZERO(&set_execp);
74        
75         curl_multi_fdset(retval->curl_mult, &set_read, &set_write, &set_execp, &max_fd);
76
77         for (i = 0; i <= max_fd; i++) {
78                 if (FD_ISSET(i, &set_read) || FD_ISSET(i, &set_write)) {
79                         GIOChannel *chan = g_io_channel_unix_new(i);
80                         g_io_add_watch(chan,
81                                         G_IO_IN | G_IO_OUT | G_IO_PRI | G_IO_ERR | G_IO_HUP,
82                                         _curl_multi_perform,
83                                         retval);
84                 }
85         }
86
87         return retval;
88 }
89
90 static size_t _read_data(void *ptr, size_t size, size_t nmemb, void *user_data)
91 {
92         struct request *req = user_data;
93         size_t bytes_used = 0;
94
95         while (bytes_used < size * nmemb) {
96                 size_t bytes;
97                 size_t i;
98
99                 bytes = 1024 - req->offset;
100                 if (size * nmemb < bytes - bytes_used) {
101                         bytes = size * nmemb - bytes_used;
102                 }
103
104                 memcpy(req->buffer + req->offset, ptr + bytes_used, bytes);
105                 bytes_used += bytes;
106
107                 for (i = req->offset; i < bytes + req->offset; i++) {
108                         if (req->state & COMM) {
109                                 if (req->buffer[i] == '-') {
110                                         if (req->start_tag == req->buffer + i - 2) {
111                                                 req->start_tag = &req->buffer[i - 1];
112                                         } else if (req->start_tag != req->buffer + i - 1) {
113                                                 req->start_tag = &req->buffer[i];
114                                         }
115                                 } else if (req->buffer[i] == '>') {
116                                         if (req->start_tag && strncmp(req->start_tag, "-->", 3) == 0) {
117                                                 req->state &= ~COMM & ~TAG;
118                                         }
119                                         req->start_tag = NULL;
120                                 } else {
121                                         req->start_tag = NULL;
122                                 }
123                                 continue;
124                         } else if (req->state & STYLE) {
125                                 if (req->buffer[i] == '<') {
126                                         req->start_tag = &req->buffer[i];
127                                 } else if (req->buffer[i] == '>' &&
128                                                 req->start_tag) {
129                                         if (strncmp("</style>",
130                                                                 req->start_tag,
131                                                                 7) == 0) {
132                                                 req->state &= ~STYLE;
133                                         }
134                                         req->start_tag = NULL;
135                                 } else if (!strchr("/style", req->buffer[i])) {
136                                         req->start_tag = NULL;
137                                 }
138                         } else if (req->state & DQUOT) {
139                                 if (req->buffer[i] == '"') {
140                                         req->state &= ~DQUOT;
141                                         if (req->state & REL) {
142                                                 if (req->rel) { free(req->rel); }
143                                                 req->rel = g_strndup(req->start_rel + 1,
144                                                                 &req->buffer[i] - req->start_rel - 1);
145                                                 req->state &= ~REL;
146                                         } else if (req->state & HREF) {
147                                                 if (req->href) { free(req->href); }
148                                                 req->href = g_strndup(req->start_href + 1,
149                                                                 &req->buffer[i] - req->start_href - 1);
150                                                 req->state &= ~HREF;
151                                         }
152                                 }
153                                 continue;
154                         } else if (req->state & SQUOT) {
155                                 if (req->buffer[i] == '\'') {
156                                         req->state &= ~SQUOT;
157                                         if (req->state & REL) {
158                                                 if (req->rel) { free(req->rel); }
159                                                 req->rel = g_strndup(req->start_rel + 1,
160                                                                 &req->buffer[i] - req->start_rel - 1);
161                                                 req->state &= ~REL;
162                                         } else if (req->state & HREF) {
163                                                 if (req->href) { free(req->href); }
164                                                 req->href = g_strndup(req->start_href + 1,
165                                                                 &req->buffer[i] - req->start_href - 1);
166                                                 req->state &= ~HREF;
167                                         }
168                                 }
169                                 continue;
170                         } else if (req->state & LINK) {
171                                 if (req->buffer[i] == ' ') {
172                                         req->last_space = &req->buffer[i];
173                                 } else if (req->buffer[i] == '=') {
174                                         if (strncmp(req->last_space, " rel=", 5) == 0) {
175                                                 req->state |= REL;
176                                         } else if (strncmp(req->last_space, " href=", 6) == 0) {
177                                                 req->state |= HREF;
178                                         }
179                                 } else if (req->buffer[i] == '>') {
180                                         if (req->rel && strcmp(req->rel, rel_wanted) == 0) {
181                                                 req->state = FINISHED;
182                                                 break;
183                                         }
184                                         if (req->rel) { free(req->rel); req->rel = NULL; }
185                                         if (req->href) { free(req->href); req->href = NULL; }
186                                         req->state &= ~LINK & ~TAG;
187                                         req->start_tag = NULL;
188                                 } else if (req->buffer[i] == '\'') {
189                                         req->state |= SQUOT;
190                                         if (req->state & REL) {
191                                                 req->start_rel = &req->buffer[i];
192                                         } else if (req->state & HREF) {
193                                                 req->start_href = &req->buffer[i];
194                                         }
195                                 } else if (req->buffer[i] == '"') {
196                                         req->state |= DQUOT;
197                                         if (req->state & REL) {
198                                                 req->start_rel = &req->buffer[i];
199                                         } else if (req->state & HREF) {
200                                                 req->start_href = &req->buffer[i];
201                                         }
202                                 }
203                                 continue;
204                         } else if (req->state & TAG) {
205                                 if (req->buffer[i] == '>') {
206                                         req->state &= ~TAG;
207                                         req->start_tag = NULL;
208                                 } else if (req->buffer[i] == '-') {
209                                         if (strncmp(req->start_tag, "<!--", 4) == 0) {
210                                                 req->state |= COMM;
211                                                 req->start_tag = NULL;
212                                         }
213                                 } else if (req->buffer[i] == ' ') {
214                                         if (!(req->state & LINK)) {
215                                                 if (strncmp(req->start_tag, "<link ", 6) == 0) {
216                                                         req->state |= LINK;
217                                                 }
218                                                 else if (strncmp(req->start_tag, "<style ", 7) == 0) {
219                                                         req->state |= STYLE;
220                                                 }
221                                         }
222                                         req->last_space = &req->buffer[i];
223                                 } else if (req->buffer[i] == '\'') {
224                                         req->state |= SQUOT;
225                                         if (req->state & REL) {
226                                                 req->start_rel = &req->buffer[i];
227                                         } else if (req->state & HREF) {
228                                                 req->start_href = &req->buffer[i];
229                                         }
230                                 } else if (req->buffer[i] == '"') {
231                                         req->state |= DQUOT;
232                                         if (req->state & REL) {
233                                                 req->start_rel = &req->buffer[i];
234                                         } else if (req->state & HREF) {
235                                                 req->start_href = &req->buffer[i];
236                                         }
237                                 }
238                                 continue;
239                         } else {
240                                 if (req->buffer[i] == '<') {
241                                         req->start_tag = &req->buffer[i];
242                                         req->state |= TAG;
243                                 }
244                         }
245                 }
246
247                 if (req->state & FINISHED) {
248                         printf("%s\n", req->rel);
249                         printf("%s\n", req->href);
250                         break;
251                 }
252                 if (req->start_tag && (req->start_tag != req->buffer || req->offset + bytes >= 1000)) {
253                         req->offset = (bytes + req->offset) - (req->start_tag - req->buffer);
254                         printf("Offset: %u, %u, %p, %p\n", req->offset, bytes, req->start_tag, req->buffer);
255                         memmove(req->buffer, req->start_tag, req->offset);
256                         if (req->start_rel) {
257                                 req->start_rel -= req->start_tag - req->buffer;
258                         }
259                         if (req->start_href) {
260                                 req->start_href -= req->start_tag - req->buffer;
261                         }
262                         if (req->last_space) {
263                                 req->last_space -= req->start_tag - req->buffer;
264                         }
265                         req->start_tag = req->buffer;
266                 } else {
267                         req->offset = 0;
268                         printf("Offset: %u\n", req->offset);
269                         req->start_tag = NULL;
270                         req->start_rel = NULL;
271                         req->start_href = NULL;
272                         req->state &= COMM;
273                 }
274         }
275
276         return bytes_used / size;
277 }
278
279 static gboolean still_running(gpointer data) {
280         printf("%s\n", (const char *)data);
281         return TRUE;
282 }
283
284
285 int main(int argc, char **argv)
286 {
287         GMainLoop *loop = g_main_loop_new(NULL, FALSE);
288         struct request *req = maemo_blog_request_new(argv[1]);
289        
290         g_timeout_add(200, still_running, "Still happily running.");
291         g_main_loop_run(loop);
292
293         return 0;
294 }
295
296 static gboolean _curl_multi_perform(GIOChannel *chan, GIOCondition cond, gpointer data)
297 {
298         struct request *req = data;
299         int running;
300         (void)chan;
301         (void)cond;
302
303         while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(req->curl_mult, &running));
304
305         if (!running) {
306                 if (req->rel && req->href && strcmp(req->rel, rel_wanted) == 0) {
307                         printf("Request successfully finished: %s!\n", req->href);
308                 } else {
309                         printf("Request failed. =(\n");
310                 }
311                 return FALSE;
312         }
313
314         return TRUE;
315 }
Note: See TracBrowser for help on using the browser.