Annotation of embedaddon/miniupnpd/miniupnpc/src/miniwget.c, revision 1.1

1.1     ! misho       1: /* $Id: miniwget.c,v 1.82 2020/05/29 21:14:22 nanard Exp $ */
        !             2: /* Project : miniupnp
        !             3:  * Website : http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
        !             4:  * Author : Thomas Bernard
        !             5:  * Copyright (c) 2005-2020 Thomas Bernard
        !             6:  * This software is subject to the conditions detailed in the
        !             7:  * LICENCE file provided in this distribution. */
        !             8: 
        !             9: #include <stdio.h>
        !            10: #include <stdlib.h>
        !            11: #include <string.h>
        !            12: #include <ctype.h>
        !            13: #ifdef _WIN32
        !            14: #include <winsock2.h>
        !            15: #include <ws2tcpip.h>
        !            16: #include <io.h>
        !            17: #define MAXHOSTNAMELEN 64
        !            18: #include "win32_snprintf.h"
        !            19: #define socklen_t int
        !            20: #ifndef strncasecmp
        !            21: #if defined(_MSC_VER) && (_MSC_VER >= 1400)
        !            22: #define strncasecmp _memicmp
        !            23: #else /* defined(_MSC_VER) && (_MSC_VER >= 1400) */
        !            24: #define strncasecmp memicmp
        !            25: #endif /* defined(_MSC_VER) && (_MSC_VER >= 1400) */
        !            26: #endif /* #ifndef strncasecmp */
        !            27: #else /* #ifdef _WIN32 */
        !            28: #include <unistd.h>
        !            29: #include <sys/param.h>
        !            30: #if defined(__amigaos__) && !defined(__amigaos4__)
        !            31: #define socklen_t int
        !            32: #else /* #if defined(__amigaos__) && !defined(__amigaos4__) */
        !            33: #include <sys/select.h>
        !            34: #endif /* #else defined(__amigaos__) && !defined(__amigaos4__) */
        !            35: #include <sys/socket.h>
        !            36: #include <netinet/in.h>
        !            37: #include <arpa/inet.h>
        !            38: #include <net/if.h>
        !            39: #include <netdb.h>
        !            40: #define closesocket close
        !            41: #include <strings.h>
        !            42: #endif /* #else _WIN32 */
        !            43: #ifdef __GNU__
        !            44: #define MAXHOSTNAMELEN 64
        !            45: #endif /* __GNU__ */
        !            46: 
        !            47: #ifndef MIN
        !            48: #define MIN(x,y) (((x)<(y))?(x):(y))
        !            49: #endif /* MIN */
        !            50: 
        !            51: 
        !            52: #include "miniupnpcstrings.h"
        !            53: #include "miniwget.h"
        !            54: #include "connecthostport.h"
        !            55: #include "receivedata.h"
        !            56: 
        !            57: #ifndef MAXHOSTNAMELEN
        !            58: #define MAXHOSTNAMELEN 64
        !            59: #endif
        !            60: 
        !            61: /*
        !            62:  * Read a HTTP response from a socket.
        !            63:  * Process Content-Length and Transfer-encoding headers.
        !            64:  * return a pointer to the content buffer, which length is saved
        !            65:  * to the length parameter.
        !            66:  */
        !            67: void *
        !            68: getHTTPResponse(SOCKET s, int * size, int * status_code)
        !            69: {
        !            70:        char buf[2048];
        !            71:        int n;
        !            72:        int endofheaders = 0;
        !            73:        int chunked = 0;
        !            74:        int content_length = -1;
        !            75:        unsigned int chunksize = 0;
        !            76:        unsigned int bytestocopy = 0;
        !            77:        /* buffers : */
        !            78:        char * header_buf;
        !            79:        unsigned int header_buf_len = 2048;
        !            80:        unsigned int header_buf_used = 0;
        !            81:        char * content_buf;
        !            82:        unsigned int content_buf_len = 2048;
        !            83:        unsigned int content_buf_used = 0;
        !            84:        char chunksize_buf[32];
        !            85:        unsigned int chunksize_buf_index;
        !            86: #ifdef DEBUG
        !            87:        char * reason_phrase = NULL;
        !            88:        int reason_phrase_len = 0;
        !            89: #endif
        !            90: 
        !            91:        if(status_code) *status_code = -1;
        !            92:        header_buf = malloc(header_buf_len);
        !            93:        if(header_buf == NULL)
        !            94:        {
        !            95: #ifdef DEBUG
        !            96:                fprintf(stderr, "%s: Memory allocation error\n", "getHTTPResponse");
        !            97: #endif /* DEBUG */
        !            98:                *size = -1;
        !            99:                return NULL;
        !           100:        }
        !           101:        content_buf = malloc(content_buf_len);
        !           102:        if(content_buf == NULL)
        !           103:        {
        !           104:                free(header_buf);
        !           105: #ifdef DEBUG
        !           106:                fprintf(stderr, "%s: Memory allocation error\n", "getHTTPResponse");
        !           107: #endif /* DEBUG */
        !           108:                *size = -1;
        !           109:                return NULL;
        !           110:        }
        !           111:        chunksize_buf[0] = '\0';
        !           112:        chunksize_buf_index = 0;
        !           113: 
        !           114:        while((n = receivedata(s, buf, sizeof(buf), 5000, NULL)) > 0)
        !           115:        {
        !           116:                if(endofheaders == 0)
        !           117:                {
        !           118:                        int i;
        !           119:                        int linestart=0;
        !           120:                        int colon=0;
        !           121:                        int valuestart=0;
        !           122:                        if(header_buf_used + n > header_buf_len) {
        !           123:                                char * tmp = realloc(header_buf, header_buf_used + n);
        !           124:                                if(tmp == NULL) {
        !           125:                                        /* memory allocation error */
        !           126:                                        free(header_buf);
        !           127:                                        free(content_buf);
        !           128:                                        *size = -1;
        !           129:                                        return NULL;
        !           130:                                }
        !           131:                                header_buf = tmp;
        !           132:                                header_buf_len = header_buf_used + n;
        !           133:                        }
        !           134:                        memcpy(header_buf + header_buf_used, buf, n);
        !           135:                        header_buf_used += n;
        !           136:                        /* search for CR LF CR LF (end of headers)
        !           137:                         * recognize also LF LF */
        !           138:                        i = 0;
        !           139:                        while(i < ((int)header_buf_used-1) && (endofheaders == 0)) {
        !           140:                                if(header_buf[i] == '\r') {
        !           141:                                        i++;
        !           142:                                        if(header_buf[i] == '\n') {
        !           143:                                                i++;
        !           144:                                                if(i < (int)header_buf_used && header_buf[i] == '\r') {
        !           145:                                                        i++;
        !           146:                                                        if(i < (int)header_buf_used && header_buf[i] == '\n') {
        !           147:                                                                endofheaders = i+1;
        !           148:                                                        }
        !           149:                                                }
        !           150:                                        }
        !           151:                                } else if(header_buf[i] == '\n') {
        !           152:                                        i++;
        !           153:                                        if(header_buf[i] == '\n') {
        !           154:                                                endofheaders = i+1;
        !           155:                                        }
        !           156:                                }
        !           157:                                i++;
        !           158:                        }
        !           159:                        if(endofheaders == 0)
        !           160:                                continue;
        !           161:                        /* parse header lines */
        !           162:                        for(i = 0; i < endofheaders - 1; i++) {
        !           163:                                if(linestart > 0 && colon <= linestart && header_buf[i]==':')
        !           164:                                {
        !           165:                                        colon = i;
        !           166:                                        while(i < (endofheaders-1)
        !           167:                                              && (header_buf[i+1] == ' ' || header_buf[i+1] == '\t'))
        !           168:                                                i++;
        !           169:                                        valuestart = i + 1;
        !           170:                                }
        !           171:                                /* detecting end of line */
        !           172:                                else if(header_buf[i]=='\r' || header_buf[i]=='\n')
        !           173:                                {
        !           174:                                        if(linestart == 0 && status_code)
        !           175:                                        {
        !           176:                                                /* Status line
        !           177:                                                 * HTTP-Version SP Status-Code SP Reason-Phrase CRLF */
        !           178:                                                int sp;
        !           179:                                                for(sp = 0; sp < i - 1; sp++)
        !           180:                                                        if(header_buf[sp] == ' ')
        !           181:                                                        {
        !           182:                                                                if(*status_code < 0)
        !           183:                                                                {
        !           184:                                                                        if (header_buf[sp+1] >= '1' && header_buf[sp+1] <= '9')
        !           185:                                                                                *status_code = atoi(header_buf + sp + 1);
        !           186:                                                                }
        !           187:                                                                else
        !           188:                                                                {
        !           189: #ifdef DEBUG
        !           190:                                                                        reason_phrase = header_buf + sp + 1;
        !           191:                                                                        reason_phrase_len = i - sp - 1;
        !           192: #endif
        !           193:                                                                        break;
        !           194:                                                                }
        !           195:                                                        }
        !           196: #ifdef DEBUG
        !           197:                                                printf("HTTP status code = %d, Reason phrase = %.*s\n",
        !           198:                                                       *status_code, reason_phrase_len, reason_phrase);
        !           199: #endif
        !           200:                                        }
        !           201:                                        else if(colon > linestart && valuestart > colon)
        !           202:                                        {
        !           203: #ifdef DEBUG
        !           204:                                                printf("header='%.*s', value='%.*s'\n",
        !           205:                                                       colon-linestart, header_buf+linestart,
        !           206:                                                       i-valuestart, header_buf+valuestart);
        !           207: #endif
        !           208:                                                if(0==strncasecmp(header_buf+linestart, "content-length", colon-linestart))
        !           209:                                                {
        !           210:                                                        content_length = atoi(header_buf+valuestart);
        !           211: #ifdef DEBUG
        !           212:                                                        printf("Content-Length: %d\n", content_length);
        !           213: #endif
        !           214:                                                }
        !           215:                                                else if(0==strncasecmp(header_buf+linestart, "transfer-encoding", colon-linestart)
        !           216:                                                   && 0==strncasecmp(header_buf+valuestart, "chunked", 7))
        !           217:                                                {
        !           218: #ifdef DEBUG
        !           219:                                                        printf("chunked transfer-encoding!\n");
        !           220: #endif
        !           221:                                                        chunked = 1;
        !           222:                                                }
        !           223:                                        }
        !           224:                                        while((i < (int)header_buf_used) && (header_buf[i]=='\r' || header_buf[i] == '\n'))
        !           225:                                                i++;
        !           226:                                        linestart = i;
        !           227:                                        colon = linestart;
        !           228:                                        valuestart = 0;
        !           229:                                }
        !           230:                        }
        !           231:                        /* copy the remaining of the received data back to buf */
        !           232:                        n = header_buf_used - endofheaders;
        !           233:                        memcpy(buf, header_buf + endofheaders, n);
        !           234:                        /* if(headers) */
        !           235:                }
        !           236:                /* if we get there, endofheaders != 0.
        !           237:                 * In the other case, there was a continue above */
        !           238:                /* content */
        !           239:                if(chunked)
        !           240:                {
        !           241:                        int i = 0;
        !           242:                        while(i < n)
        !           243:                        {
        !           244:                                if(chunksize == 0)
        !           245:                                {
        !           246:                                        /* reading chunk size */
        !           247:                                        if(chunksize_buf_index == 0) {
        !           248:                                                /* skipping any leading CR LF */
        !           249:                                                if(buf[i] == '\r') i++;
        !           250:                                                if(i<n && buf[i] == '\n') i++;
        !           251:                                        }
        !           252:                                        while(i<n && isxdigit(buf[i])
        !           253:                                             && chunksize_buf_index < (sizeof(chunksize_buf)-1))
        !           254:                                        {
        !           255:                                                chunksize_buf[chunksize_buf_index++] = buf[i];
        !           256:                                                chunksize_buf[chunksize_buf_index] = '\0';
        !           257:                                                i++;
        !           258:                                        }
        !           259:                                        while(i<n && buf[i] != '\r' && buf[i] != '\n')
        !           260:                                                i++; /* discarding chunk-extension */
        !           261:                                        if(i<n && buf[i] == '\r') i++;
        !           262:                                        if(i<n && buf[i] == '\n') {
        !           263:                                                unsigned int j;
        !           264:                                                for(j = 0; j < chunksize_buf_index; j++) {
        !           265:                                                if(chunksize_buf[j] >= '0'
        !           266:                                                   && chunksize_buf[j] <= '9')
        !           267:                                                        chunksize = (chunksize << 4) + (chunksize_buf[j] - '0');
        !           268:                                                else
        !           269:                                                        chunksize = (chunksize << 4) + ((chunksize_buf[j] | 32) - 'a' + 10);
        !           270:                                                }
        !           271:                                                chunksize_buf[0] = '\0';
        !           272:                                                chunksize_buf_index = 0;
        !           273:                                                i++;
        !           274:                                        } else {
        !           275:                                                /* not finished to get chunksize */
        !           276:                                                continue;
        !           277:                                        }
        !           278: #ifdef DEBUG
        !           279:                                        printf("chunksize = %u (%x)\n", chunksize, chunksize);
        !           280: #endif
        !           281:                                        if(chunksize == 0)
        !           282:                                        {
        !           283: #ifdef DEBUG
        !           284:                                                printf("end of HTTP content - %d %d\n", i, n);
        !           285:                                                /*printf("'%.*s'\n", n-i, buf+i);*/
        !           286: #endif
        !           287:                                                goto end_of_stream;
        !           288:                                        }
        !           289:                                }
        !           290:                                /* it is guaranteed that (n >= i) */
        !           291:                                bytestocopy = (chunksize < (unsigned int)(n - i))?chunksize:(unsigned int)(n - i);
        !           292:                                if((content_buf_used + bytestocopy) > content_buf_len)
        !           293:                                {
        !           294:                                        char * tmp;
        !           295:                                        if((content_length >= 0) && ((unsigned int)content_length >= (content_buf_used + bytestocopy))) {
        !           296:                                                content_buf_len = content_length;
        !           297:                                        } else {
        !           298:                                                content_buf_len = content_buf_used + bytestocopy;
        !           299:                                        }
        !           300:                                        tmp = realloc(content_buf, content_buf_len);
        !           301:                                        if(tmp == NULL) {
        !           302:                                                /* memory allocation error */
        !           303:                                                free(content_buf);
        !           304:                                                free(header_buf);
        !           305:                                                *size = -1;
        !           306:                                                return NULL;
        !           307:                                        }
        !           308:                                        content_buf = tmp;
        !           309:                                }
        !           310:                                memcpy(content_buf + content_buf_used, buf + i, bytestocopy);
        !           311:                                content_buf_used += bytestocopy;
        !           312:                                i += bytestocopy;
        !           313:                                chunksize -= bytestocopy;
        !           314:                        }
        !           315:                }
        !           316:                else
        !           317:                {
        !           318:                        /* not chunked */
        !           319:                        if(content_length > 0
        !           320:                           && (content_buf_used + n) > (unsigned int)content_length) {
        !           321:                                /* skipping additional bytes */
        !           322:                                n = content_length - content_buf_used;
        !           323:                        }
        !           324:                        if(content_buf_used + n > content_buf_len)
        !           325:                        {
        !           326:                                char * tmp;
        !           327:                                if(content_length >= 0
        !           328:                                   && (unsigned int)content_length >= (content_buf_used + n)) {
        !           329:                                        content_buf_len = content_length;
        !           330:                                } else {
        !           331:                                        content_buf_len = content_buf_used + n;
        !           332:                                }
        !           333:                                tmp = realloc(content_buf, content_buf_len);
        !           334:                                if(tmp == NULL) {
        !           335:                                        /* memory allocation error */
        !           336:                                        free(content_buf);
        !           337:                                        free(header_buf);
        !           338:                                        *size = -1;
        !           339:                                        return NULL;
        !           340:                                }
        !           341:                                content_buf = tmp;
        !           342:                        }
        !           343:                        memcpy(content_buf + content_buf_used, buf, n);
        !           344:                        content_buf_used += n;
        !           345:                }
        !           346:                /* use the Content-Length header value if available */
        !           347:                if(content_length > 0 && content_buf_used >= (unsigned int)content_length)
        !           348:                {
        !           349: #ifdef DEBUG
        !           350:                        printf("End of HTTP content\n");
        !           351: #endif
        !           352:                        break;
        !           353:                }
        !           354:        }
        !           355: end_of_stream:
        !           356:        free(header_buf);
        !           357:        *size = content_buf_used;
        !           358:        if(content_buf_used == 0)
        !           359:        {
        !           360:                free(content_buf);
        !           361:                content_buf = NULL;
        !           362:        }
        !           363:        return content_buf;
        !           364: }
        !           365: 
        !           366: /* miniwget3() :
        !           367:  * do all the work.
        !           368:  * Return NULL if something failed. */
        !           369: static void *
        !           370: miniwget3(const char * host,
        !           371:           unsigned short port, const char * path,
        !           372:           int * size, char * addr_str, int addr_str_len,
        !           373:           const char * httpversion, unsigned int scope_id,
        !           374:           int * status_code)
        !           375: {
        !           376:        char buf[2048];
        !           377:        SOCKET s;
        !           378:        int n;
        !           379:        int len;
        !           380:        int sent;
        !           381:        void * content;
        !           382: 
        !           383:        *size = 0;
        !           384:        s = connecthostport(host, port, scope_id);
        !           385:        if(ISINVALID(s))
        !           386:                return NULL;
        !           387: 
        !           388:        /* get address for caller ! */
        !           389:        if(addr_str)
        !           390:        {
        !           391:                struct sockaddr_storage saddr;
        !           392:                socklen_t saddrlen;
        !           393: 
        !           394:                saddrlen = sizeof(saddr);
        !           395:                if(getsockname(s, (struct sockaddr *)&saddr, &saddrlen) < 0)
        !           396:                {
        !           397:                        perror("getsockname");
        !           398:                }
        !           399:                else
        !           400:                {
        !           401: #if defined(__amigaos__) && !defined(__amigaos4__)
        !           402:        /* using INT WINAPI WSAAddressToStringA(LPSOCKADDR, DWORD, LPWSAPROTOCOL_INFOA, LPSTR, LPDWORD);
        !           403:      * But his function make a string with the port :  nn.nn.nn.nn:port */
        !           404: /*             if(WSAAddressToStringA((SOCKADDR *)&saddr, sizeof(saddr),
        !           405:                             NULL, addr_str, (DWORD *)&addr_str_len))
        !           406:                {
        !           407:                    printf("WSAAddressToStringA() failed : %d\n", WSAGetLastError());
        !           408:                }*/
        !           409:                        /* the following code is only compatible with ip v4 addresses */
        !           410:                        strncpy(addr_str, inet_ntoa(((struct sockaddr_in *)&saddr)->sin_addr), addr_str_len);
        !           411: #else
        !           412: #if 0
        !           413:                        if(saddr.sa_family == AF_INET6) {
        !           414:                                inet_ntop(AF_INET6,
        !           415:                                          &(((struct sockaddr_in6 *)&saddr)->sin6_addr),
        !           416:                                          addr_str, addr_str_len);
        !           417:                        } else {
        !           418:                                inet_ntop(AF_INET,
        !           419:                                          &(((struct sockaddr_in *)&saddr)->sin_addr),
        !           420:                                          addr_str, addr_str_len);
        !           421:                        }
        !           422: #endif
        !           423:                        /* getnameinfo return ip v6 address with the scope identifier
        !           424:                         * such as : 2a01:e35:8b2b:7330::%4281128194 */
        !           425:                        n = getnameinfo((const struct sockaddr *)&saddr, saddrlen,
        !           426:                                        addr_str, addr_str_len,
        !           427:                                        NULL, 0,
        !           428:                                        NI_NUMERICHOST | NI_NUMERICSERV);
        !           429:                        if(n != 0) {
        !           430: #ifdef _WIN32
        !           431:                                fprintf(stderr, "getnameinfo() failed : %d\n", n);
        !           432: #else
        !           433:                                fprintf(stderr, "getnameinfo() failed : %s\n", gai_strerror(n));
        !           434: #endif
        !           435:                        }
        !           436: #endif
        !           437:                }
        !           438: #ifdef DEBUG
        !           439:                printf("address miniwget : %s\n", addr_str);
        !           440: #endif
        !           441:        }
        !           442: 
        !           443:        len = snprintf(buf, sizeof(buf),
        !           444:                  "GET %s HTTP/%s\r\n"
        !           445:                             "Host: %s:%d\r\n"
        !           446:                                 "Connection: Close\r\n"
        !           447:                                 "User-Agent: " OS_STRING ", " UPNP_VERSION_STRING ", MiniUPnPc/" MINIUPNPC_VERSION_STRING "\r\n"
        !           448: 
        !           449:                                 "\r\n",
        !           450:                           path, httpversion, host, port);
        !           451:        if ((unsigned int)len >= sizeof(buf))
        !           452:        {
        !           453:                closesocket(s);
        !           454:                return NULL;
        !           455:        }
        !           456:        sent = 0;
        !           457:        /* sending the HTTP request */
        !           458:        while(sent < len)
        !           459:        {
        !           460:                n = send(s, buf+sent, len-sent, 0);
        !           461:                if(n < 0)
        !           462:                {
        !           463:                        perror("send");
        !           464:                        closesocket(s);
        !           465:                        return NULL;
        !           466:                }
        !           467:                else
        !           468:                {
        !           469:                        sent += n;
        !           470:                }
        !           471:        }
        !           472:        content = getHTTPResponse(s, size, status_code);
        !           473:        closesocket(s);
        !           474:        return content;
        !           475: }
        !           476: 
        !           477: /* miniwget2() :
        !           478:  * Call miniwget3(); retry with HTTP/1.1 if 1.0 fails. */
        !           479: static void *
        !           480: miniwget2(const char * host,
        !           481:           unsigned short port, const char * path,
        !           482:           int * size, char * addr_str, int addr_str_len,
        !           483:           unsigned int scope_id, int * status_code)
        !           484: {
        !           485:        char * respbuffer;
        !           486: 
        !           487: #if 1
        !           488:        respbuffer = miniwget3(host, port, path, size,
        !           489:                               addr_str, addr_str_len, "1.1",
        !           490:                               scope_id, status_code);
        !           491: #else
        !           492:        respbuffer = miniwget3(host, port, path, size,
        !           493:                               addr_str, addr_str_len, "1.0",
        !           494:                               scope_id, status_code);
        !           495:        if (*size == 0)
        !           496:        {
        !           497: #ifdef DEBUG
        !           498:                printf("Retrying with HTTP/1.1\n");
        !           499: #endif
        !           500:                free(respbuffer);
        !           501:                respbuffer = miniwget3(host, port, path, size,
        !           502:                                       addr_str, addr_str_len, "1.1",
        !           503:                                       scope_id, status_code);
        !           504:        }
        !           505: #endif
        !           506:        return respbuffer;
        !           507: }
        !           508: 
        !           509: 
        !           510: 
        !           511: 
        !           512: /* parseURL()
        !           513:  * arguments :
        !           514:  *   url :             source string not modified
        !           515:  *   hostname :        hostname destination string (size of MAXHOSTNAMELEN+1)
        !           516:  *   port :            port (destination)
        !           517:  *   path :            pointer to the path part of the URL
        !           518:  *
        !           519:  * Return values :
        !           520:  *    0 - Failure
        !           521:  *    1 - Success         */
        !           522: int
        !           523: parseURL(const char * url,
        !           524:          char * hostname, unsigned short * port,
        !           525:          char * * path, unsigned int * scope_id)
        !           526: {
        !           527:        char * p1, *p2, *p3;
        !           528:        if(!url)
        !           529:                return 0;
        !           530:        p1 = strstr(url, "://");
        !           531:        if(!p1)
        !           532:                return 0;
        !           533:        p1 += 3;
        !           534:        if(  (url[0]!='h') || (url[1]!='t')
        !           535:           ||(url[2]!='t') || (url[3]!='p'))
        !           536:                return 0;
        !           537:        memset(hostname, 0, MAXHOSTNAMELEN + 1);
        !           538:        if(*p1 == '[')
        !           539:        {
        !           540:                /* IP v6 : http://[2a00:1450:8002::6a]/path/abc */
        !           541:                char * scope;
        !           542:                scope = strchr(p1, '%');
        !           543:                p2 = strchr(p1, ']');
        !           544:                if(p2 && scope && scope < p2 && scope_id) {
        !           545:                        /* parse scope */
        !           546: #ifdef IF_NAMESIZE
        !           547:                        char tmp[IF_NAMESIZE];
        !           548:                        int l;
        !           549:                        scope++;
        !           550:                        /* "%25" is just '%' in URL encoding */
        !           551:                        if(scope[0] == '2' && scope[1] == '5')
        !           552:                                scope += 2;     /* skip "25" */
        !           553:                        l = p2 - scope;
        !           554:                        if(l >= IF_NAMESIZE)
        !           555:                                l = IF_NAMESIZE - 1;
        !           556:                        memcpy(tmp, scope, l);
        !           557:                        tmp[l] = '\0';
        !           558:                        *scope_id = if_nametoindex(tmp);
        !           559:                        if(*scope_id == 0) {
        !           560:                                *scope_id = (unsigned int)strtoul(tmp, NULL, 10);
        !           561:                        }
        !           562: #else
        !           563:                        /* under windows, scope is numerical */
        !           564:                        char tmp[8];
        !           565:                        size_t l;
        !           566:                        scope++;
        !           567:                        /* "%25" is just '%' in URL encoding */
        !           568:                        if(scope[0] == '2' && scope[1] == '5')
        !           569:                                scope += 2;     /* skip "25" */
        !           570:                        l = p2 - scope;
        !           571:                        if(l >= sizeof(tmp))
        !           572:                                l = sizeof(tmp) - 1;
        !           573:                        memcpy(tmp, scope, l);
        !           574:                        tmp[l] = '\0';
        !           575:                        *scope_id = (unsigned int)strtoul(tmp, NULL, 10);
        !           576: #endif
        !           577:                }
        !           578:                p3 = strchr(p1, '/');
        !           579:                if(p2 && p3)
        !           580:                {
        !           581:                        p2++;
        !           582:                        strncpy(hostname, p1, MIN(MAXHOSTNAMELEN, (int)(p2-p1)));
        !           583:                        if(*p2 == ':')
        !           584:                        {
        !           585:                                *port = 0;
        !           586:                                p2++;
        !           587:                                while( (*p2 >= '0') && (*p2 <= '9'))
        !           588:                                {
        !           589:                                        *port *= 10;
        !           590:                                        *port += (unsigned short)(*p2 - '0');
        !           591:                                        p2++;
        !           592:                                }
        !           593:                        }
        !           594:                        else
        !           595:                        {
        !           596:                                *port = 80;
        !           597:                        }
        !           598:                        *path = p3;
        !           599:                        return 1;
        !           600:                }
        !           601:        }
        !           602:        p2 = strchr(p1, ':');
        !           603:        p3 = strchr(p1, '/');
        !           604:        if(!p3)
        !           605:                return 0;
        !           606:        if(!p2 || (p2>p3))
        !           607:        {
        !           608:                strncpy(hostname, p1, MIN(MAXHOSTNAMELEN, (int)(p3-p1)));
        !           609:                *port = 80;
        !           610:        }
        !           611:        else
        !           612:        {
        !           613:                strncpy(hostname, p1, MIN(MAXHOSTNAMELEN, (int)(p2-p1)));
        !           614:                *port = 0;
        !           615:                p2++;
        !           616:                while( (*p2 >= '0') && (*p2 <= '9'))
        !           617:                {
        !           618:                        *port *= 10;
        !           619:                        *port += (unsigned short)(*p2 - '0');
        !           620:                        p2++;
        !           621:                }
        !           622:        }
        !           623:        *path = p3;
        !           624:        return 1;
        !           625: }
        !           626: 
        !           627: void *
        !           628: miniwget(const char * url, int * size,
        !           629:          unsigned int scope_id, int * status_code)
        !           630: {
        !           631:        unsigned short port;
        !           632:        char * path;
        !           633:        /* protocol://host:port/chemin */
        !           634:        char hostname[MAXHOSTNAMELEN+1];
        !           635:        *size = 0;
        !           636:        if(!parseURL(url, hostname, &port, &path, &scope_id))
        !           637:                return NULL;
        !           638: #ifdef DEBUG
        !           639:        printf("parsed url : hostname='%s' port=%hu path='%s' scope_id=%u\n",
        !           640:               hostname, port, path, scope_id);
        !           641: #endif
        !           642:        return miniwget2(hostname, port, path, size, 0, 0, scope_id, status_code);
        !           643: }
        !           644: 
        !           645: void *
        !           646: miniwget_getaddr(const char * url, int * size,
        !           647:                  char * addr, int addrlen, unsigned int scope_id,
        !           648:                  int * status_code)
        !           649: {
        !           650:        unsigned short port;
        !           651:        char * path;
        !           652:        /* protocol://host:port/path */
        !           653:        char hostname[MAXHOSTNAMELEN+1];
        !           654:        *size = 0;
        !           655:        if(addr)
        !           656:                addr[0] = '\0';
        !           657:        if(!parseURL(url, hostname, &port, &path, &scope_id))
        !           658:                return NULL;
        !           659: #ifdef DEBUG
        !           660:        printf("parsed url : hostname='%s' port=%hu path='%s' scope_id=%u\n",
        !           661:               hostname, port, path, scope_id);
        !           662: #endif
        !           663:        return miniwget2(hostname, port, path, size, addr, addrlen, scope_id, status_code);
        !           664: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>