/*************************************************************************
* 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 .
**************************************************************************/
#include "filelist_utils.h"
#include "../Interface/Server.h"
#include "../stringtools.h"
void writeFileRepeat(IFile *f, const char *buf, size_t bsize)
{
_u32 written=0;
do
{
_u32 rc=f->Write(buf+written, (_u32)(bsize-written));
written+=rc;
if(rc==0)
{
Server->Log("Failed to write to file "+f->getFilename()+" retrying... "+os_last_error_str(), LL_WARNING);
Server->wait(10000);
}
}
while(written* extra )
{
++pos;
switch(state)
{
case ParseState_Type:
if(ch=='f')
{
data.isdir=false;
state=ParseState_Quote;
}
else if(ch=='d')
{
data.isdir=true;
state=ParseState_Quote;
}
else if(ch=='u')
{
data.isdir=true;
state=ParseState_TypeFinish;
}
else
{
Server->Log("Error parsing file BackupServerGet::getNextEntry - 1. Unexpected char '"+std::string(1, ch)+"' at pos "+convert(pos-1)+". Expected 'f', 'd' or 'u'.", LL_ERROR);
}
break;
case ParseState_TypeFinish:
if(ch=='\n')
{
data.name="..";
data.last_modified=0;
data.size = 0;
reset();
if(extra!=NULL)
{
extra->clear();
}
return true;
}
else
{
Server->Log("Error parsing file BackupServerGet::getNextEntry - 2. Unexpected char '" + std::string(1, ch) + "'at pos " + convert(pos-1)+". Expected '\\n'.", LL_ERROR);
}
break;
case ParseState_Quote:
//"
state=ParseState_Name;
break;
case ParseState_NameFinish:
if(ch!='"')
{
t_name.erase(t_name.size()-1,1);
data.name=(t_name);
t_name="";
if(data.isdir && data.name=="..")
{
data.last_modified=0;
data.size = 0;
if(ch=='\n')
{
reset();
if(extra!=NULL)
{
extra->clear();
}
return true;
}
else
{
state=ParseState_ExtraParams;
return false;
}
}
else if(data.isdir && ch=='\n')
{
data.last_modified=0;
data.size = 0;
reset();
if(extra!=NULL)
{
extra->clear();
}
return true;
}
else
{
state=ParseState_Filesize;
return false;
}
}
//fallthrough
case ParseState_Name:
if(state==ParseState_Name && ch=='"')
{
state=ParseState_NameFinish;
}
else if(state==ParseState_Name && ch=='\\')
{
state=ParseState_NameEscape;
break;
}
else if(state==ParseState_NameFinish)
{
state=ParseState_Name;
}
t_name+=ch;
break;
case ParseState_NameEscape:
if(ch!='"' && ch!='\\')
{
t_name+='\\';
}
t_name+=ch;
state=ParseState_Name;
break;
case ParseState_Filesize:
if(ch!=' ')
{
t_name+=ch;
}
else
{
data.size=os_atoi64(t_name);
t_name="";
state=ParseState_ModifiedTime;
}
break;
case ParseState_ModifiedTime:
if(ch!='\n' && ch!='#')
{
t_name+=ch;
}
else
{
data.last_modified=os_atoi64(t_name);
if(ch=='\n')
{
reset();
if(extra!=NULL)
{
extra->clear();
}
return true;
}
else
{
t_name="";
state=ParseState_ExtraParams;
}
}
break;
case ParseState_ExtraParams:
if(ch!='\n')
{
t_name+=ch;
}
else
{
if(extra!=NULL)
{
extra->clear();
ParseParamStrHttp(t_name, extra, false);
}
reset();
return true;
}
break;
}
return false;
}
void FileListParser::reset( void )
{
t_name="";
state=ParseState_Type;
pos = 0;
}
FileListParser::FileListParser()
: state(ParseState_Type), pos(0)
{
}