Ignore:
Timestamp:
2010-07-24T13:29:48Z (14 years ago)
Author:
Wilmer van der Gaast <wilmer@…>
Branches:
master
Children:
03f3828
Parents:
938c305 (diff), c495217 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merging libyahoo2 fixes. Now completely up-to-date with libyahoo2 svn
again, should try to keep it up a little bit better and submit my fixes
upstream.

This also adds code for Yahoo! file transfers but BitlBee isn't using it
yet. (It doesn't seem to support flow control which makes this complicated.)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • protocols/yahoo/yahoo_httplib.c

    r938c305 rc8791f2  
    3030#  define strrchr rindex
    3131# endif
    32 char *strchr (), *strrchr ();
     32char *strchr(), *strrchr();
    3333# if !HAVE_MEMCPY
    3434#  define memcpy(d, s, n) bcopy ((s), (d), (n))
     
    3636# endif
    3737#endif
    38 
    3938
    4039#include <errno.h>
     
    6362extern enum yahoo_log_level log_level;
    6463
    65 int yahoo_tcp_readline(char *ptr, int maxlen, int fd)
     64int yahoo_tcp_readline(char *ptr, int maxlen, void *fd)
    6665{
    6766        int n, rc;
     
    7170
    7271                do {
    73                         rc = read(fd, &c, 1);
    74                 } while(rc == -1 && (errno == EINTR || errno == EAGAIN)); /* this is bad - it should be done asynchronously */
     72                        rc = YAHOO_CALLBACK(ext_yahoo_read) (fd, &c, 1);
     73                } while (rc == -1 && (errno == EINTR || errno == EAGAIN));      /* this is bad - it should be done asynchronously */
    7574
    7675                if (rc == 1) {
    77                         if(c == '\r')                   /* get rid of \r */
     76                        if (c == '\r')  /* get rid of \r */
    7877                                continue;
    7978                        *ptr = c;
     
    8382                } else if (rc == 0) {
    8483                        if (n == 1)
    85                                 return (0);             /* EOF, no data */
     84                                return (0);     /* EOF, no data */
    8685                        else
    87                                 break;                  /* EOF, w/ data */
     86                                break;  /* EOF, w/ data */
    8887                } else {
    8988                        return -1;
     
    9695
    9796static 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        
     97        char *host, int *port, char *path, int *ssl)
     98{
     99        char *urlcopy = NULL;
     100        char *slash = NULL;
     101        char *colon = NULL;
     102
    104103        /*
    105104         * http://hostname
     
    111110         * http://hostname:port/path
    112111         * http://hostname:port/path:foo
     112         * and https:// variants of the above
    113113         */
    114114
    115         if(strstr(url, "http://") == url) {
    116                 urlcopy = strdup(url+7);
     115        if (strstr(url, "http://") == url) {
     116                urlcopy = strdup(url + 7);
     117        } else if (strstr(url, "https://") == url) {
     118                urlcopy = strdup(url + 8);
     119                *ssl = 1;
    117120        } else {
    118121                WARNING(("Weird url - unknown protocol: %s", url));
     
    123126        colon = strchr(urlcopy, ':');
    124127
    125         if(!colon || (slash && slash < colon)) {
    126                 *port = 80;
     128        if (!colon || (slash && slash < colon)) {
     129                if (*ssl)
     130                        *port = 443;
     131                else
     132                        *port = 80;
    127133        } else {
    128134                *colon = 0;
    129                 *port = atoi(colon+1);
    130         }
    131 
    132         if(!slash) {
     135                *port = atoi(colon + 1);
     136        }
     137
     138        if (!slash) {
    133139                strcpy(path, "/");
    134140        } else {
     
    138144
    139145        strcpy(host, urlcopy);
    140        
     146
    141147        FREE(urlcopy);
    142148
     
    146152static int isurlchar(unsigned char c)
    147153{
    148         return (isalnum(c) || '-' == c || '_' == c);
     154        return (isalnum(c));
    149155}
    150156
    151157char *yahoo_urlencode(const char *instr)
    152158{
    153         int ipos=0, bpos=0;
     159        int ipos = 0, bpos = 0;
    154160        char *str = NULL;
    155161        int len = strlen(instr);
    156162
    157         if(!(str = y_new(char, 3*len + 1) ))
    158                 return "";
    159 
    160         while(instr[ipos]) {
    161                 while(isurlchar(instr[ipos]))
     163        if (!(str = y_new(char, 3 *len + 1)))
     164                 return "";
     165
     166        while (instr[ipos]) {
     167                while (isurlchar(instr[ipos]))
    162168                        str[bpos++] = instr[ipos++];
    163                 if(!instr[ipos])
     169                if (!instr[ipos])
    164170                        break;
    165                
    166                 snprintf(&str[bpos], 4, "%%%.2x", instr[ipos]);
    167                 bpos+=3;
     171
     172                snprintf(&str[bpos], 4, "%%%02x", instr[ipos] & 0xff);
     173                bpos += 3;
    168174                ipos++;
    169175        }
    170         str[bpos]='\0';
     176        str[bpos] = '\0';
    171177
    172178        /* free extra alloc'ed mem. */
    173179        len = strlen(str);
    174         str = y_renew(char, str, len+1);
     180        str = y_renew(char, str, len + 1);
    175181
    176182        return (str);
     
    179185char *yahoo_urldecode(const char *instr)
    180186{
    181         int ipos=0, bpos=0;
     187        int ipos = 0, bpos = 0;
    182188        char *str = NULL;
    183         char entity[3]={0,0,0};
     189        char entity[3] = { 0, 0, 0 };
    184190        unsigned dec;
    185191        int len = strlen(instr);
    186192
    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++]=' ';
     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++] = ' ';
    194200                                ipos++;
    195201                        } else
    196202                                str[bpos++] = instr[ipos++];
    197                 if(!instr[ipos])
     203                if (!instr[ipos])
    198204                        break;
    199                
    200                 if(instr[ipos+1] && instr[ipos+2]) {
     205
     206                if (instr[ipos + 1] && instr[ipos + 2]) {
    201207                        ipos++;
    202                         entity[0]=instr[ipos++];
    203                         entity[1]=instr[ipos++];
     208                        entity[0] = instr[ipos++];
     209                        entity[1] = instr[ipos++];
    204210                        sscanf(entity, "%2x", &dec);
    205211                        str[bpos++] = (char)dec;
     
    208214                }
    209215        }
    210         str[bpos]='\0';
     216        str[bpos] = '\0';
    211217
    212218        /* free extra alloc'ed mem. */
    213219        len = strlen(str);
    214         str = y_renew(char, str, len+1);
     220        str = y_renew(char, str, len + 1);
    215221
    216222        return (str);
     
    219225char *yahoo_xmldecode(const char *instr)
    220226{
    221         int ipos=0, bpos=0, epos=0;
     227        int ipos = 0, bpos = 0, epos = 0;
    222228        char *str = NULL;
    223         char entity[4]={0,0,0,0};
    224         char *entitymap[5][2]={
    225                 {"amp;",  "&"},
     229        char entity[4] = { 0, 0, 0, 0 };
     230        char *entitymap[5][2] = {
     231                {"amp;", "&"},
    226232                {"quot;", "\""},
    227                 {"lt;",   "<"},
    228                 {"gt;",   "<"},
     233                {"lt;", "<"},
     234                {"gt;", "<"},
    229235                {"nbsp;", " "}
    230236        };
     
    232238        int len = strlen(instr);
    233239
    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++]=' ';
     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++] = ' ';
    241247                                ipos++;
    242248                        } else
    243249                                str[bpos++] = instr[ipos++];
    244                 if(!instr[ipos] || !instr[ipos+1])
     250                if (!instr[ipos] || !instr[ipos + 1])
    245251                        break;
    246252                ipos++;
    247253
    248                 if(instr[ipos] == '#') {
     254                if (instr[ipos] == '#') {
    249255                        ipos++;
    250                         epos=0;
    251                         while(instr[ipos] != ';')
    252                                 entity[epos++]=instr[ipos++];
     256                        epos = 0;
     257                        while (instr[ipos] != ';')
     258                                entity[epos++] = instr[ipos++];
    253259                        sscanf(entity, "%u", &dec);
    254260                        str[bpos++] = (char)dec;
     
    256262                } else {
    257263                        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];
     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];
    262268                                        ipos += strlen(entitymap[i][0]);
    263269                                        break;
     
    265271                }
    266272        }
    267         str[bpos]='\0';
     273        str[bpos] = '\0';
    268274
    269275        /* free extra alloc'ed mem. */
    270276        len = strlen(str);
    271         str = y_renew(char, str, len+1);
     277        str = y_renew(char, str, len + 1);
    272278
    273279        return (str);
    274280}
    275281
    276 typedef void (*http_connected)(int id, int fd, int error);
     282typedef void (*http_connected) (int id, void *fd, int error);
    277283
    278284struct callback_data {
     
    283289};
    284290
    285 static void connect_complete(int fd, int error, void *data)
     291static void connect_complete(void *fd, int error, void *data)
    286292{
    287293        struct callback_data *ccd = data;
    288         if(error == 0 && fd > 0)
    289                 write(fd, ccd->request, strlen(ccd->request));
    290         FREE(ccd->request);
     294        if (error == 0)
     295                YAHOO_CALLBACK(ext_yahoo_write) (fd, ccd->request,
     296                        strlen(ccd->request));
     297        free(ccd->request);
    291298        ccd->callback(ccd->id, fd, error, ccd->user_data);
    292299        FREE(ccd);
    293300}
    294301
    295 static 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);
     302static void yahoo_send_http_request(int id, char *host, int port, char *request,
     303        yahoo_get_fd_callback callback, void *data, int use_ssl)
     304{
     305        struct callback_data *ccd = y_new0(struct callback_data, 1);
    299306        ccd->callback = callback;
    300307        ccd->id = id;
    301308        ccd->request = strdup(request);
    302309        ccd->user_data = data;
    303        
    304         YAHOO_CALLBACK(ext_yahoo_connect_async)(id, host, port, connect_complete, ccd);
    305 }
    306 
    307 void yahoo_http_post(int id, const char *url, const char *cookies, long content_length,
    308                 yahoo_get_fd_callback callback, void *data)
     310
     311        YAHOO_CALLBACK(ext_yahoo_connect_async) (id, host, port,
     312                connect_complete, ccd, use_ssl);
     313}
     314
     315void yahoo_http_post(int id, const char *url, const char *cookies,
     316        long content_length, yahoo_get_fd_callback callback, void *data)
    309317{
    310318        char host[255];
     
    312320        char path[255];
    313321        char buff[1024];
    314        
    315         if(!url_to_host_port_path(url, host, &port, path))
     322        int ssl = 0;
     323
     324        if (!url_to_host_port_path(url, host, &port, path, &ssl))
    316325                return;
    317326
    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 
    332 void yahoo_http_get(int id, const char *url, const char *cookies,
    333                 yahoo_get_fd_callback callback, void *data)
     327        /* thanks to kopete dumpcap */
     328        snprintf(buff, sizeof(buff),
     329                "POST %s HTTP/1.1\r\n"
     330                "Cookie: %s\r\n"
     331                "User-Agent: Mozilla/5.0\r\n"
     332                "Host: %s\r\n"
     333                "Content-Length: %ld\r\n"
     334                "Cache-Control: no-cache\r\n"
     335                "\r\n", path, cookies, host, content_length);
     336
     337        yahoo_send_http_request(id, host, port, buff, callback, data, ssl);
     338}
     339
     340void yahoo_http_get(int id, const char *url, const char *cookies, int http11,
     341        int keepalive, yahoo_get_fd_callback callback, void *data)
    334342{
    335343        char host[255];
    336344        int port = 80;
    337345        char path[255];
    338         char buff[1024];
    339        
    340         if(!url_to_host_port_path(url, host, &port, path))
     346        char buff[2048];
     347        char cookiebuff[1024];
     348        int ssl = 0;
     349
     350        if (!url_to_host_port_path(url, host, &port, path, &ssl))
    341351                return;
    342352
    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 
    354 struct url_data {
    355         yahoo_get_url_handle_callback callback;
    356         void *user_data;
    357 };
    358 
    359 static 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);
     353        /* Allow cases when we don't need to send a cookie */
     354        if (cookies)
     355                snprintf(cookiebuff, sizeof(cookiebuff), "Cookie: %s\r\n",
     356                        cookies);
     357        else
     358                cookiebuff[0] = '\0';
     359
     360        snprintf(buff, sizeof(buff),
     361                "GET %s HTTP/1.%s\r\n"
     362                "%sHost: %s\r\n"
     363                "User-Agent: Mozilla/4.5 [en] (" PACKAGE "/" VERSION ")\r\n"
     364                "Accept: */*\r\n"
     365                "%s" "\r\n", path, http11?"1":"0", cookiebuff, host,
     366                keepalive? "Connection: Keep-Alive\r\n":"Connection: close\r\n");
     367
     368        yahoo_send_http_request(id, host, port, buff, callback, data, ssl);
     369}
     370
     371void yahoo_http_head(int id, const char *url, const char *cookies, int len,
     372        char *payload, yahoo_get_fd_callback callback, void *data)
     373{
     374        char host[255];
     375        int port = 80;
     376        char path[255];
     377        char buff[2048];
     378        char cookiebuff[1024];
     379        int ssl = 0;
     380
     381        if (!url_to_host_port_path(url, host, &port, path, &ssl))
    372382                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 
    421 void 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 
     383
     384        /* Allow cases when we don't need to send a cookie */
     385        if (cookies)
     386                snprintf(cookiebuff, sizeof(cookiebuff), "Cookie: %s\r\n",
     387                        cookies);
     388        else
     389                cookiebuff[0] = '\0';
     390
     391        snprintf(buff, sizeof(buff),
     392                "HEAD %s HTTP/1.0\r\n"
     393                "Accept: */*\r\n"
     394                "Host: %s:%d\r\n"
     395                "User-Agent: Mozilla/4.5 [en] (" PACKAGE "/" VERSION ")\r\n"
     396                "%s"
     397                "Content-Length: %d\r\n"
     398                "Cache-Control: no-cache\r\n"
     399                "\r\n%s", path, host, port, cookiebuff, len,
     400                payload?payload:"");
     401
     402        yahoo_send_http_request(id, host, port, buff, callback, data, ssl);
     403}
     404
Note: See TracChangeset for help on using the changeset viewer.