source: protocols/yahoo/yahoo_httplib.c @ 60d0582

Last change on this file since 60d0582 was b7d3cc34, checked in by Wilmer van der Gaast <wilmer@…>, at 2005-11-06T18:23:18Z

Initial repository (0.99 release tree)

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