source: protocols/yahoo/yahoo_httplib.c @ 4fefb77

Last change on this file since 4fefb77 was fcc2da9, checked in by Jelmer Vernooij <jelmer@…>, at 2006-05-26T15:46:51Z

Remove unnecessary Windows-specific code.

  • Property mode set to 100644
File size: 8.8 KB
Line 
1/*
2 * libyahoo2: yahoo_httplib.c
3 *
4 * Copyright (C) 2002-2004, Philip S Tellis <philip.tellis AT gmx.net>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 *
20 */
21
22#include <stdio.h>
23#include <stdlib.h>
24
25#if STDC_HEADERS
26# include <string.h>
27#else
28# if !HAVE_STRCHR
29#  define strchr index
30#  define strrchr rindex
31# endif
32char *strchr (), *strrchr ();
33# if !HAVE_MEMCPY
34#  define memcpy(d, s, n) bcopy ((s), (d), (n))
35#  define memmove(d, s, n) bcopy ((s), (d), (n))
36# endif
37#endif
38
39
40#include <errno.h>
41#ifndef _WIN32
42#include <unistd.h>
43#endif
44#include <ctype.h>
45#include "yahoo2.h"
46#include "yahoo2_callbacks.h"
47#include "yahoo_httplib.h"
48#include "yahoo_util.h"
49
50#include "yahoo_debug.h"
51#ifdef __MINGW32__
52# include <winsock2.h>
53# define snprintf _snprintf
54#endif
55
56#ifdef USE_STRUCT_CALLBACKS
57extern struct yahoo_callbacks *yc;
58#define YAHOO_CALLBACK(x)       yc->x
59#else
60#define YAHOO_CALLBACK(x)       x
61#endif
62
63extern enum yahoo_log_level log_level;
64
65int yahoo_tcp_readline(char *ptr, int maxlen, int fd)
66{
67        int n, rc;
68        char c;
69
70        for (n = 1; n < maxlen; n++) {
71
72                do {
73                        rc = read(fd, &c, 1);
74                } while(rc == -1 && (errno == EINTR || errno == EAGAIN)); /* this is bad - it should be done asynchronously */
75
76                if (rc == 1) {
77                        if(c == '\r')                   /* get rid of \r */
78                                continue;
79                        *ptr = c;
80                        if (c == '\n')
81                                break;
82                        ptr++;
83                } else if (rc == 0) {
84                        if (n == 1)
85                                return (0);             /* EOF, no data */
86                        else
87                                break;                  /* EOF, w/ data */
88                } else {
89                        return -1;
90                }
91        }
92
93        *ptr = 0;
94        return (n);
95}
96
97static int url_to_host_port_path(const char *url,
98                char *host, int *port, char *path)
99{
100        char *urlcopy=NULL;
101        char *slash=NULL;
102        char *colon=NULL;
103       
104        /*
105         * http://hostname
106         * http://hostname/
107         * http://hostname/path
108         * http://hostname/path:foo
109         * http://hostname:port
110         * http://hostname:port/
111         * http://hostname:port/path
112         * http://hostname:port/path:foo
113         */
114
115        if(strstr(url, "http://") == url) {
116                urlcopy = strdup(url+7);
117        } else {
118                WARNING(("Weird url - unknown protocol: %s", url));
119                return 0;
120        }
121
122        slash = strchr(urlcopy, '/');
123        colon = strchr(urlcopy, ':');
124
125        if(!colon || (slash && slash < colon)) {
126                *port = 80;
127        } else {
128                *colon = 0;
129                *port = atoi(colon+1);
130        }
131
132        if(!slash) {
133                strcpy(path, "/");
134        } else {
135                strcpy(path, slash);
136                *slash = 0;
137        }
138
139        strcpy(host, urlcopy);
140       
141        FREE(urlcopy);
142
143        return 1;
144}
145
146static int isurlchar(unsigned char c)
147{
148        return (isalnum(c) || '-' == c || '_' == c);
149}
150
151char *yahoo_urlencode(const char *instr)
152{
153        int ipos=0, bpos=0;
154        char *str = NULL;
155        int len = strlen(instr);
156
157        if(!(str = y_new(char, 3*len + 1) ))
158                return "";
159
160        while(instr[ipos]) {
161                while(isurlchar(instr[ipos]))
162                        str[bpos++] = instr[ipos++];
163                if(!instr[ipos])
164                        break;
165               
166                snprintf(&str[bpos], 4, "%%%.2x", instr[ipos]);
167                bpos+=3;
168                ipos++;
169        }
170        str[bpos]='\0';
171
172        /* free extra alloc'ed mem. */
173        len = strlen(str);
174        str = y_renew(char, str, len+1);
175
176        return (str);
177}
178
179char *yahoo_urldecode(const char *instr)
180{
181        int ipos=0, bpos=0;
182        char *str = NULL;
183        char entity[3]={0,0,0};
184        unsigned dec;
185        int len = strlen(instr);
186
187        if(!(str = y_new(char, len+1) ))
188                return "";
189
190        while(instr[ipos]) {
191                while(instr[ipos] && instr[ipos]!='%')
192                        if(instr[ipos]=='+') {
193                                str[bpos++]=' ';
194                                ipos++;
195                        } else
196                                str[bpos++] = instr[ipos++];
197                if(!instr[ipos])
198                        break;
199               
200                if(instr[ipos+1] && instr[ipos+2]) {
201                        ipos++;
202                        entity[0]=instr[ipos++];
203                        entity[1]=instr[ipos++];
204                        sscanf(entity, "%2x", &dec);
205                        str[bpos++] = (char)dec;
206                } else {
207                        str[bpos++] = instr[ipos++];
208                }
209        }
210        str[bpos]='\0';
211
212        /* free extra alloc'ed mem. */
213        len = strlen(str);
214        str = y_renew(char, str, len+1);
215
216        return (str);
217}
218
219char *yahoo_xmldecode(const char *instr)
220{
221        int ipos=0, bpos=0, epos=0;
222        char *str = NULL;
223        char entity[4]={0,0,0,0};
224        char *entitymap[5][2]={
225                {"amp;",  "&"}, 
226                {"quot;", "\""},
227                {"lt;",   "<"}, 
228                {"gt;",   "<"}, 
229                {"nbsp;", " "}
230        };
231        unsigned dec;
232        int len = strlen(instr);
233
234        if(!(str = y_new(char, len+1) ))
235                return "";
236
237        while(instr[ipos]) {
238                while(instr[ipos] && instr[ipos]!='&')
239                        if(instr[ipos]=='+') {
240                                str[bpos++]=' ';
241                                ipos++;
242                        } else
243                                str[bpos++] = instr[ipos++];
244                if(!instr[ipos] || !instr[ipos+1])
245                        break;
246                ipos++;
247
248                if(instr[ipos] == '#') {
249                        ipos++;
250                        epos=0;
251                        while(instr[ipos] != ';')
252                                entity[epos++]=instr[ipos++];
253                        sscanf(entity, "%u", &dec);
254                        str[bpos++] = (char)dec;
255                        ipos++;
256                } else {
257                        int i;
258                        for (i=0; i<5; i++) 
259                                if(!strncmp(instr+ipos, entitymap[i][0], 
260                                               strlen(entitymap[i][0]))) {
261                                        str[bpos++] = entitymap[i][1][0];
262                                        ipos += strlen(entitymap[i][0]);
263                                        break;
264                                }
265                }
266        }
267        str[bpos]='\0';
268
269        /* free extra alloc'ed mem. */
270        len = strlen(str);
271        str = y_renew(char, str, len+1);
272
273        return (str);
274}
275
276typedef void (*http_connected)(int id, int fd, int error);
277
278struct callback_data {
279        int id;
280        yahoo_get_fd_callback callback;
281        char *request;
282        void *user_data;
283};
284
285static void connect_complete(int fd, int error, void *data)
286{
287        struct callback_data *ccd = data;
288        if(error == 0 && fd > 0)
289                write(fd, ccd->request, strlen(ccd->request));
290        FREE(ccd->request);
291        ccd->callback(ccd->id, fd, error, ccd->user_data);
292        FREE(ccd);
293}
294
295static void yahoo_send_http_request(int id, char *host, int port, char *request, 
296                yahoo_get_fd_callback callback, void *data)
297{
298        struct callback_data *ccd=y_new0(struct callback_data, 1);
299        ccd->callback = callback;
300        ccd->id = id;
301        ccd->request = strdup(request);
302        ccd->user_data = data;
303       
304        YAHOO_CALLBACK(ext_yahoo_connect_async)(id, host, port, connect_complete, ccd);
305}
306
307void yahoo_http_post(int id, const char *url, const char *cookies, long content_length,
308                yahoo_get_fd_callback callback, void *data)
309{
310        char host[255];
311        int port = 80;
312        char path[255];
313        char buff[1024];
314       
315        if(!url_to_host_port_path(url, host, &port, path))
316                return;
317
318        snprintf(buff, sizeof(buff), 
319                        "POST %s HTTP/1.0\r\n"
320                        "Content-length: %ld\r\n"
321                        "User-Agent: Mozilla/4.5 [en] (" PACKAGE "/" VERSION ")\r\n"
322                        "Host: %s:%d\r\n"
323                        "Cookie: %s\r\n"
324                        "\r\n",
325                        path, content_length, 
326                        host, port,
327                        cookies);
328
329        yahoo_send_http_request(id, host, port, buff, callback, data);
330}
331
332void yahoo_http_get(int id, const char *url, const char *cookies,
333                yahoo_get_fd_callback callback, void *data)
334{
335        char host[255];
336        int port = 80;
337        char path[255];
338        char buff[1024];
339       
340        if(!url_to_host_port_path(url, host, &port, path))
341                return;
342
343        snprintf(buff, sizeof(buff), 
344                        "GET %s HTTP/1.0\r\n"
345                        "Host: %s:%d\r\n"
346                        "User-Agent: Mozilla/4.5 [en] (" PACKAGE "/" VERSION ")\r\n"
347                        "Cookie: %s\r\n"
348                        "\r\n",
349                        path, host, port, cookies);
350
351        yahoo_send_http_request(id, host, port, buff, callback, data);
352}
353
354struct url_data {
355        yahoo_get_url_handle_callback callback;
356        void *user_data;
357};
358
359static void yahoo_got_url_fd(int id, int fd, int error, void *data)
360{
361        char *tmp=NULL;
362        char buff[1024];
363        unsigned long filesize=0;
364        char *filename=NULL;
365        int n;
366
367        struct url_data *ud = data;
368
369        if(error || fd < 0) {
370                ud->callback(id, fd, error, filename, filesize, ud->user_data);
371                FREE(ud);
372                return;
373        }
374
375        while((n=yahoo_tcp_readline(buff, sizeof(buff), fd)) > 0) {
376                LOG(("Read:%s:\n", buff));
377                if(!strcmp(buff, ""))
378                        break;
379
380                if( !strncasecmp(buff, "Content-length:", 
381                                strlen("Content-length:")) ) {
382                        tmp = strrchr(buff, ' ');
383                        if(tmp)
384                                filesize = atol(tmp);
385                }
386
387                if( !strncasecmp(buff, "Content-disposition:", 
388                                strlen("Content-disposition:")) ) {
389                        tmp = strstr(buff, "name=");
390                        if(tmp) {
391                                tmp+=strlen("name=");
392                                if(tmp[0] == '"') {
393                                        char *tmp2;
394                                        tmp++;
395                                        tmp2 = strchr(tmp, '"');
396                                        if(tmp2)
397                                                *tmp2 = '\0';
398                                } else {
399                                        char *tmp2;
400                                        tmp2 = strchr(tmp, ';');
401                                        if(!tmp2)
402                                                tmp2 = strchr(tmp, '\r');
403                                        if(!tmp2)
404                                                tmp2 = strchr(tmp, '\n');
405                                        if(tmp2)
406                                                *tmp2 = '\0';
407                                }
408
409                                filename = strdup(tmp);
410                        }
411                }
412        }
413
414        LOG(("n == %d\n", n));
415        LOG(("Calling callback, filename:%s, size: %ld\n", filename, filesize));
416        ud->callback(id, fd, error, filename, filesize, ud->user_data);
417        FREE(ud);
418        FREE(filename);
419}
420
421void yahoo_get_url_fd(int id, const char *url, const struct yahoo_data *yd,
422                yahoo_get_url_handle_callback callback, void *data)
423{
424        char buff[1024];
425        struct url_data *ud = y_new0(struct url_data, 1);
426        snprintf(buff, sizeof(buff), "Y=%s; T=%s", yd->cookie_y, yd->cookie_t);
427        ud->callback = callback;
428        ud->user_data = data;
429        yahoo_http_get(id, url, buff, yahoo_got_url_fd, ud);
430}
431
Note: See TracBrowser for help on using the repository browser.