/* * This file is a part of Winix * and is distributed under the 2-Clause BSD licence. * Author: Tomasz Sowa */ /* * Copyright (c) 2008-2021, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #include "httpsimpleparser.h" #include "misc.h" #include "utf8/utf8.h" namespace Winix { void HttpSimpleParser::ToLower(std::wstring & s) { for(wchar_t & c : s) { if( c>='A' && c<='Z' ) c = c - 'A' + 'a'; } } bool HttpSimpleParser::IsWhite(int c) { if( c==' ' || c=='\t' ) return true; return false; } void HttpSimpleParser::SkipWhiteChars() { while( IsWhite(last_c) ) last_c = GetChar(); } int HttpSimpleParser::ParseHalfHex(int c) { if( c>='a' && c<='z' ) c += 'A' - 'a'; // to upper case if( c >= 'A' ) c = c - 'A' + 10; else c = c - '0'; c &= 0xf; return c; } void HttpSimpleParser::CheckSpecialChar() { if( last_c == '%' ) { int c1 = GetChar(); int c2 = GetChar(); if( c1==-1 || c2==-1 ) { last_c = -1; } else { c1 = ParseHalfHex(c1); c2 = ParseHalfHex(c2); last_c = (c1 << 4) + c2; } } else if( last_c == '+' ) { last_c = ' '; } } void HttpSimpleParser::ReadName() { // we're checking 'separator' and '=' because the string is allowed not having '=' (the value is optional) utf8_token.clear(); last_name.clear(); for( ; last_c!=-1 && last_c!=separator && last_c!='=' ; last_c = GetChar() ) { if( recognize_special_chars ) CheckSpecialChar(); if( last_c != -1 ) { if( getchar_returns_utf8_chars ) utf8_token += last_c; else last_name += last_c; } } if( getchar_returns_utf8_chars ) pt::utf8_to_wide(utf8_token, last_name); if( last_c == '=' ) last_c = GetChar(); } void HttpSimpleParser::ReadQuotedValue() { // skipping '"' last_c = GetChar(); utf8_token.clear(); last_value.clear(); for( ; last_c!=-1 && last_c!='"' ; last_c = GetChar() ) { if( recognize_special_chars ) CheckSpecialChar(); if( last_c != -1 ) { if( getchar_returns_utf8_chars ) utf8_token += last_c; else last_value += last_c; } } if( getchar_returns_utf8_chars ) pt::utf8_to_wide(utf8_token, last_value); if( last_c == '"' ) last_c = GetChar(); // looking for a separator (skipping) for( ; last_c!=-1 && last_c!=separator ; last_c = GetChar() ); } void HttpSimpleParser::ReadNormalValue() { utf8_token.clear(); last_value.clear(); for( ; last_c!=-1 && last_c!=separator ; last_c = GetChar() ) { if( recognize_special_chars ) CheckSpecialChar(); if( last_c != -1 ) { if( getchar_returns_utf8_chars ) utf8_token += last_c; else last_value += last_c; } } if( getchar_returns_utf8_chars ) pt::utf8_to_wide(utf8_token, last_value); } void HttpSimpleParser::ReadValue() { if( skip_white_chars ) SkipWhiteChars(); if( value_can_be_quoted && last_c == '"' ) ReadQuotedValue(); else ReadNormalValue(); if( last_c == separator ) last_c = GetChar(); } /* * there can be some important values like passwords so its better * to clear them now */ void HttpSimpleParser::Clear() { Overwrite(last_name); Overwrite(last_value); Overwrite(utf8_token); last_name.clear(); last_value.clear(); utf8_token.clear(); } void HttpSimpleParser::Parse() { for( last_c = GetChar() ; last_c != -1 ; ) { last_name.clear(); last_value.clear(); if( read_name ) ReadName(); ReadValue(); if( skip_white_chars ) { TrimWhite(last_name); TrimWhite(last_value); } Parameter(last_name, last_value); // user definied function } Clear(); } } // namespace Winix