Andrew Boyson / net

Dependents:   oldheating gps motorhome heating

tcp/http/httprequest.c

Committer:
andrewboyson
Date:
2018-01-11
Revision:
61:aad055f1b0d1
Parent:
tcp/http/httprequest.cpp@ 54:84ef2b29cf7e
Child:
110:67c96c143c2a

File content as of revision 61:aad055f1b0d1:

#include <stdbool.h>
#include <stdio.h>
#include <string.h>

char* HttpGetNextLine(char* p, char* pE) //Terminates this line and returns the start of the next line or NULL if none
{
    while (true)
    {
        if (p == pE)             //There are no more lines
        {
            *p = 0;              //terminate the line
            return NULL;   
        }
        if (*p == 0) return NULL;//There are no more lines
        if (*p == '\n')
        {
            *p = 0;              //make the line a c string
            return p + 1;        //return the start of the next line
        }
        if (*p < ' ')    *p = 0; //terminate the line at any invalid characters
        if (*p >= 0x7f)  *p = 0; //terminate the line at any invalid characters
        p++;
    }
}

void HttpSplitRequest(char* p, char** ppMethod, char** ppPath, char** ppQuery)
{        
    *ppMethod   = NULL;
    *ppPath     = NULL;
    *ppQuery    = NULL;

    while (*p == ' ')         //Move past any leading spaces
    {
        if (*p == 0) return;
        p++;
    }
    *ppMethod = p;            //Record the start of the method (GET or POST)
 
    while (*p != ' ')         //Move past the method
    {
        if (*p == 0) return;
        p++;
    } 
    *p = 0;                   //Terminate the method
    p++;                      //Start at next character

    while (*p == ' ')         //Move past any spaces
    {
        if (*p == 0) return;
        p++;
    } 
    *ppPath = p;              //Record the start of the path
    
    while (*p != ' ')         //Move past the path and query
    {
        if (*p == 0) return;
        if (*p == '?')
        {
            *p = 0;           //Terminate the path
            *ppQuery = p + 1; //Record the start of the query
        }
        p++;
    }
    *p = 0;                   //Terminate the path or query
}
void HttpSplitHeader(char* p, char** ppName, char** ppValue)
{
    *ppName    = p;                     //Record the start of the name
    *ppValue   = NULL;

    while (*p != ':')                   //Loop to an ':'
    {
        if (!*p) return;
        p++;
    }
    *p = 0;                             //Terminate the name by replacing the ':' with a NUL char
    p++;
    while (*p == ' ')                   //Move past any spaces
    {
        if (*p == 0) return;
        p++;
    }
    *ppValue = p;                       //Record the start of the value
}

char* HttpSplitQuery(char* p, char** ppName, char** ppValue) //returns the start of the next name value pair
{    
    *ppName    = p;                     //Record the start of the name
    *ppValue   = NULL;

    while (*p != '=')                   //Loop to an '='
    {
        if (*p == 0)    return 0;
        p++;
    }
    *p = 0;                             //Terminate the name by replacing the '=' with a NUL char
    p++;                                //Move on to the start of the value
    *ppValue = p;                       //Record the start of the value
    while (*p != '&')                   //Loop to a '&'
    {
        if (*p == 0)    return 0;
        p++;
    }
    *p = 0;                            //Terminate the value by replacing the '&' with a NULL
    return p + 1;
}
static int hexToInt(char c)
{
    int nibble;
    if (c >= '0' && c <= '9') nibble = c - '0';
    if (c >= 'A' && c <= 'F') nibble = c - 'A' + 0xA;
    if (c >= 'a' && c <= 'f') nibble = c - 'a' + 0xA;
    return nibble;
}
void HttpDecodeValue(char* value)
{
    char* pDst = value;
    int a;
    for (char* pSrc = value; *pSrc; pSrc++)
    {
        char c = *pSrc;
        switch (c)
        {
            case '+':
                c = ' ';
                break;
            case '%':
                c = *++pSrc;
                if (c == 0) break;
                a = hexToInt(c);
                a <<= 4;
                c = *++pSrc;
                if (c == 0) break;
                a += hexToInt(c);
                c = a;
                break;
            default:
                c = *pSrc;
                break;
        }
        *pDst++ = c;
    }
    *pDst = 0;
}

void HttpReadRequest(char *pData, int len, char** ppMethod, char** ppPath, char** ppQuery, char** ppLastModified)
{    
    char* pEnd = pData + len;
    char* pThis = pData;    
    char* pNext = HttpGetNextLine(pThis, pEnd);
    HttpSplitRequest(pThis, ppMethod, ppPath, ppQuery);

    while(pNext)
    {
        pThis = pNext;
        pNext = HttpGetNextLine(pThis, pEnd);
        if (*pThis == 0) break;     //This line is empty ie no more headers
        char* pName;
        char* pValue;
        HttpSplitHeader(pThis, &pName, &pValue);
        if (strcmp(pName, "If-Modified-Since") == 0) *ppLastModified = pValue;
    }
}