/************************************************************************* * 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) { }