source: protocols/yahoo/yahoo_httplib.c @ f9756bd

Last change on this file since f9756bd was c3c2e14, checked in by Wilmer van der Gaast <wilmer@…>, at 2005-11-30T12:12:25Z

Got rid of the config.h includes in IM-code. Now that HAVE_CONFIG_H is
defined, they started to cause problems.

  • Property mode set to 100644
File size: 8.9 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 write(a,b,c) send(a,b,c,0)
54# define read(a,b,c)  recv(a,b,c,0)
55# define snprintf _snprintf
56#endif
57
58#ifdef USE_STRUCT_CALLBACKS
59extern struct yahoo_callbacks *yc;
60#define YAHOO_CALLBACK(x)       yc->x
61#else
62#define YAHOO_CALLBACK(x)       x
63#endif
64
65extern enum yahoo_log_level log_level;
66
67int yahoo_tcp_readline(char *ptr, int maxlen, int fd)
68{
69        int n, rc;
70        char c;
71
72        for (n = 1; n < maxlen; n++) {
73
74                do {
75                        rc = read(fd, &c, 1);
76                } while(rc == -1 && (errno == EINTR || errno == EAGAIN)); /* this is bad - it should be done asynchronously */
77
78                if (rc == 1) {
79                        if(c == '\r')                   /* get rid of \r */
80                                continue;
81                        *ptr = c;
82                        if (c == '\n')
83                                break;
84                        ptr++;
85                } else if (rc == 0) {
86                        if (n == 1)
87                                return (0);             /* EOF, no data */
88                        else
89                                break;                  /* EOF, w/ data */
90                } else {
91                        return -1;
92                }
93        }
94
95        *ptr = 0;
96        return (n);
97}
98
99static int url_to_host_port_path(const char *url,
100                char *host, int *port, char *path)
101{
102        char *urlcopy=NULL;
103        char *slash=NULL;
104        char *colon=NULL;
105       
106        /*
107         * http://hostname
108         * http://hostname/
109         * http://hostname/path
110         * http://hostname/path:foo
111         * http://hostname:port
112         * http://hostname:port/
113         * http://hostname:port/path
114         * http://hostname:port/path:foo
115         */
116
117        if(strstr(url, "http://") == url) {
118                urlcopy = strdup(url+7);
119        } else {
120                WARNING(("Weird url - unknown protocol: %s", url));
121                return 0;
122        }
123
124        slash = strchr(urlcopy, '/');
125        colon = strchr(urlcopy, ':');
126
127        if(!colon || (slash && slash < colon)) {
128                *port = 80;
129        } else {
130                *colon = 0;
131                *port = atoi(colon+1);
132        }
133
134        if(!slash) {
135                strcpy(path, "/");
136        } else {
137                strcpy(path, slash);
138                *slash = 0;
139        }
140
141        strcpy(host, urlcopy);
142       
143        FREE(urlcopy);
144
145        return 1;
146}
147
148static int isurlchar(unsigned char c)
149{
150        return (isalnum(c) || '-' == c || '_' == c);
151}
152
153char *yahoo_urlencode(const char *instr)
154{
155        int ipos=0, bpos=0;
156        char *str = NULL;
157        int len = strlen(instr);
158
159        if(!(str = y_new(char, 3*len + 1) ))
160                return "";
161
162        while(instr[ipos]) {
163                while(isurlchar(instr[ipos]))
164                        str[bpos++] = instr[ipos++];
165                if(!instr[ipos])
166                        break;
167               
168                snprintf(&str[bpos], 4, "%%%.2x", instr[ipos]);
169                bpos+=3;
170                ipos++;
171        }
172        str[bpos]='\0';
173
174        /* free extra alloc'ed mem. */
175        len = strlen(str);
176        str = y_renew(char, str, len+1);
177
178        return (str);
179}
180
181char *yahoo_urldecode(const char *instr)
182{
183        int ipos=0, bpos=0;
184        char *str = NULL;
185        char entity[3]={0,0,0};
186        unsigned dec;
187        int len = strlen(instr);
188
189        if(!(str = y_new(char, len+1) ))
190                return "";
191
192        while(instr[ipos]) {
193                while(instr[ipos] && instr[ipos]!='%')
194                        if(instr[ipos]=='+') {
195                                str[bpos++]=' ';
196                                ipos++;
197                        } else
198                                str[bpos++] = instr[ipos++];
199                if(!instr[ipos])
200                        break;
201               
202                if(instr[ipos+1] && instr[ipos+2]) {
203                        ipos++;
204                        entity[0]=instr[ipos++];
205                        entity[1]=instr[ipos++];
206                        sscanf(entity, "%2x", &dec);
207                        str[bpos++] = (char)dec;
208                } else {
209                        str[bpos++] = instr[ipos++];
210                }
211        }
212        str[bpos]='\0';
213
214        /* free extra alloc'ed mem. */
215        len = strlen(str);
216        str = y_renew(char, str, len+1);
217
218        return (str);
219}
220
221char *yahoo_xmldecode(const char *instr)
222{
223        int ipos=0, bpos=0, epos=0;
224        char *str = NULL;
225        char entity[4]={0,0,0,0};
226        char *entitymap[5][2]={
227                {"amp;",  "&"}, 
228                {"quot;", "\""},
229                {"lt;",   "<"}, 
230                {"gt;",   "<"}, 
231                {"nbsp;", " "}
232        };
233        unsigned dec;
234        int len = strlen(instr);
235
236        if(!(str = y_new(char, len+1) ))
237                return "";
238
239        while(instr[ipos]) {
240                while(instr[ipos] && instr[ipos]!='&')
241                        if(instr[ipos]=='+') {
242                                str[bpos++]=' ';
243                                ipos++;
244                        } else
245                                str[bpos++] = instr[ipos++];
246                if(!instr[ipos] || !instr[ipos+1])
247                        break;
248                ipos++;
249
250                if(instr[ipos] == '#') {
251                        ipos++;
252                        epos=0;
253                        while(instr[ipos] != ';')
254                                entity[epos++]=instr[ipos++];
255                        sscanf(entity, "%u", &dec);
256                        str[bpos++] = (char)dec;
257                        ipos++;
258                } else {
259                        int i;
260                        for (i=0; i<5; i++) 
261                                if(!strncmp(instr+ipos, entitymap[i][0], 
262                                               strlen(entitymap[i][0]))) {
263                                        str[bpos++] = entitymap[i][1][0];
264                                        ipos += strlen(entitymap[i][0]);
265                                        break;
266                                }
267                }
268        }
269        str[bpos]='\0';
270
271        /* free extra alloc'ed mem. */
272        len = strlen(str);
273        str = y_renew(char, str, len+1);
274
275        return (str);
276}
277
278typedef void (*http_connected)(int id, int fd, int error);
279
280struct callback_data {
281        int id;
282        yahoo_get_fd_callback callback;
283        char *request;
284        void *user_data;
285};
286
287static void connect_complete(int fd, int error, void *data)
288{
289        struct callback_data *ccd = data;
290        if(error == 0 && fd > 0)
291                write(fd, ccd->request, strlen(ccd->request));
292        FREE(ccd->request);
293        ccd->callback(ccd->id, fd, error, ccd->user_data);
294        FREE(ccd);
295}
296
297static void yahoo_send_http_request(int id, char *host, int port, char *request, 
298                yahoo_get_fd_callback callback, void *data)
299{
300        struct callback_data *ccd=y_new0(struct callback_data, 1);
301        ccd->callback = callback;
302        ccd->id = id;
303        ccd->request = strdup(request);
304        ccd->user_data = data;
305       
306        YAHOO_CALLBACK(ext_yahoo_connect_async)(id, host, port, connect_complete, ccd);
307}
308
309void yahoo_http_post(int id, const char *url, const char *cookies, long content_length,
310                yahoo_get_fd_callback callback, void *data)
311{
312        char host[255];
313        int port = 80;
314        char path[255];
315        char buff[1024];
316       
317        if(!url_to_host_port_path(url, host, &port, path))
318                return;
319
320        snprintf(buff, sizeof(buff), 
321                        "POST %s HTTP/1.0\r\n"
322                        "Content-length: %ld\r\n"
323                        "User-Agent: Mozilla/4.5 [en] (" PACKAGE "/" VERSION ")\r\n"
324                        "Host: %s:%d\r\n"
325                        "Cookie: %s\r\n"
326                        "\r\n",
327                        path, content_length, 
328                        host, port,
329                        cookies);
330
331        yahoo_send_http_request(id, host, port, buff, callback, data);
332}
333
334void yahoo_http_get(int id, const char *url, const char *cookies,
335                yahoo_get_fd_callback callback, void *data)
336{
337        char host[255];
338        int port = 80;
339        char path[255];
340        char buff[1024];
341       
342        if(!url_to_host_port_path(url, host, &port, path))
343                return;
344
345        snprintf(buff, sizeof(buff), 
346                        "GET %s HTTP/1.0\r\n"
347                        "Host: %s:%d\r\n"
348                        "User-Agent: Mozilla/4.5 [en] (" PACKAGE "/" VERSION ")\r\n"
349                        "Cookie: %s\r\n"
350                        "\r\n",
351                        path, host, port, cookies);
352
353        yahoo_send_http_request(id, host, port, buff, callback, data);
354}
355
356struct url_data {
357        yahoo_get_url_handle_callback callback;
358        void *user_data;
359};
360
361static void yahoo_got_url_fd(int id, int fd, int error, void *data)
362{
363        char *tmp=NULL;
364        char buff[1024];
365        unsigned long filesize=0;
366        char *filename=NULL;
367        int n;
368
369        struct url_data *ud = data;
370
371        if(error || fd < 0) {
372                ud->callback(id, fd, error, filename, filesize, ud->user_data);
373                FREE(ud);
374                return;
375        }
376
377        while((n=yahoo_tcp_readline(buff, sizeof(buff), fd)) > 0) {
378                LOG(("Read:%s:\n", buff));
379                if(!strcmp(buff, ""))
380                        break;
381
382                if( !strncasecmp(buff, "Content-length:", 
383                                strlen("Content-length:")) ) {
384                        tmp = strrchr(buff, ' ');
385                        if(tmp)
386                                filesize = atol(tmp);
387                }
388
389                if( !strncasecmp(buff, "Content-disposition:", 
390                                strlen("Content-disposition:")) ) {
391                        tmp = strstr(buff, "name=");
392                        if(tmp) {
393                                tmp+=strlen("name=");
394                                if(tmp[0] == '"') {
395                                        char *tmp2;
396                                        tmp++;
397                                        tmp2 = strchr(tmp, '"');
398                                        if(tmp2)
399                                                *tmp2 = '\0';
400                                } else {
401                                        char *tmp2;
402                                        tmp2 = strchr(tmp, ';');
403                                        if(!tmp2)
404                                                tmp2 = strchr(tmp, '\r');
405                                        if(!tmp2)
406                                                tmp2 = strchr(tmp, '\n');
407                                        if(tmp2)
408                                                *tmp2 = '\0';
409                                }
410
411                                filename = strdup(tmp);
412                        }
413                }
414        }
415
416        LOG(("n == %d\n", n));
417        LOG(("Calling callback, filename:%s, size: %ld\n", filename, filesize));
418        ud->callback(id, fd, error, filename, filesize, ud->user_data);
419        FREE(ud);
420        FREE(filename);
421}
422
423void yahoo_get_url_fd(int id, const char *url, const struct yahoo_data *yd,
424                yahoo_get_url_handle_callback callback, void *data)
425{
426        char buff[1024];
427        struct url_data *ud = y_new0(struct url_data, 1);
428        snprintf(buff, sizeof(buff), "Y=%s; T=%s", yd->cookie_y, yd->cookie_t);
429        ud->callback = callback;
430        ud->user_data = data;
431        yahoo_http_get(id, url, buff, yahoo_got_url_fd, ud);
432}
433
Note: See TracBrowser for help on using the repository browser.