コード例 #1
0
BinHTTPURLInputStream::BinHTTPURLInputStream(const XMLURL& urlSource, const XMLNetHTTPInfo* httpInfo /*=0*/)
      : fSocketHandle(0)
      , fBytesProcessed(0)
{
    if(!fInitialized)
    {
        if (!fInitMutex)
        {
            XMLMutex* tmpMutex = new XMLMutex(XMLPlatformUtils::fgMemoryManager);
            if (XMLPlatformUtils::compareAndSwap((void**)&fInitMutex, tmpMutex, 0))
            {
                // Someone beat us to it, so let's clean up ours
                delete tmpMutex;
            }
         }
         XMLMutexLock lock(fInitMutex);
         if (!fInitialized)
         {
             Initialize(urlSource.getMemoryManager());
         }
    }

    fMemoryManager = urlSource.getMemoryManager();
    //
    // Pull all of the parts of the URL out of th urlSource object, and transcode them
    //   and transcode them back to ASCII.
    //
    const XMLCh*        hostName = urlSource.getHost();
    char*               hostNameAsCharStar = XMLString::transcode(hostName, urlSource.getMemoryManager());
    ArrayJanitor<char>  janBuf1(hostNameAsCharStar, urlSource.getMemoryManager());

    const XMLCh*        path = urlSource.getPath();
    char*               pathAsCharStar = XMLString::transcode(path, urlSource.getMemoryManager());
    ArrayJanitor<char>  janBuf2(pathAsCharStar, urlSource.getMemoryManager());

    const XMLCh*        fragment = urlSource.getFragment();
    char*               fragmentAsCharStar = 0;
    if (fragment)
        fragmentAsCharStar = XMLString::transcode(fragment, urlSource.getMemoryManager());
    ArrayJanitor<char>  janBuf3(fragmentAsCharStar, urlSource.getMemoryManager());

    const XMLCh*        query = urlSource.getQuery();
    char*               queryAsCharStar = 0;
    if (query)
        queryAsCharStar = XMLString::transcode(query, urlSource.getMemoryManager());
    ArrayJanitor<char>  janBuf4(queryAsCharStar, urlSource.getMemoryManager());		

    unsigned short      portNumber = (unsigned short) urlSource.getPortNum();

    //
    // Set up a socket.
    //
    struct hostent*     hostEntPtr = 0;
    struct sockaddr_in  sa;


    if ((hostEntPtr = gethostbyname(hostNameAsCharStar)) == NULL)
    {
        unsigned long  numAddress = inet_addr(hostNameAsCharStar);
        if (numAddress == INADDR_NONE)
        {
            // Call WSAGetLastError() to get the error number.
            ThrowXMLwithMemMgr1(NetAccessorException,
                     XMLExcepts::NetAcc_TargetResolution, hostName, fMemoryManager);
        }
        if ((hostEntPtr =
                gethostbyaddr((const char *) &numAddress,
                              sizeof(unsigned long), AF_INET)) == NULL)
        {
            // Call WSAGetLastError() to get the error number.
            ThrowXMLwithMemMgr1(NetAccessorException,
                     XMLExcepts::NetAcc_TargetResolution, hostName, fMemoryManager);
        }
    }

    memcpy((void *) &sa.sin_addr,
           (const void *) hostEntPtr->h_addr, hostEntPtr->h_length);
    sa.sin_family = hostEntPtr->h_addrtype;
    sa.sin_port = htons(portNumber);

    SOCKET s = socket(hostEntPtr->h_addrtype, SOCK_STREAM, 0);
    if (s == INVALID_SOCKET)
    {
        // Call WSAGetLastError() to get the error number.
        ThrowXMLwithMemMgr1(NetAccessorException,
                 XMLExcepts::NetAcc_CreateSocket, urlSource.getURLText(), fMemoryManager);
    }
    SocketJanitor janSock(&s);

    if (connect(s, (struct sockaddr *) &sa, sizeof(sa)) == SOCKET_ERROR)
    {
        // Call WSAGetLastError() to get the error number.
        ThrowXMLwithMemMgr1(NetAccessorException,
                 XMLExcepts::NetAcc_ConnSocket, urlSource.getURLText(), fMemoryManager);
    }


    // Set a flag so we know that the headers have not been read yet.
    bool fHeaderRead = false;

    // The port is open and ready to go.
    // Build up the http GET command to send to the server.
    // To do:  We should really support http 1.1.  This implementation
    //         is weak.

    memset(fBuffer, 0, sizeof(fBuffer));

    if(httpInfo==0)
        strcpy(fBuffer, "GET ");
    else {
        switch(httpInfo->fHTTPMethod) {
        case XMLNetHTTPInfo::GET:   strcpy(fBuffer, "GET "); break;
        case XMLNetHTTPInfo::PUT:   strcpy(fBuffer, "PUT "); break;
        case XMLNetHTTPInfo::POST:  strcpy(fBuffer, "POST "); break;
        }
    }
    strcat(fBuffer, pathAsCharStar);

    if (queryAsCharStar != 0)
    {
        // Tack on a ? before the fragment
        strcat(fBuffer,"?");
        strcat(fBuffer, queryAsCharStar);
    }

    if (fragmentAsCharStar != 0)
    {
        strcat(fBuffer, fragmentAsCharStar);
    }
    strcat(fBuffer, " HTTP/1.0\r\n");


    strcat(fBuffer, "Host: ");
    strcat(fBuffer, hostNameAsCharStar);
    if (portNumber != 80)
    {
        strcat(fBuffer, ":");
        int i = strlen(fBuffer);
        _itoa(portNumber, fBuffer+i, 10);
    }
    strcat(fBuffer, "\r\n");

    const XMLCh* username = urlSource.getUser();
    const XMLCh* password = urlSource.getPassword();
    if (username && password)
    {
        XMLBuffer userPass(256, fMemoryManager);
        userPass.append(username);
        userPass.append(chColon);
        userPass.append(password);
        char* userPassAsCharStar = XMLString::transcode(userPass.getRawBuffer(), fMemoryManager);
        ArrayJanitor<char>  janBuf(userPassAsCharStar, fMemoryManager);

        unsigned int len;
        XMLByte* encodedData = Base64::encode((XMLByte *)userPassAsCharStar, strlen(userPassAsCharStar), &len, fMemoryManager);
        ArrayJanitor<XMLByte>  janBuf2(encodedData, fMemoryManager);
 
        if (encodedData)
        {
            // HTTP doesn't want the 0x0A separating the data in chunks of 76 chars per line
            XMLByte* authData = (XMLByte*)fMemoryManager->allocate((len+1)*sizeof(XMLByte));
            ArrayJanitor<XMLByte>  janBuf(authData, fMemoryManager);
            XMLByte* cursor=authData;
            for(unsigned int i=0;i<len;i++)
                if(encodedData[i]!=chLF)
                    *cursor++=encodedData[i];
            *cursor++=0;
            strcat(fBuffer, "Authorization: Basic ");
            strcat(fBuffer, (char*)authData);
            strcat(fBuffer, "\r\n");
        }
    }

    if(httpInfo!=0 && httpInfo->fHeaders!=0)
        strncat(fBuffer,httpInfo->fHeaders,httpInfo->fHeadersLen);

    strcat(fBuffer, "\r\n");

    // Send the http request
    int lent = strlen(fBuffer);
    int  aLent = 0;
    if ((aLent = send(s, fBuffer, lent, 0)) != lent)
    {
        // Call WSAGetLastError() to get the error number.
        ThrowXMLwithMemMgr1(NetAccessorException,
                 XMLExcepts::NetAcc_WriteSocket, urlSource.getURLText(), fMemoryManager);
    }

    if(httpInfo!=0 && httpInfo->fPayload!=0) {
        int  aLent = 0;
        if ((aLent = send(s, httpInfo->fPayload, httpInfo->fPayloadLen, 0)) != httpInfo->fPayloadLen)
        {
            // Call WSAGetLastError() to get the error number.
            ThrowXMLwithMemMgr1(NetAccessorException,
                     XMLExcepts::NetAcc_WriteSocket, urlSource.getURLText(), fMemoryManager);
        }
    }

    //
    // get the response, check the http header for errors from the server.
    //
    memset(fBuffer, 0, sizeof(fBuffer));
    aLent = recv(s, fBuffer, sizeof(fBuffer)-1, 0);
    if (aLent == SOCKET_ERROR || aLent == 0)
    {
        // Call WSAGetLastError() to get the error number.
        ThrowXMLwithMemMgr1(NetAccessorException, XMLExcepts::NetAcc_ReadSocket, urlSource.getURLText(), fMemoryManager);
    }

    fBufferEnd = fBuffer+aLent;
    *fBufferEnd = 0;

    do {
        // Find the break between the returned http header and any data.
        //  (Delimited by a blank line)
        // Hang on to any data for use by the first read from this BinHTTPURLInputStream.
        //
        fBufferPos = strstr(fBuffer, "\r\n\r\n");
        if (fBufferPos != 0)
        {
            fBufferPos += 4;
            *(fBufferPos-2) = 0;
            fHeaderRead = true;
        }
        else
        {
            fBufferPos = strstr(fBuffer, "\n\n");
            if (fBufferPos != 0)
            {
                fBufferPos += 2;
                *(fBufferPos-1) = 0;
                fHeaderRead = true;
            }
            else
            {
                //
                // Header is not yet read, do another recv() to get more data...
                aLent = recv(s, fBufferEnd, (sizeof(fBuffer) - 1) - (fBufferEnd - fBuffer), 0);
                if (aLent == SOCKET_ERROR || aLent == 0)
                {
                    // Call WSAGetLastError() to get the error number.
                    ThrowXMLwithMemMgr1(NetAccessorException, XMLExcepts::NetAcc_ReadSocket, urlSource.getURLText(), fMemoryManager);
                }
                fBufferEnd = fBufferEnd + aLent;
                *fBufferEnd = 0;
            }
        }
    } while(fHeaderRead == false);

    // Make sure the header includes an HTTP 200 OK response.
    //
    char *p = strstr(fBuffer, "HTTP");
    if (p == 0)
    {
        ThrowXMLwithMemMgr1(NetAccessorException, XMLExcepts::NetAcc_ReadSocket, urlSource.getURLText(), fMemoryManager);
    }

    p = strchr(p, ' ');
    if (p == 0)
    {
        ThrowXMLwithMemMgr1(NetAccessorException, XMLExcepts::NetAcc_ReadSocket, urlSource.getURLText(), fMemoryManager);
    }

    int httpResponse = atoi(p);
    if (httpResponse != 200)
    {
        // Most likely a 404 Not Found error.
        //   Should recognize and handle the forwarding responses.
        //
        ThrowXMLwithMemMgr1(NetAccessorException, XMLExcepts::File_CouldNotOpenFile, urlSource.getURLText(), fMemoryManager);
    }

    fSocketHandle = (unsigned int) *janSock.release();
}
コード例 #2
0
UnixHTTPURLInputStream::UnixHTTPURLInputStream(const XMLURL& urlSource, const XMLNetHTTPInfo* httpInfo/*=0*/)
    : BinHTTPInputStreamCommon(urlSource.getMemoryManager()),
      fSocket(0)
{
    //
    //  Convert the hostName to the platform's code page for gethostbyname and
    //  inet_addr functions.
    //

    MemoryManager *memoryManager = urlSource.getMemoryManager();

    const XMLCh*        hostName = urlSource.getHost();

    if (hostName == 0)
      ThrowXMLwithMemMgr1(NetAccessorException,
                          XMLExcepts::File_CouldNotOpenFile,
                          urlSource.getURLText(),
                          memoryManager);

    char*               hostNameAsCharStar = XMLString::transcode(hostName, memoryManager);
    ArrayJanitor<char>  janHostNameAsCharStar(hostNameAsCharStar, memoryManager);

    XMLURL url(urlSource);
    int redirectCount = 0;
    SocketJanitor janSock(0);

    do {
        //
        // Set up a socket.
        //

#if HAVE_GETADDRINFO
        struct addrinfo hints, *res, *ai;

        CharBuffer portBuffer(10, memoryManager);
        portBuffer.appendDecimalNumber(url.getPortNum());

        memset(&hints, 0, sizeof(struct addrinfo));
        hints.ai_family = PF_UNSPEC;
        hints.ai_socktype = SOCK_STREAM;
        int n = getaddrinfo(hostNameAsCharStar,portBuffer.getRawBuffer(),&hints, &res);
        if(n != 0)
        {
            hints.ai_flags = AI_NUMERICHOST;
            n = getaddrinfo(hostNameAsCharStar,portBuffer.getRawBuffer(),&hints, &res);
            if(n != 0)
                ThrowXMLwithMemMgr1(NetAccessorException, XMLExcepts::NetAcc_TargetResolution, hostName, memoryManager);
        }
        janSock.reset();
        for (ai = res; ai != NULL; ai = ai->ai_next) {
            // Open a socket with the correct address family for this address.
            fSocket = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
            if (fSocket < 0)
                continue;
            janSock.reset(&fSocket);
            if (connect(fSocket, ai->ai_addr, ai->ai_addrlen) < 0)
            {
                freeaddrinfo(res);
                ThrowXMLwithMemMgr1(NetAccessorException,
                         XMLExcepts::NetAcc_ConnSocket, url.getURLText(), memoryManager);
            }
            break;
        }
        freeaddrinfo(res);
        if (fSocket < 0)
        {
            ThrowXMLwithMemMgr1(NetAccessorException,
                     XMLExcepts::NetAcc_CreateSocket, url.getURLText(), memoryManager);
        }
#else
        struct hostent *hostEntPtr = 0;
        struct sockaddr_in sa;

        // Use the hostName in the local code page ....
        if((hostEntPtr = gethostbyname(hostNameAsCharStar)) == NULL)
        {
            unsigned long  numAddress = inet_addr(hostNameAsCharStar);
            if ((hostEntPtr =
                    gethostbyaddr((char *) &numAddress,
                        sizeof(unsigned long), AF_INET)) == NULL)
            {
                ThrowXMLwithMemMgr1(NetAccessorException,
                    XMLExcepts::NetAcc_TargetResolution, hostName, memoryManager);
            }
        }

        memset(&sa, '\0', sizeof(sockaddr_in));  // iSeries fix ??
        memcpy((void *) &sa.sin_addr,
            (const void *) hostEntPtr->h_addr, hostEntPtr->h_length);
        sa.sin_family = hostEntPtr->h_addrtype;
        sa.sin_port = htons((unsigned short)url.getPortNum());

        janSock.reset();
        fSocket = socket(hostEntPtr->h_addrtype, SOCK_STREAM, 0);
        if(fSocket < 0)
        {
            ThrowXMLwithMemMgr1(NetAccessorException,
                XMLExcepts::NetAcc_CreateSocket, url.getURLText(), memoryManager);
        }
        janSock.reset(&fSocket);

        if(connect(fSocket, (struct sockaddr *) &sa, sizeof(sa)) < 0)
        {
            ThrowXMLwithMemMgr1(NetAccessorException,
                XMLExcepts::NetAcc_ConnSocket, url.getURLText(), memoryManager);
        }
#endif

        int status = sendRequest(url, httpInfo);

        if(status == 200) {
            // HTTP 200 OK response means we're done.
            break;
        }
        // a 3xx response means there was an HTTP redirect
        else if(status >= 300 && status <= 307) {
            redirectCount++;

            XMLCh *newURLString = findHeader("Location");
            ArrayJanitor<XMLCh> janNewURLString(newURLString, memoryManager);

            if(newURLString == 0 || *newURLString == 0) {
                ThrowXMLwithMemMgr1(NetAccessorException, XMLExcepts::File_CouldNotOpenFile, url.getURLText(), memoryManager);
            }

            XMLURL newURL(memoryManager);
            newURL.setURL(url, newURLString);
            if(newURL.getProtocol() != XMLURL::HTTP) {
                ThrowXMLwithMemMgr1(NetAccessorException, XMLExcepts::File_CouldNotOpenFile, newURL.getURLText(), memoryManager);
            }

            url = newURL;
            hostName = newURL.getHost();

            if (hostName == 0)
              ThrowXMLwithMemMgr1(NetAccessorException,
                                  XMLExcepts::File_CouldNotOpenFile,
                                  newURL.getURLText(),
                                  memoryManager);

            janHostNameAsCharStar.release();
            hostNameAsCharStar = XMLString::transcode(hostName, memoryManager);
            janHostNameAsCharStar.reset(hostNameAsCharStar, memoryManager);
        }
        else {
            // Most likely a 404 Not Found error.
            ThrowXMLwithMemMgr1(NetAccessorException, XMLExcepts::File_CouldNotOpenFile, url.getURLText(), memoryManager);
        }
    } while(redirectCount < 6);

    janSock.release();
}