/** * \file * * \author Georg Hopp * * \copyright * Copyright © 2014 Georg Hopp * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include "trbase.h" #include "trio.h" #include "trdata.h" #include "http/parser.h" #include "http/header.h" #include "http/interface/http_intro.h" ssize_t httpParserParse(void * _this, TR_Stream st) { HttpParser this = _this; int cont = 1; ssize_t read; char * line; char * line_end; if (TR_cbufIsLocked(this->buffer)) { if (FALSE == this->ourLock) return 0; } else { TR_cbufLock(this->buffer); this->ourLock = TRUE; } if (NULL != this->incomplete) { TR_cbufSetData(this->buffer, this->incomplete, this->isize); TR_MEM_FREE(this->incomplete); } if (0 > (read = TR_cbufRead(this->buffer, st))) { TR_cbufRelease(this->buffer); this->ourLock = FALSE; return read; } while (cont) { switch(this->state) { case HTTP_MESSAGE_GARBAGE: TR_cbufSkipNonAlpha(this->buffer); if (! TR_cbufIsEmpty(this->buffer)) { this->state = HTTP_MESSAGE_START; } else { TR_cbufRelease(this->buffer); this->ourLock = FALSE; cont = 0; break; } case HTTP_MESSAGE_START: if (NULL == (line = TR_cbufGetLine(this->buffer, &line_end))) { if (! TR_cbufIsEmpty(this->buffer)) { this->isize = this->buffer->bused; this->incomplete = TR_malloc(this->isize); memcpy(this->incomplete, TR_cbufGetData(this->buffer, this->isize), this->isize); } TR_cbufRelease(this->buffer); this->ourLock = FALSE; cont = 0; break; } httpParserNewMessage(this, line, line_end); if (NULL == this->current) { TR_cbufRelease(this->buffer); this->ourLock = FALSE; return -2; // a server error occured can't process... } httpParserRequestVars(this); this->state = HTTP_MESSAGE_INTRO_DONE; case HTTP_MESSAGE_INTRO_DONE: if (NULL == (line = TR_cbufGetLine(this->buffer, &line_end))) { if (! TR_cbufIsEmpty(this->buffer)) { this->isize = this->buffer->bused; this->incomplete = TR_malloc(this->isize); memcpy(this->incomplete, TR_cbufGetData(this->buffer, this->isize), this->isize); } TR_cbufRelease(this->buffer); this->ourLock = FALSE; cont = 0; break; } if (0 != strlen(line)) { httpParserHeader(this, line, line_end); break; } this->state = HTTP_MESSAGE_HEADERS_DONE; case HTTP_MESSAGE_HEADERS_DONE: if (this->current->dbody == this->current->nbody) { this->state = HTTP_MESSAGE_DONE; } else { if (TR_cbufIsEmpty(this->buffer)) { TR_cbufRelease(this->buffer); this->ourLock = FALSE; cont = 0; break; } TR_cbufIncRead( this->buffer, httpParserBody( this, TR_cbufGetRead(this->buffer), this->buffer->bused)); break; } case HTTP_MESSAGE_DONE: { HttpHeader enc = TR_hashGet( this->current->header, CSTRA("content-type")); /** * do we have form data?? */ if (NULL != enc && 0 == strncasecmp( "application/x-www-form-urlencoded", enc->value[0], MIN(sizeof("application/x-www-form-urlencoded")-1, enc->nvalue[0]))) { //!> then parse them... httpParserPostVars(this); } /** * enqueue current request */ TR_queuePut(this->queue, this->current); this->current = NULL; /** * prepare for next request */ this->state = HTTP_MESSAGE_GARBAGE; } break; default: break; } } return this->queue->nmsg; } // vim: set ts=4 sw=4: