mirror of
https://github.com/uroni/urbackup_backend.git
synced 2025-10-26 11:36:50 +00:00
512 lines
11 KiB
C++
512 lines
11 KiB
C++
/*************************************************************************
|
|
* UrBackup - Client/Server backup system
|
|
* Copyright (C) 2011-2016 Martin Raiber
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
**************************************************************************/
|
|
|
|
#include "vld.h"
|
|
#include "Template.h"
|
|
#include "stringtools.h"
|
|
#include "Table.h"
|
|
#include "utf8/utf8.h"
|
|
#include "Server.h"
|
|
|
|
#include "Interface/Database.h"
|
|
|
|
CTemplate::CTemplate(std::string pFile)
|
|
{
|
|
file=pFile;
|
|
data=getFile(pFile);
|
|
|
|
mCurrValues=new CTable();
|
|
mValuesRoot=mCurrValues;
|
|
|
|
AddDefaultReplacements();
|
|
}
|
|
|
|
CTemplate::~CTemplate()
|
|
{
|
|
delete mValuesRoot;
|
|
|
|
for(size_t i=0;i<mTables.size();++i)
|
|
{
|
|
mTables[i].first->destroyQuery( mTables[i].second );
|
|
}
|
|
}
|
|
|
|
void CTemplate::AddDefaultReplacements(void)
|
|
{
|
|
#define ADD_REPLACEMENT(key,value) mReplacements.push_back( std::pair<std::string, std::string>(key,value) )
|
|
#define ADD_REPLACEMENT_CODE(key,value) {unsigned char ch=key; std::string tmp;tmp+=ch; mReplacements.push_back( std::pair<std::string, std::string>(tmp,value) );}
|
|
/*ADD_REPLACEMENT(L"ä",L"\\xE4");
|
|
ADD_REPLACEMENT(L"ö",L"\\xF6");
|
|
ADD_REPLACEMENT(L"ü",L"\\xFC");
|
|
ADD_REPLACEMENT(L"Ä",L"\\xC4");
|
|
ADD_REPLACEMENT(L"Ö",L"\\xFC");
|
|
ADD_REPLACEMENT(L"Ü",L"\\xD6");
|
|
ADD_REPLACEMENT(L"ß",L"\\xDF");
|
|
ADD_REPLACEMENT_CODE(246, "\\xF6");
|
|
ADD_REPLACEMENT_CODE(228, "\\xE4");
|
|
ADD_REPLACEMENT_CODE(252, "\\xFC");
|
|
ADD_REPLACEMENT_CODE(196, "\\xC4");
|
|
ADD_REPLACEMENT_CODE(214, "\\xD6");
|
|
ADD_REPLACEMENT_CODE(220, "\\xDC");
|
|
ADD_REPLACEMENT_CODE(223, "\\xDF");*/
|
|
}
|
|
|
|
ITable* CTemplate::createTableRecursive(std::string key)
|
|
{
|
|
std::vector<std::string> toks;
|
|
Tokenize(key, toks, ".");
|
|
ITable *ct=mCurrValues;
|
|
for(size_t i=0;i<toks.size();++i)
|
|
{
|
|
ITable *nt=ct->getObject(toks[i]);
|
|
if( nt==NULL )
|
|
{
|
|
nt=new CRATable();
|
|
ct->addObject(toks[i], nt);
|
|
}
|
|
ct=nt;
|
|
}
|
|
|
|
return ct;
|
|
}
|
|
|
|
ITable* CTemplate::getTable(std::string key)
|
|
{
|
|
ITable *ret;
|
|
if( (ret=findTable(key))!=NULL )
|
|
return ret;
|
|
else
|
|
return createTableRecursive(key);
|
|
}
|
|
|
|
void CTemplate::setValue(std::string key, std::string value)
|
|
{
|
|
std::vector<std::string> toks;
|
|
Tokenize(key, toks, ".");
|
|
ITable *ct=mCurrValues;
|
|
if( toks.size()==0 )
|
|
return;
|
|
|
|
if( toks.size()>1 )
|
|
{
|
|
for(size_t i=0;i<toks.size()-1;++i)
|
|
{
|
|
ct=ct->getObject(toks[i]);
|
|
if( ct==NULL )
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( ct!=NULL )
|
|
ct->addString(toks[toks.size()-1], value);
|
|
}
|
|
|
|
ITable *CTemplate::findTable(std::string key)
|
|
{
|
|
std::vector<std::string> toks;
|
|
Tokenize(key, toks, ".");
|
|
ITable *ct;
|
|
|
|
if( toks.size()>0 )
|
|
{
|
|
ct=mCurrValues->getObject(toks[0]);
|
|
if( ct==NULL && mValuesRoot!=mCurrValues )
|
|
{
|
|
ct=mValuesRoot->getObject(toks[0]);
|
|
}
|
|
|
|
for(size_t i=1;i<toks.size() && ct!=NULL;++i)
|
|
{
|
|
ct=ct->getObject(toks[i]);
|
|
}
|
|
|
|
return ct;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
bool CTemplate::FindValue(const std::string &key, std::string &value, bool dbs)
|
|
{
|
|
ITable *val=findTable(key);
|
|
|
|
if( val!=NULL )
|
|
{
|
|
value=val->getValue();
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
if( dbs==false )
|
|
return false;
|
|
else
|
|
{
|
|
for(size_t i=0;i<mTables.size();++i)
|
|
{
|
|
mTables[i].second->Bind(key);
|
|
db_results res=mTables[i].second->Read();
|
|
mTables[i].second->Reset();
|
|
|
|
if( res.size() >0 )
|
|
{
|
|
db_single_result result=res[0];
|
|
db_single_result::iterator iter=result.find("value");
|
|
if( iter!= result.end() )
|
|
{
|
|
value=iter->second;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
std::string CTemplate::getData(void)
|
|
{
|
|
std::string output=data;
|
|
transform(output);
|
|
return output;
|
|
}
|
|
|
|
void CTemplate::transform(std::string &output)
|
|
{
|
|
for(size_t i=0;i<output.size();++i)
|
|
{
|
|
if( output[i]=='\n' && i!=0 && output[i-1]!='\r' )
|
|
{
|
|
output.insert(i,"\r");
|
|
}
|
|
}
|
|
|
|
bool retry=true;
|
|
while(retry==true)
|
|
{
|
|
retry=false;
|
|
for(size_t i=0;i<output.size();++i)
|
|
{
|
|
// VALUES
|
|
if( next(output, i, "#{")==true )
|
|
{
|
|
size_t j;
|
|
for(j=i+2;j<output.size();++j)
|
|
{
|
|
if( output[j]=='}' )
|
|
break;
|
|
}
|
|
|
|
std::string var=output.substr(i+2, (j)-(i+2) );
|
|
std::string value;
|
|
|
|
bool b=FindValue( var, value);
|
|
if( b==true )
|
|
{
|
|
output.replace(i, j-i+1, value );
|
|
}
|
|
else
|
|
{
|
|
|
|
}
|
|
}
|
|
//PREPROCESSOR
|
|
{
|
|
if( ((i==0||i==1) && next(output, i, "#exit" )) || (i!=0 && next(output, i, "\n#exit")) )
|
|
{
|
|
output.erase(i);
|
|
break;
|
|
}
|
|
bool foreach1=false,foreach2=false;
|
|
if( ((i==0||i==1) && (foreach1=next(output, i, "#foreach in ")==true)) || (foreach2=next(output, i, "\r\n#foreach in "))==true)
|
|
{
|
|
if( foreach2 )
|
|
i+=2;
|
|
std::string var;
|
|
for(size_t j=i+12;j<output.size();++j)
|
|
{
|
|
if( output[j]=='\n' || output[j]=='\r' )
|
|
break;
|
|
|
|
var+=output[j];
|
|
}
|
|
|
|
ITable *tab=findTable(var);
|
|
|
|
if( tab!=NULL )
|
|
{
|
|
size_t len=12+var.size();
|
|
|
|
size_t end=std::string::npos;
|
|
int count=0;
|
|
for(size_t j=i+len;j<output.size();++j)
|
|
{
|
|
if( next(output, j, "\r\n#foreach") )
|
|
{
|
|
++count;
|
|
}
|
|
if( next(output, j, "\r\n#endfor" ) )
|
|
{
|
|
if( count<=0 )
|
|
{
|
|
end=j;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
--count;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if( foreach2 )
|
|
{
|
|
len+=2;
|
|
i-=2;
|
|
}
|
|
|
|
if( end!=std::string::npos )
|
|
{
|
|
std::string mid=output.substr(i+len, end-(i+len));
|
|
std::string strend=output.substr(end+9);
|
|
output=output.substr(0,i);
|
|
ITable *old_values=mCurrValues;
|
|
|
|
for(size_t k=0;k<tab->getSize();++k)
|
|
{
|
|
std::string tmp=mid;
|
|
mCurrValues=tab->getObject(k);
|
|
transform(tmp);
|
|
output+=tmp;
|
|
}
|
|
|
|
mCurrValues=old_values;
|
|
|
|
i=output.size()-1;
|
|
output+=strend;
|
|
}
|
|
}
|
|
}
|
|
bool ifndef1=false,ifndef2=false;
|
|
bool next2=false;
|
|
if( ((i==0||i==1) && next(output, i, "#ifdef ")==true) || (next2=next(output, i, "\r\n#ifdef "))==true
|
|
||((i==0||i==1) && (ifndef1=next(output, i, "#ifndef "))==true) || ((ifndef2=next(output, i, "\r\n#ifndef "))==true)
|
|
)
|
|
{
|
|
bool ifndef=false;
|
|
if( ifndef1 || ifndef2 )
|
|
ifndef=true;
|
|
|
|
if( next2==true||ifndef2==true )
|
|
i+=2;
|
|
|
|
std::string var;
|
|
int addi=7;
|
|
if( ifndef==true )
|
|
++addi;
|
|
for(size_t j=i+addi;j<output.size();++j)
|
|
{
|
|
if( output[j]=='\n' || output[j]=='\r' )
|
|
break;
|
|
|
|
var+=output[j];
|
|
}
|
|
|
|
std::string value;
|
|
|
|
bool found=FindValue(var, value);
|
|
|
|
if( ifndef==true )
|
|
found=!found;
|
|
|
|
if( found==true )
|
|
{
|
|
if(i!=0)
|
|
i-=2;
|
|
|
|
output.erase(i,addi+var.size()+2 );
|
|
|
|
size_t j;
|
|
size_t todel=std::string::npos;
|
|
size_t proc=0;
|
|
for(j=i;j<output.size();++j)
|
|
{
|
|
if( next(output, j , "\r\n#ifdef") || next(output, j , "\r\n#ifndef") )
|
|
{
|
|
++proc;
|
|
}
|
|
else if( proc==0 && next(output, j, "\r\n#elseif" ) )
|
|
{
|
|
if( todel==std::string::npos )
|
|
todel=j;
|
|
}
|
|
else if( proc==0 && next(output, j, "\r\n#else" ) )
|
|
{
|
|
if( todel==std::string::npos )
|
|
todel=j;
|
|
}
|
|
else if( next(output, j, "\r\n#endif" ) )
|
|
{
|
|
if( proc!=0 )
|
|
{
|
|
--proc;
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
}
|
|
//Not tested...
|
|
if( i>0 )--i;
|
|
output.erase(j, 8);
|
|
if( todel!=std::string::npos )
|
|
output.erase(todel, j-todel);
|
|
}
|
|
else
|
|
{
|
|
size_t todel=0;
|
|
size_t enterelseif=std::string::npos;
|
|
size_t stopelseif=std::string::npos;
|
|
size_t proc=0;
|
|
for(size_t j=i;j<output.size();++j)
|
|
{
|
|
if( next(output, j , "\r\n#ifdef") || next(output, j , "\r\n#ifndef") )
|
|
{
|
|
++proc;
|
|
}
|
|
else if( proc==0 && next(output, j , "\r\n#elseif" ) )
|
|
{
|
|
std::string key;
|
|
for(size_t k=j+10;k<output.size();++k)
|
|
{
|
|
if( output[k]=='\r' || output[k]=='\n' )
|
|
break;
|
|
key+=output[k];
|
|
}
|
|
if( enterelseif==std::string::npos )
|
|
{
|
|
std::string value;
|
|
if( FindValue( key, value) )
|
|
{
|
|
enterelseif=j;
|
|
}
|
|
}
|
|
else if(stopelseif==std::string::npos )
|
|
{
|
|
stopelseif=j;
|
|
}
|
|
output.erase(j, 10+key.size() );
|
|
}
|
|
else if( proc==0 &&next(output, j, "\r\n#else") )
|
|
{
|
|
if( enterelseif==std::string::npos )
|
|
{
|
|
enterelseif=j;
|
|
}
|
|
else if( stopelseif==std::string::npos )
|
|
stopelseif=j;
|
|
|
|
output.erase(j, 7 );
|
|
--j;
|
|
if( todel>0 )
|
|
todel--;
|
|
}
|
|
else if( next(output, j, "\r\n#endif" ) )
|
|
{
|
|
if( proc!=0 )
|
|
--proc;
|
|
else
|
|
{
|
|
if( enterelseif!=std::string::npos )
|
|
if( stopelseif==std::string::npos )
|
|
stopelseif=j;
|
|
break;
|
|
}
|
|
}
|
|
++todel;
|
|
}
|
|
std::string data;
|
|
if( enterelseif!=std::string::npos )
|
|
data=output.substr(enterelseif, stopelseif-enterelseif);
|
|
if( i==0 && data.size()>1 )
|
|
data.erase(0,2);
|
|
if( i!=0 )
|
|
{
|
|
i-=2;
|
|
todel+=2;
|
|
}
|
|
output.erase(i, todel+8);
|
|
if( data.size()>0 )
|
|
{
|
|
output.insert(i, data);
|
|
}
|
|
if( i>0 )
|
|
--i;
|
|
else
|
|
{
|
|
retry=true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if( next(output, i, "#include \"")==true )
|
|
{
|
|
std::string fn;
|
|
bool inside=false;
|
|
for(size_t j=i;j<output.size();++j)
|
|
{
|
|
if( output[j]=='"' && inside==true )
|
|
break;
|
|
else if(output[j]=='"')
|
|
inside=true;
|
|
else if( inside==true )
|
|
fn+=output[j];
|
|
}
|
|
|
|
output.erase(i,11+fn.size() );
|
|
std::string ttext=getFile(ExtractFilePath(file)+"/"+fn );
|
|
transform(ttext);
|
|
output.insert(i, ttext );
|
|
}
|
|
}
|
|
//REPLACEMENTS
|
|
for( size_t j=0;j<mReplacements.size();++j)
|
|
{
|
|
if( next(output, i, mReplacements[j].first)==true )
|
|
{
|
|
output.erase(i, mReplacements[j].first.size() );
|
|
output.insert(i, mReplacements[j].second );
|
|
i+=mReplacements[j].second.size();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CTemplate::Reset(void)
|
|
{
|
|
delete mValuesRoot;
|
|
mCurrValues=new CTable();
|
|
mValuesRoot=mCurrValues;
|
|
}
|
|
|
|
void CTemplate::addValueTable( IDatabase* db, const std::string &table)
|
|
{
|
|
mTables.push_back( std::pair< IDatabase*, IQuery*>(db, db->Prepare("SELECT * FROM "+table+" WHERE key=?",false) ) );
|
|
}
|