//-----------------------------------------------------------------------------
/// SendHTTPErrorResponse
///
/// Sends an error page back
///
/// \param requestID An ID for a particular request; the plugin will get this
///  id as a parameter to the ProcessRequest( ) function
/// \param nErrorCode numeric identifier of the error to return
///
/// \return true if the response could be sent; false otherwise
//-----------------------------------------------------------------------------
bool SendHTTPErrorResponse(CommunicationID& requestID, int nErrorCode)
{
    // see if the response is streaming and rate limited
    if (ShouldResponseBeSent(requestID, true) == true)
    {
        // the message shouldn't be sent because of the rate limiting
        // return true though so the server thinks it was sent successfully
        return true;
    }

    Response* pResponse = NULL;

    if (MakeResponse(requestID, &pResponse) == false)
    {
        return false;
    }

    if (OutputHTTPError(pResponse->client_socket, nErrorCode) == false)
    {
        DestroyResponse(requestID, &pResponse);
        return false;
    }

    if (pResponse->m_bStreamingEnabled == false)
    {
        DestroyResponse(requestID, &pResponse);
    }

    return true;
}
//-----------------------------------------------------------------------------
/// SendRedirectResponse
///
/// Redirects the browser to a different URL than the one requested
///
/// \param requestID An ID for a particular request; the plugin will get this
///  id as a parameter to the ProcessRequest( ) function
/// \param pNewURL The url that the browser is being redirected to
///
/// \return true if the response could be sent; false otherwise
//-----------------------------------------------------------------------------
bool SendRedirectResponse(CommunicationID& requestID, const char* pNewURL)
{
    if (pNewURL == NULL)
    {
        return false;
    }

    // see if the response is streaming and rate limited
    if (ShouldResponseBeSent(requestID, true) == true)
    {
        // the message shouldn't be sent because of the rate limiting
        // return true though so the server thinks it was sent successfully
        return true;
    }

    Response* pResponse = NULL;

    if (MakeResponse(requestID, &pResponse) == false)
    {
        return false;
    }

    // generate the redirect html
    static char headerBuffer[COMM_BUFFER_SIZE];
    static char htmlBuffer[COMM_BUFFER_SIZE];

    sprintf_s(htmlBuffer, COMM_BUFFER_SIZE, "<html><body><a href=\"%s\">%s</a></body></html>", pNewURL, pNewURL);
    sprintf_s(headerBuffer, COMM_BUFFER_SIZE, "HTTP/1.0 301\r\nContent-Type: text/html\r\nContent-Length: %zd\r\nLocation: %s\r\n\r\n", strlen(htmlBuffer), pNewURL);

    bool nRes1;
    bool nRes2;
    nRes1 = pResponse->client_socket->Send(headerBuffer, (DWORD)strlen(headerBuffer));
    nRes2 = pResponse->client_socket->Send(htmlBuffer, (DWORD)strlen(htmlBuffer));

    pResponse->client_socket->close();

    if ((nRes1 == false) ||
        (nRes2 == false))
    {
        DestroyResponse(requestID, &pResponse);
        return false;
    }

    if (pResponse->m_bStreamingEnabled == false)
    {
        DestroyResponse(requestID, &pResponse);
    }

    return true;
}
//-----------------------------------------------------------------------------
/// SendMimeResponse
///
/// Sends a single buffer of raw data as the response which should be
/// interpreted by the recipient as being of the indicated MIME type
///
/// \param requestID An ID for a particular request; the plugin will get this
///  id as a parameter to the ProcessRequest( ) function
/// \param cpMimeType A string identifying which MIME type to use for
///  interpreting the data
/// \param cpData pointer to the data that should be sent as a response
/// \param uSizeInBytes number of bytes of data pointed to by cpData
///
/// \return true if the response could be sent; false otherwise
//-----------------------------------------------------------------------------
bool SendMimeResponse(CommunicationID& requestID, const char* cpMimeType, const char* cpData, unsigned int uSizeInBytes)
{
    if (cpMimeType == NULL)
    {
        Log(logERROR, "Failed to send %s response because data is NULL\n", cpMimeType);
        return false;
    }

    // see if the response is streaming and rate limited
    if (ShouldResponseBeSent(requestID, true) == true)
    {
        // the message shouldn't be sent because of the rate limiting
        // return true though so the server thinks it was sent successfully
        return true;
    }

    Response* pResponse = NULL;

    if (MakeResponse(requestID, &pResponse) == false)
    {
        return false;
    }

    // if Data is NULL then close streaming connection
    if (pResponse->m_bStreamingEnabled == true)
    {
        if (cpData == NULL)
        {
            const char* pstr = "--BoundaryString\r\n";
            pResponse->client_socket->Send(pstr, (unsigned int)strlen(pstr));
            CloseConnection(*pResponse);
            DestroyResponse(requestID, &pResponse);
            return true;
        }
    }

    if (Send(*pResponse, cpMimeType, cpData, uSizeInBytes) == false)
    {
        DestroyResponse(requestID, &pResponse);
        return false;
    }

    if (pResponse->m_bStreamingEnabled == false)
    {
        DestroyResponse(requestID, &pResponse);
    }

    return true;
}
//-----------------------------------------------------------------------------
/// SendFormattedTextResponse
///
/// Send a formatted string to be interpreted as text by the recipient.
///
/// \param requestID An ID for a particular request; the plugin will get this
///  id as a parameter to the ProcessRequest( ) function
/// \param cpFormat pointer to a character format that should be send as a
///  response; it is expected that this format consumes the remaining
///  parameters to this function
///
/// \return true if the response could be sent; false otherwise
//-----------------------------------------------------------------------------
bool SendFormattedTextResponse(CommunicationID& requestID, const char* cpFormat, ...)
{
    if (cpFormat == NULL)
    {
        Log(logERROR, "Failed to send formatted response because data is NULL\n");
        return false;
    }

    // see if the response is streaming and rate limited
    if (ShouldResponseBeSent(requestID, true) == true)
    {
        // the message shouldn't be sent because of the rate limiting
        // return true though so the server thinks it was sent successfully
        return true;
    }

    Response* pResponse = NULL;

    if (MakeResponse(requestID, &pResponse) == false)
    {
        Log(logERROR, "Failed to make a response for requestID %d\n", requestID);
        return false;
    }

    static char string[ 10240 ];
    va_list arg_ptr;

    va_start(arg_ptr, cpFormat);
    vsprintf_s(string, 10240, cpFormat, arg_ptr);
    va_end(arg_ptr);

    if (Send(*pResponse, "text/plain", string, (unsigned long)strlen(string)) == false)
    {
        Log(logERROR, "Failed to 'Send' response for requestID %d\n", requestID);
        DestroyResponse(requestID, &pResponse);
        return false;
    }

    if (pResponse->m_bStreamingEnabled == false)
    {
        DestroyResponse(requestID, &pResponse);
    }

    return true;
}
示例#5
0
  String HTTP::HandleRequest(const String& request)
  {
    u32 line = 0;
    u32 pos = 0;
    String requestLine = NextSubstring(request, line);

    String verb = NextSubstring(requestLine, pos, " ");
    if(verb == "GET" || verb == "HEAD")
    {
      LOG("Verb: " << verb);

      String requestedResource = NextSubstring(requestLine, pos, " ");
      String requestVersion = NextSubstring(requestLine, pos, " ");
      LOG("resource: " << requestedResource);
      LOG("version: " << requestVersion);

      return MakeResponse(OK, TextHTML, "<html><body><p>hai</p></body><html>", verb == "GET");
    }
    //MakeResponse(NotFound, TextHTML, "<html><body><h1>NotFound!</h1></body></html>");
    return EMPTY_STRING;
  }
//-----------------------------------------------------------------------------
/// SendBinaryResponse
///
/// Sends a single buffer of raw data as the response.
///
/// \param requestID An ID for a particular request; the plugin will get this
///  id as a parameter to the ProcessRequest( ) function
/// \param cpData pointer to the data that should be sent as a response
/// \param uSizeInBytes number of bytes of data pointed to by cpData
///
/// \return true if the response could be sent; false otherwise
//-----------------------------------------------------------------------------
bool SendBinaryResponse(CommunicationID& requestID,
                        const char* cpData,
                        unsigned int uSizeInBytes)
{
    if (cpData == NULL)
    {
        Log(logERROR, "Failed to send binary response because data is NULL\n");
        return false;
    }

    // see if the response is streaming and rate limited
    if (ShouldResponseBeSent(requestID, true) == true)
    {
        // the message shouldn't be sent because of the rate limiting
        // return true though so the server thinks it was sent successfully
        return true;
    }

    Response* pResponse = NULL;

    if (MakeResponse(requestID, &pResponse) == false)
    {
        Log(logERROR, "Failed to make a response for requestID %d\n", requestID);
        return false;
    }

    if (Send(*pResponse, "application/octet-stream", cpData, uSizeInBytes) == false)
    {
        Log(logERROR, "Failed to 'Send' response for requestID %d\n", requestID);

        if (pResponse->m_bStreamingEnabled == false)
        {
            DestroyResponse(requestID, &pResponse);
        }

        return false;
    }

    return true;
}
//-----------------------------------------------------------------------------
/// SendTextResponse
///
/// Sends a character string to be interpreted as text by the recipient.
///
/// \param requestID An ID for a particular request; the plugin will get this
///  id as a parameter to the ProcessRequest( ) function
/// \param cpData pointer to the text that should be sent as a response
///
/// \return true if the response could be sent; false otherwise
//-----------------------------------------------------------------------------
bool SendTextResponse(CommunicationID& requestID, const char* cpData)
{
    if (cpData == NULL)
    {
        Log(logERROR, "Failed to send text response because data is NULL\n");
        return false;
    }

    // see if the response is streaming and rate limited
    if (ShouldResponseBeSent(requestID, true) == true)
    {
        // the message shouldn't be sent because of the rate limiting
        // return true though so the server thinks it was sent successfully
        return true;
    }

    Response* pResponse = NULL;

    if (MakeResponse(requestID, &pResponse) == false)
    {
        Log(logERROR, "Failed to make a response for requestID %d to send content: %s\n", requestID, cpData);
        return false;
    }

    if (Send(*pResponse, "text/plain", cpData, (unsigned long)strlen(cpData)) == false)
    {
        Log(logERROR, "Failed to 'Send' response for requestID %d with content: %s\n", requestID, cpData);
        DestroyResponse(requestID, &pResponse);
        return false;
    }

    if (pResponse->m_bStreamingEnabled == false)
    {
        DestroyResponse(requestID, &pResponse);
    }

    return true;
}
//-----------------------------------------------------------------------------
/// SendFileResponse
///
/// Sends the binary contents of a file to be interpreted by the recipient as
/// the type of file indicated by the file's extension.
///
/// \param requestID An ID for a particular request; the plugin will get this
///  id as a parameter to the ProcessRequest( ) function
/// \param cpData pointer to the filename that should be sent as a response
///
/// \return true if the response could be sent; false otherwise
//-----------------------------------------------------------------------------
bool SendFileResponse(CommunicationID& requestID, const char* cpFile)
{
    if (cpFile == NULL)
    {
        Log(logERROR, "Failed to send file response because filename is NULL\n");
        return false;
    }

    // see if the response is streaming and rate limited
    if (ShouldResponseBeSent(requestID, true) == true)
    {
        // the message shouldn't be sent because of the rate limiting
        // return true though so the server thinks it was sent successfully
        return true;
    }

    Response* pResponse = NULL;

    if (MakeResponse(requestID, &pResponse) == false)
    {
        Log(logERROR, "Failed to make a response for requestID %d to send file: %s\n", requestID, cpFile);
        return false;
    }

    // collect file data and generate response
    FILE* in;
    long fileSize;
    char* fileBuffer;
    fopen_s(&in, cpFile, "rb");    // read binary

    if (!in)
    {
        // file error, not found?
        OutputHTTPError(pResponse->client_socket, 404);     // 404 - not found
        return false;
    }

    // determine file size
    fseek(in, 0, SEEK_END);
    fileSize = ftell(in);
    fseek(in, 0, SEEK_SET);

    // allocate Buffer_ and read in file contents
    fileBuffer = new char[fileSize];
    fread(fileBuffer, sizeof(char), fileSize, in);
    fclose(in);

    bool bRes = Send(*pResponse, mimetypes[ FindMimeType(cpFile)].mime, fileBuffer, fileSize);

    if (bRes == false)
    {
        Log(logERROR, "Failed to 'Send' response for requestID %d\n", requestID);
        DestroyResponse(requestID, &pResponse);
    }

    delete [] fileBuffer;

    if (pResponse->m_bStreamingEnabled == false)
    {
        DestroyResponse(requestID, &pResponse);
    }

    return bRes;

}