/* * This file is a part of Winix * and is not publicly distributed * * Copyright (c) 2008-2011, Tomasz Sowa * All rights reserved. * */ #include "functionparser.h" #include "core/log.h" #include "core/item.h" #include "core/error.h" #include "functions.h" #include "utf8.h" FunctionParser::FunctionParser() { utf8 = false; } void FunctionParser::UTF8(bool use_utf8) { utf8 = use_utf8; } 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; //!! mozna dodac sprawdzanie dlugosci path // jesli wieksza niz np 2048 to zglosic incorrect url // i nie parsowac 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(); CheckAddFunction(); SkipSlashes(); if( !cur->request->function && *path && *path!='#' && *path!='?' ) { 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; Error status = db->GetItem(parent_id, name, cur->request->item); if( status == WINIX_ERR_OK ) { 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; } if( status == WINIX_ERR_NO_ITEM ) { 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(); ToWide(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 { c = *path; path += 1; } return c; } void FunctionParser::ToWide(const std::string & src, std::wstring & dst) { dst.clear(); if( utf8 ) Ezc::UTF8ToWide(src, dst, false); else AssignString(src, dst, false); } void FunctionParser::ReadName() { SkipSlashes(); name_ascii.clear(); while( *path && *path!='/' && *path!='?' && *path!='#' ) name_ascii += GetChar(); ToWide(name_ascii, name); } void FunctionParser::ReadOrdinaryParName() { name_ascii.clear(); while( *path && *path!='=' && *path!='&' && *path!='#' ) name_ascii += GetChar(); ToWide(name_ascii, name); } void FunctionParser::ReadOrdinaryParValue() { value_ascii.clear(); if( *path=='=' ) path += 1; while( *path && *path!='&' && *path!='#' ) value_ascii += GetChar(); ToWide(value_ascii, value); } void FunctionParser::ReadWinixParName() { name_ascii.clear(); while( *path && *path!='/' && *path!=':' && *path!='#' ) name_ascii += GetChar(); ToWide(name_ascii, name); } void FunctionParser::ReadWinixParValue() { value_ascii.clear(); if( *path==':' ) path += 1; while( *path && *path!='/' && *path!='#' ) value_ascii += GetChar(); ToWide(value_ascii, value); }