Jump to content

C++ openURL Function

- - - - -

  • Please log in to reply
No replies to this topic

#1
brownhead

brownhead

    Programmer

  • Members
  • PipPipPipPip
  • 173 posts
I made this the other day and thought others might like to use it since I wasn't able to find an easy alternative online. The function uses Window's INET to retrieve the contents of a webpage. Only HTTP is supported, though if you have a serious need for FTP it's not too hard to implement using INET. Function is pretty easy to use, here's the code.
#include <wininet.h>
#include <string.h>

/**
 * Retrieves the contents of a file from a remote HTTP server. In
 * other words: gets the contents of a webpage. The function is
 * synchronous, meaning it will not return until it has retrieved
 * the contents of the web page, or it has failed. Expect a time
 * delay.
 *
 * \param zurl  A null terminated string of the URL of the web page.
 * \param zsize A pointer to an integer that will be set to the size
 *              (in bytes) of the string returned. If the function
 *              fails the integer will not be changed. This parameter
 *              can be NULL.
 *
 * \return A null-terminated string containing the contents of the
 *         web page. If the function fails, NULL is returned. Don't
 *         forget to free the string when you're done with it.
 **/
char* openURL(const char* zurl, int* zsize)
{
    // This will hold the web page's contents
    char* content = NULL;
    int content_size = 0;

    // Create the buffers that will hold each part of the url
    int zurl_len = strlen(zurl) + 1;
    char* hostName = (char*)malloc(zurl_len);
    char* urlPath = (char*)malloc(zurl_len);
    char* extraInfo = (char*)malloc(zurl_len);

    // Create a URL_COMPONENTS structure and zero its members
    URL_COMPONENTS url;
    memset(&url, 0, sizeof(URL_COMPONENTS));

    // Tell it how big it is
    url.dwStructSize = sizeof(URL_COMPONENTS);

    // Place our buffers in the structures
    url.lpszHostName = hostName;
    url.dwHostNameLength = zurl_len;
    url.lpszUrlPath = urlPath;
    url.dwUrlPathLength = zurl_len;
    url.lpszExtraInfo = extraInfo;
    url.dwExtraInfoLength = zurl_len;

    // Now break the url apart
    if (!InternetCrackUrl(zurl, 0, ICU_DECODE, &url)) goto failURL;

    // Append the extraInfo varaible to urlPath because they should always be together
    if (url.dwExtraInfoLength != 0)
    {
        urlPath = (char*)realloc(urlPath, strlen(urlPath) + strlen(extraInfo));
        strcat(urlPath, extraInfo);
    }

    // Enable INET for our application. Use default proxy settings.
    HINTERNET hInet = InternetOpen("openURL", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
    if (hInet == NULL) goto failInet;

    // Prepare our connection to the server
    HINTERNET hServer = InternetConnect(hInet, hostName, INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
    if (hServer == NULL) goto failServer;

    // Create our request
    HINTERNET hRequest = HttpOpenRequest(hServer, NULL, urlPath, NULL, NULL, NULL, 0, 0);
    if (hRequest == NULL) goto failRequest;

    // Send out our request
    if (!HttpSendRequest(hRequest, NULL, 0, NULL, 0)) goto failRequest;

    // Loop until we get all of the webpage contents from the server
    DWORD available;
    while (InternetQueryDataAvailable(hRequest, &available, 0, 0))
    {
        // Create a buffer to hold the information from the server
        char* buffer = (char*)malloc(available + 1);

        // Read the information we've been sent into our buffer
        DWORD bytesRead;
        if (!InternetReadFile(hRequest, buffer, available, &bytesRead))
        {
            free(buffer);
            goto failRequest;
        }

        // If were done getting information, break
        if (bytesRead == 0) break;

        // If this is the first piece of content we've gotten
        if (content == NULL)
        {
            // Copy the contents of the buffer into the newly allocated content
            content = (char*)malloc(bytesRead);
            content_size = bytesRead;
            memcpy(content, buffer, bytesRead);
        }
        else
        {
            // Reallocate content
            content = (char*)realloc(content, content_size + bytesRead);

            // Join the new content with the old
            memcpy(content + content_size, buffer, bytesRead);

            // Update content_size
            content_size += bytesRead;
        }
    }

    // Ensure content is null terminated
    content = (char*)realloc(content, ++content_size);
    content[content_size - 1] = '\0';

    // Set the size
    if (zsize != NULL) (*zsize) = content_size;

    // Clean up
    InternetCloseHandle(hRequest);
    InternetCloseHandle(hServer);
    InternetCloseHandle(hInet);
    free(extraInfo);
    free(urlPath);
    free(hostName);
    return content;

    // Clean up when failure occurs
    failRequest: InternetCloseHandle(hRequest);
    failServer: InternetCloseHandle(hServer);
    failInet: InternetCloseHandle(hInet);
    failURL:
    free(extraInfo);
    free(urlPath);
    free(hostName);
    free(content);
    return NULL;
}
Note: This code will compile as C code and as C++ code.




1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users