/** * Parses the provided data chunk, keeping state to allow streaming parsing, i.e., the * parsing where only partial information is available at any one time. The method * htp_urlenp_finalize() must be invoked at the end to finalize parsing. * * @param urlenp * @param data * @param len * @return */ int htp_urlenp_parse_partial(htp_urlenp_t *urlenp, unsigned char *data, size_t len) { size_t startpos = 0; size_t pos = 0; int c; if (data == NULL) len = 0; for (;;) { // Get the next character, or -1 if (pos < len) c = data[pos]; else c = -1; switch (urlenp->_state) { // Process key case HTP_URLENP_STATE_KEY: // Look for =, argument separator, or end of input if ((c == '=') || (c == urlenp->argument_separator) || (c == -1)) { // Data from startpos to pos htp_urlenp_add_field_piece(urlenp, data, startpos, pos, c); if (c != -1) { // Next state startpos = pos + 1; urlenp->_state = HTP_URLENP_STATE_VALUE; } } break; // Process value case HTP_URLENP_STATE_VALUE: // Look for argument separator or end of input if ((c == urlenp->argument_separator) || (c == -1)) { // Data from startpos to pos htp_urlenp_add_field_piece(urlenp, data, startpos, pos, c); if (c != -1) { // Next state startpos = pos + 1; urlenp->_state = HTP_URLENP_STATE_KEY; } } break; } // Have we reached the end of input? if (c == -1) break; pos++; } return HTP_OK; }
/** * Parses the provided data chunk, keeping state to allow streaming parsing, i.e., the * parsing where only partial information is available at any one time. The method * htp_urlenp_finalize() must be invoked at the end to finalize parsing. * * @param[in] urlenp * @param[in] _data * @param[in] len * @return */ htp_status_t htp_urlenp_parse_partial(htp_urlenp_t *urlenp, const void *_data, size_t len) { unsigned char *data = (unsigned char *) _data; size_t startpos = 0; size_t pos = 0; int c; if (data == NULL) len = 0; do { // Get the next character, or use -1 to indicate end of input. if (pos < len) c = data[pos]; else c = -1; switch (urlenp->_state) { case HTP_URLENP_STATE_KEY: // Look for =, argument separator, or end of input. if ((c == '=') || (c == urlenp->argument_separator) || (c == -1)) { // Data from startpos to pos. htp_urlenp_add_field_piece(urlenp, data, startpos, pos, c); // If it's not the end of input, then it must be the end of this field. if (c != -1) { // Next state. startpos = pos + 1; if (c == urlenp->argument_separator) { urlenp->_state = HTP_URLENP_STATE_KEY; } else { urlenp->_state = HTP_URLENP_STATE_VALUE; } } } pos++; break; case HTP_URLENP_STATE_VALUE: // Look for argument separator or end of input. if ((c == urlenp->argument_separator) || (c == -1)) { // Data from startpos to pos. htp_urlenp_add_field_piece(urlenp, data, startpos, pos, c); // If it's not the end of input, then it must be the end of this field. if (c != -1) { // Next state. startpos = pos + 1; urlenp->_state = HTP_URLENP_STATE_KEY; } } pos++; break; default: // Invalid state. return HTP_ERROR; } } while (c != -1); return HTP_OK; }