/* * 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 "functionparser.h" #include "core/log.h" #include "core/error.h" #include "functions.h" #include "utf8/utf8.h" #include "models/item.h" namespace Winix { FunctionParser::FunctionParser() { } bool FunctionParser::Parse(Cur * pcur, Db * pdb, Functions * pfunctions, System * psystem) { db = pdb; cur = pcur; system = psystem; functions = pfunctions; last_dir = 0; path = cur->request->env_request_uri.c_str(); ParseDirsItemFunction(); ParseParams(); ParseAnchor(); return cur->request->status == WINIX_ERR_OK; } void FunctionParser::ParseDirsItemFunction() { if( !AddRootDir() ) return; ReadName(); while( IsDir() ) { AddDir(); ReadName(); } if( name.empty() ) return; if( CheckAddFunction() ) return; if( CheckAddItem() ) { ReadName(); if( !name.empty() ) { CheckAddFunction(); if( !cur->request->function ) { log << log3 << "FP: unknown function: " << name << logend; cur->request->status = WINIX_ERR_NO_ITEM; } } } } bool FunctionParser::AddRootDir() { last_dir = system->dirs.GetRootDir(); if( !last_dir ) { log << log3 << "FP: there is not a root directory" << logend; cur->request->status = WINIX_ERR_INTERNAL_ERROR; return false; } AddDir(); return true; } bool FunctionParser::IsDir() { // directory names should not be empty if( name.empty() || !last_dir ) return false; last_dir = system->dirs.GetDir(name, last_dir->id); return last_dir != 0; } bool FunctionParser::CheckAddItem() { // cur->request->dir_tab has at least one element long parent_id = cur->request->dir_tab.back()->id; morm::Finder finder(model_connector); finder. select(). where(). eq(L"parent_id", parent_id). eq(L"url", name). get(cur->request->item); //Error status = db->GetItem(parent_id, name, cur->request->item); //if( status == WINIX_ERR_OK ) if( cur->request->item.found() ) { log << log3 << "FP: Item: id: " << cur->request->item.id << ", url: " << cur->request->item.url << logend; cur->request->last_item = &cur->request->item; cur->request->is_item = true; return true; } else { log << log3 << "FP: No Item: url: " << name << logend; cur->request->status = WINIX_ERR_NO_ITEM; return false; } log << log1 << "FP: db error" << logend; cur->request->status = WINIX_ERR_INTERNAL_ERROR; return false; } bool FunctionParser::CheckAddFunction() { cur->request->function = functions->Find(name); if( cur->request->function ) { log << log3 << "FP: Function: " << cur->request->function->fun.url << logend; return true; } return false; } void FunctionParser::AddDir() { cur->request->dir_tab.push_back( last_dir ); log << log3 << "FP: Directory: "; if( last_dir->parent_id == -1 ) log << "(root)" << logend; else log << last_dir->url << logend; cur->request->last_item = cur->request->dir_tab.back(); } void FunctionParser::ParseParams() { SkipSlashes(); if( *path == '#' ) { // there are not any parameters return; } if( *path == '?' ) ParseOrdinaryParams(); else ParseWinixParams(); } void FunctionParser::ParseOrdinaryParams() { if( *path == '?' ) path += 1; do { ReadOrdinaryParName(); if( name.empty() ) break; ReadOrdinaryParValue(); if( *path == '&' ) path += 1; AddParam(); } while( true ); } void FunctionParser::ParseWinixParams() { do { SkipSlashes(); ReadWinixParName(); if( name.empty() ) break; ReadWinixParValue(); AddParam(); } while( true ); } void FunctionParser::AddParam() { param.name = name; param.value = value; cur->request->param_tab.push_back(param); log << log3 << "FP: Param: name=" << param.name; if( !param.value.empty() ) log << ", value=" << param.value; log << logend; } void FunctionParser::ParseAnchor() { if( *path == 0 ) return; if( *path != '#' ) { cur->request->status = WINIX_ERR_INCORRECT_URI; return; } path += 1; name_ascii.clear(); while( *path ) name_ascii += GetChar(); pt::utf8_to_wide(name_ascii, cur->request->anchor); if( !cur->request->anchor.empty() ) log << log3 << "FP: anchor: " << cur->request->anchor << logend; } void FunctionParser::SkipSlashes() { while( *path == '/' ) path += 1; } int FunctionParser::FromHex(int c) { if( c>='0' && c<='9' ) return c - '0'; else if( c>='a' && c<='f' ) return c - 'a' + 10; else if( c>='A' && c<='F' ) return c - 'A' + 10; else cur->request->status = WINIX_ERR_INCORRECT_URI; return 0; } int FunctionParser::GetChar() { int c; if( *path == 0 ) return 0; if( *path == '%' && *(path+1)!=0 && *(path+2)!=0 ) { c = (FromHex(*(path+1)) << 4) + FromHex(*(path+2)); if( c == 0 ) cur->request->status = WINIX_ERR_INCORRECT_URI; path += 3; } else if( *path == '+' ) { c = ' '; path += 1; } else { c = *path; path += 1; } return c; } void FunctionParser::ReadName() { SkipSlashes(); name_ascii.clear(); while( *path && *path!='/' && *path!='?' && *path!='#' ) name_ascii += GetChar(); pt::utf8_to_wide(name_ascii, name); } void FunctionParser::ReadOrdinaryParName() { name_ascii.clear(); while( *path && *path!='=' && *path!='&' && *path!='#' ) name_ascii += GetChar(); pt::utf8_to_wide(name_ascii, name); } void FunctionParser::ReadOrdinaryParValue() { value_ascii.clear(); if( *path=='=' ) path += 1; while( *path && *path!='&' && *path!='#' ) value_ascii += GetChar(); pt::utf8_to_wide(value_ascii, value); } void FunctionParser::ReadWinixParName() { name_ascii.clear(); while( *path && *path!='/' && *path!=':' && *path!='#' ) name_ascii += GetChar(); pt::utf8_to_wide(name_ascii, name); } void FunctionParser::ReadWinixParValue() { value_ascii.clear(); if( *path == ':' ) path += 1; while( *path && *path!='/' && *path!='#' ) value_ascii += GetChar(); pt::utf8_to_wide(value_ascii, value); } } // namespace Winix