void CClientThread::EnableNagle(void) { if(has_socket) { #ifdef DISABLE_NAGLE #ifdef _WIN32 BOOL opt=FALSE; int err=setsockopt(int_socket,IPPROTO_TCP, TCP_NODELAY, (char*)&opt, sizeof(BOOL) ); if( err==SOCKET_ERROR ) Log("Error: Setting TCP_NODELAY=FALSE failed", LL_WARNING); #else static bool once=true; if( once==true ) { once=false; int opt=1; int err=setsockopt(int_socket, IPPROTO_TCP, TCP_CORK, (char*)&opt, sizeof(int) ); if( err==SOCKET_ERROR ) { Log("Error: Setting TCP_CORK failed. errno: "+nconvert(errno), LL_WARNING); } } #endif #endif } }
CClientThread::CClientThread(SOCKET pSocket, CTCPFileServ* pParent) { int_socket=pSocket; DisableNagle(); stopped=false; killable=false; has_socket=true; parent=pParent; #ifdef _WIN32 bufmgr=new CBufMgr(NBUFFERS,READSIZE); #else bufmgr=NULL; #endif hFile=0; #ifdef _WIN32 int window_size; int window_size_len=sizeof(window_size); getsockopt(pSocket, SOL_SOCKET, SO_SNDBUF,(char *) &window_size, &window_size_len ); Log("Info: Window size="+nconvert(window_size)); #endif close_the_socket=true; errcount=0; clientpipe=Server->PipeFromSocket(pSocket); mutex=NULL; cond=NULL; state=CS_NONE; update_file=NULL; chunk_send_thread_ticket=ILLEGAL_THREADPOOL_TICKET; }
void ServerPingThread::operator()(void) { unsigned int last_ping_ok=Server->getTimeMS(); while(stop==false) { //Server->Log("Sending ping running...", LL_DEBUG); if(server_get->sendClientMessage("PING RUNNING -"+nconvert(server_get->getPCDone())+"-#token="+server_token, "OK", L"Error sending 'running' ping to client", 30000, false, LL_DEBUG)) { last_ping_ok=Server->getTimeMS(); } //Server->Log("Done sending ping running.", LL_DEBUG); if(Server->getTimeMS()-last_ping_ok>ping_intervall*6) { is_timeout=true; } else { is_timeout=false; } Server->wait(ping_intervall); } Server->wait(1000); delete this; }
void CClientThread::ReadFilePart(HANDLE hFile, const _i64 &offset,const bool &last) { LPOVERLAPPED overlap=new OVERLAPPED; //memset(overlap, 0, sizeof(OVERLAPPED) ); overlap->Offset=(DWORD)offset; overlap->OffsetHigh=(DWORD)(offset>>32); SLPData *ldata=new SLPData; ldata->buffer=bufmgr->getBuffer(); if( ldata->buffer==NULL ) { Log("Error: No Free Buffer", LL_DEBUG); Log("Info: Free Buffers="+nconvert(bufmgr->nfreeBufffer()), LL_DEBUG ); return; } ldata->t_send=&t_send; ldata->t_unsend=&t_unsend; ldata->last=last; ldata->filepart=currfilepart; ldata->sendfilepart=&sendfilepart; overlap->hEvent=ldata; BOOL b=ReadFileEx(hFile, ldata->buffer, READSIZE, overlap, FileIOCompletionRoutine); ++currfilepart; if( /*GetLastError() != ERROR_SUCCESS ||*/ b==false) { Log("Error: Can't start reading from File", LL_DEBUG); return; } }
void saveClientSettings(SClientSettings settings, IDatabase *db, int clientid) { IQuery *q_get=db->Prepare("SELECT value FROM settings_db.settings WHERE clientid="+nconvert(clientid)+" AND key=?"); IQuery *q_update=db->Prepare("UPDATE settings_db.settings SET value=? WHERE key=? AND clientid="+nconvert(clientid)); IQuery *q_insert=db->Prepare("INSERT INTO settings_db.settings (key, value, clientid) VALUES (?,?,"+nconvert(clientid)+")"); updateSetting(L"overwrite", settings.overwrite?L"true":L"false", q_get, q_update, q_insert); }
CMutex::~CMutex(void) { int rc; if( (rc=pthread_mutex_destroy(&ptmutex))!=0) { Server->Log("Error destroying mutex rc="+nconvert(rc), LL_ERROR); } }
std::vector<SLogLine> Connector::getLogdata(int logid, int loglevel) { std::string d=getResponse("GET LOGDATA","logid="+nconvert(logid)+"&loglevel="+nconvert(loglevel)); std::vector<std::string> lines; TokenizeMail(d, lines, "\n"); std::vector<SLogLine> ret; for(size_t i=0; i<lines.size(); ++i) { std::string l=lines[i]; if(l.empty())continue; SLogLine ll; ll.loglevel=atoi(getuntil("-", l).c_str()); ll.msg=wxString::FromUTF8(getafter("-", l).c_str()); ret.push_back(ll); } return ret; }
bool os_link_symbolic_junctions(const std::wstring &target, const std::wstring &lname) { bool ret=false; std::wstring wtarget=target; HANDLE hJunc=INVALID_HANDLE_VALUE; char *buf=NULL; if(wtarget.find(os_file_prefix(L""))==0) wtarget.erase(0, os_file_prefix(L"").size()); if(!wtarget.empty() && wtarget[0]!='\\') wtarget=L"\\??\\"+wtarget; if(!wtarget.empty() && wtarget[target.size()-1]!='\\') wtarget+=L"\\"; if(!CreateDirectoryW(lname.c_str(), NULL) ) { goto cleanup; } hJunc=CreateFileW(lname.c_str(), GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS, NULL); if(hJunc==INVALID_HANDLE_VALUE) goto cleanup; size_t bsize=sizeof(REPARSE_MOUNTPOINT_DATA_BUFFER) + (wtarget.size()+1) * sizeof(wchar_t)+30; buf=new char[bsize]; memset(buf, 0, bsize); REPARSE_MOUNTPOINT_DATA_BUFFER *rb=(REPARSE_MOUNTPOINT_DATA_BUFFER*)buf; rb->ReparseTag=IO_REPARSE_TAG_MOUNT_POINT; rb->ReparseTargetMaximumLength=(WORD)((wtarget.size()+1)*sizeof(wchar_t)); rb->ReparseTargetLength=rb->ReparseTargetMaximumLength-1*sizeof(wchar_t); rb->ReparseDataLength=rb->ReparseTargetLength+12; memcpy(rb->ReparseTarget, wtarget.c_str(), rb->ReparseTargetMaximumLength); DWORD bytes_ret; if(!DeviceIoControl(hJunc, FSCTL_SET_REPARSE_POINT, rb, rb->ReparseDataLength+REPARSE_MOUNTPOINT_HEADER_SIZE, NULL, 0, &bytes_ret, NULL) ) { goto cleanup; } ret=true; cleanup: if(!ret) { #ifndef OS_FUNC_NO_SERVER Server->Log("Creating junction failed. Last error="+nconvert((int)GetLastError()), LL_ERROR); #endif } delete []buf; if(hJunc!=INVALID_HANDLE_VALUE) CloseHandle(hJunc); if(!ret) { RemoveDirectoryW(lname.c_str()); } return ret; }
void updateArchiveSettings(int clientid, str_map &GET, IDatabase *db) { int i=0; IQuery *q=db->Prepare("DELETE FROM settings_db.automatic_archival WHERE clientid=?"); q->Bind(clientid); q->Write(); q=db->Prepare("INSERT INTO settings_db.automatic_archival (next_archival, interval, interval_unit, length, length_unit, backup_types, clientid, archive_window) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"); while(GET.find(L"archive_every_"+convert(i))!=GET.end()) { _i64 archive_next=watoi64(GET[L"archive_next_"+convert(i)]); int archive_every=watoi(GET[L"archive_every_"+convert(i)]); int archive_for=watoi(GET[L"archive_for_"+convert(i)]); std::wstring backup_type_str=GET[L"archive_backup_type_"+convert(i)]; int backup_types=ServerAutomaticArchive::getBackupTypes(backup_type_str); if(archive_next<0) { if(clientid==0) { q->Bind(0); } else { q->Bind(Server->getTimeSeconds()); } } else { q->Bind(archive_next); } q->Bind(archive_every); q->Bind(GET[L"archive_every_unit_"+convert(i)]); q->Bind(archive_for); q->Bind(GET[L"archive_for_unit_"+convert(i)]); q->Bind(backup_types); q->Bind(clientid); q->Bind(GET[L"archive_window_"+convert(i)]); q->Write(); q->Reset(); ++i; } IQuery *q_get=db->Prepare("SELECT value FROM settings_db.settings WHERE clientid="+nconvert(clientid)+" AND key=?"); if(clientid!=0) { IQuery *q_update=db->Prepare("UPDATE settings_db.settings SET value=? WHERE key=? AND clientid="+nconvert(clientid)); IQuery *q_insert=db->Prepare("INSERT INTO settings_db.settings (key, value, clientid) VALUES (?,?,"+nconvert(clientid)+")"); updateSetting(L"overwrite_archive_settings", L"true", q_get, q_update, q_insert); } else { db->Write("DELETE FROM settings_db.settings WHERE key='archive_settings_copied'"); } }
bool Connector::saveSharedPaths(const std::vector<SBackupDir> &res) { std::string args; for(size_t i=0; i<res.size(); ++i) { if(i!=0) args+="&"; args+="dir_"+nconvert(i)+"="+(std::string)res[i].path.ToUTF8().data(); args+="&dir_"+nconvert(i)+"_name="+(std::string)res[i].name.ToUTF8().data(); } std::string d=getResponse("SAVE BACKUP DIRS", args); if(d!="OK") return false; else return true; }
bool os_rename_file(std::wstring src, std::wstring dst) { DeleteFileW(dst.c_str()); BOOL rc=MoveFileW(src.c_str(), dst.c_str()); #ifdef _DEBUG if(rc==0) { Server->Log("MoveFileW error: "+nconvert((int)GetLastError()), LL_ERROR); } #endif return rc!=0; }
void getArchiveSettings(JSON::Object &obj, IDatabase *db, int clientid) { IQuery *q_get=db->Prepare("SELECT value FROM settings_db.settings WHERE clientid="+nconvert(clientid)+" AND key=?"); q_get->Bind("overwrite"); db_results res=q_get->Read(); q_get->Reset(); if(res.empty() || res[0][L"value"]!=L"true") clientid=0; q_get->Bind("overwrite_archive_settings"); res=q_get->Read(); if(res.empty() || res[0][L"value"]!=L"true") clientid=0; IQuery *q=db->Prepare("SELECT next_archival, interval, interval_unit, length, length_unit, backup_types FROM settings_db.automatic_archival WHERE clientid=?"); q->Bind(clientid); res=q->Read(); JSON::Array arr; for(size_t i=0;i<res.size();++i) { _i64 archive_next=watoi64(res[i][L"next_archival"]); JSON::Object ca; ca.set("next_archival", res[i][L"next_archival"]); ca.set("archive_every", watoi(res[i][L"interval"])); ca.set("archive_every_unit", res[i][L"interval_unit"]); ca.set("archive_for", watoi(res[i][L"length"])); ca.set("archive_for_unit", res[i][L"length_unit"]); ca.set("archive_backup_type", ServerAutomaticArchive::getBackupType(watoi(res[i][L"backup_types"]))); ca.set("archive_window", res[i][L"archive_window"]); if(archive_next>0 && clientid!=0) { _i64 tl=archive_next-(_i64)Server->getTimeSeconds(); ca.set("archive_timeleft", tl); } else { ca.set("archive_timeleft", "-"); } arr.add(ca); } obj.set("archive_settings", arr); }
ServerSettings::ServerSettings(IDatabase *db, int pClientid) : clientid(pClientid) { { IScopedLock lock(g_mutex); g_settings.push_back(this); } settings_default=Server->createDBSettingsReader(db, "settings", "SELECT value FROM settings_db.settings WHERE key=? AND clientid=0"); if(clientid!=-1) { settings_client=Server->createDBSettingsReader(db, "settings", "SELECT value FROM settings_db.settings WHERE key=? AND clientid="+nconvert(clientid)); } else { settings_client=NULL; } update(); do_update=false; }
int CClientThread::SendData(void) { if( t_send.size()==0 ) return 0; SSendData* ldata=t_send[0]; _i32 ret; ret=clientpipe->isWritable(CLIENT_TIMEOUT*1000)?1:0; if(ret < 1) { Log("Client Timeout occured.", LL_DEBUG); if( ldata->delbuf==true ) { bufmgr->releaseBuffer(ldata->delbufptr); ldata->delbuf=false; } t_send.erase( t_send.begin() ); delete ldata; return -1; } else { if( ldata->bsize>0 ) { unsigned int sent=0; while(sent<ldata->bsize) { _i32 ts; if(cmd_id==ID_GET_FILE_RESUME_HASH) ts=(std::min)((unsigned int)(next_checkpoint-sent_bytes), ldata->bsize-sent); else ts=ldata->bsize; _i32 rc=SendInt(&ldata->buffer[sent], ts); if( rc==SOCKET_ERROR ) { int err; #ifdef _WIN32 err=WSAGetLastError(); #else err=errno; #endif Log("SOCKET_ERROR in SendData(). BSize: "+nconvert(ldata->bsize)+" WSAGetLastError: "+nconvert(err), LL_DEBUG); if( ldata->delbuf==true ) { bufmgr->releaseBuffer(ldata->delbufptr); ldata->delbuf=false; } t_send.erase( t_send.begin() ); delete ldata; return -1; } else if(cmd_id==ID_GET_FILE_RESUME_HASH) { hash_func.update((unsigned char*)&ldata->buffer[sent], ts); } sent+=ts; sent_bytes+=ts; if(cmd_id==ID_GET_FILE_RESUME_HASH) { if(next_checkpoint-sent_bytes==0) { hash_func.finalize(); SendInt((char*)hash_func.raw_digest_int(), 16); next_checkpoint+=c_checkpoint_dist; if(next_checkpoint>curr_filesize) next_checkpoint=curr_filesize; hash_func.init(); } } } } else { Log("ldata is null", LL_DEBUG); } if( ldata->delbuf==true ) { bufmgr->releaseBuffer( ldata->delbufptr ); ldata->delbuf=false; } if( ldata->last==true ) { Log("Info: File End", LL_DEBUG); if( t_send.size() > 1 ) { Log("Error: Senddata exceeds 1", LL_DEBUG); } for(size_t i=0;i<t_send.size();++i) { if( t_send[i]->delbuf==true ) { bufmgr->releaseBuffer( t_send[i]->buffer ); } delete t_send[i]; } t_send.clear(); return 2; } t_send.erase( t_send.begin() ); delete ldata; return 1; } }
void ChangeJournalWatcher::update(bool force_write, std::wstring vol_str) { char buffer[BUF_LEN]; bool started_transaction=false; for(std::map<std::wstring, SChangeJournal>::iterator it=wdirs.begin();it!=wdirs.end();++it) { if(!vol_str.empty() && it->first!=vol_str) continue; if(!indexing_in_progress) { std::vector<UsnInt> jd=getJournalData(it->first); for(size_t i=0;i<jd.size();++i) { updateWithUsn(it->first, it->second, &jd[i]); it->second.last_record=jd[i].NextUsn; } deleteJournalData(it->first); } if(it->second.last_record_update) { if(started_transaction==false) { started_transaction=true; db->BeginTransaction(); } it->second.last_record_update=false; q_update_lastusn->Bind(it->second.last_record); q_update_lastusn->Bind(it->first); q_update_lastusn->Write(); q_update_lastusn->Reset(); } USN startUsn=it->second.last_record; unsigned int update_bytes=0; bool remove_it=false; bool c=true; while(c) { c=false; READ_USN_JOURNAL_DATA data; data.StartUsn=it->second.last_record; data.ReasonMask=0xFFFFFFFF;//USN_REASON_DATA_EXTEND|USN_REASON_BASIC_INFO_CHANGE|USN_REASON_DATA_OVERWRITE|USN_REASON_DATA_TRUNCATION|USN_REASON_EA_CHANGE|USN_REASON_FILE_CREATE|USN_REASON_FILE_DELETE|USN_REASON_HARD_LINK_CHANGE|USN_REASON_NAMED_DATA_EXTEND|USN_REASON_NAMED_DATA_OVERWRITE|USN_REASON_NAMED_DATA_TRUNCATION|USN_REASON_RENAME_NEW_NAME|USN_REASON_REPARSE_POINT_CHANGE|USN_REASON_SECURITY_CHANGE|USN_REASON_STREAM_CHANGE; data.ReturnOnlyOnClose=0; data.Timeout=0; data.BytesToWaitFor=0; data.UsnJournalID=it->second.journal_id; DWORD read; memset(buffer, 0, BUF_LEN); BOOL b=DeviceIoControl(it->second.hVolume, FSCTL_READ_USN_JOURNAL, &data, sizeof(READ_USN_JOURNAL_DATA), buffer, BUF_LEN, &read, NULL); if(b!=0) { DWORD dwRetBytes=read-sizeof(USN); PUSN_RECORD TUsnRecord = (PUSN_RECORD)(((PUCHAR)buffer) + sizeof(USN)); if(dwRetBytes>0) { c=true; } else if(update_bytes>5000) { update_bytes=0; /*q_update_lastusn->Bind(it->second.last_record); q_update_lastusn->Bind(it->first); q_update_lastusn->Write(); q_update_lastusn->Reset(); startUsn=it->second.last_record;*/ } USN nextUsn=*(USN *)&buffer; while(dwRetBytes>0) { std::string fn; fn.resize(TUsnRecord->FileNameLength); memcpy(&fn[0], (char*)TUsnRecord->FileName, TUsnRecord->FileNameLength); dwRetBytes-=TUsnRecord->RecordLength; update_bytes+=TUsnRecord->RecordLength; if(!indexing_in_progress) { UsnInt UsnRecord; UsnRecord.Filename=Server->ConvertFromUTF16(fn); UsnRecord.FileReferenceNumber=TUsnRecord->FileReferenceNumber; UsnRecord.ParentFileReferenceNumber=TUsnRecord->ParentFileReferenceNumber; UsnRecord.Reason=TUsnRecord->Reason; UsnRecord.Usn=TUsnRecord->Usn; UsnRecord.attributes=TUsnRecord->FileAttributes; if(UsnRecord.Filename!=L"backup_client.db" && UsnRecord.Filename!=L"backup_client.db-journal") { if(started_transaction==false) { started_transaction=true; db->BeginTransaction(); } updateWithUsn(it->first, it->second, &UsnRecord); } } else { if(fn!="backup_client.db" && fn!="backup_client.db-journal") { saveJournalData(it->second.journal_id, it->first, TUsnRecord, nextUsn); } } TUsnRecord = (PUSN_RECORD)(((PCHAR)TUsnRecord) + TUsnRecord->RecordLength); } it->second.last_record=nextUsn; } else { DWORD err=GetLastError(); if(err==ERROR_JOURNAL_ENTRY_DELETED) { Server->Log(L"Error for Volume '"+it->first+L"': Journal entry deleted", LL_ERROR); USN_JOURNAL_DATA data; DWORD r_bytes; BOOL bv=DeviceIoControl(it->second.hVolume, FSCTL_QUERY_USN_JOURNAL, NULL, 0, &data, sizeof(USN_JOURNAL_DATA), &r_bytes, NULL); if(indexing_in_progress==false) { if(bv!=0 ) { it->second.last_record=data.NextUsn; Server->Log(L"Reindexing Volume '"+it->first+L"'", LL_ERROR); if(started_transaction) { started_transaction=false; db->EndTransaction(); } reindex(it->second.rid, it->first, &it->second); return; } else if(indexing_in_progress==false) { Server->Log("Journal Data not acessible. Errorcode: "+nconvert((int)GetLastError()), LL_ERROR); has_error=true; error_dirs.push_back(it->first); } } else { if(indexing_volume==it->first) { Server->Log("Access error during indexing. Change journal too small?", LL_ERROR); has_error=true; error_dirs.push_back(it->first); } else { Server->Log("Journal Data deleted on nonindexing volume.", LL_ERROR); has_error=true; error_dirs.push_back(it->first); deleteJournalId(it->first); CloseHandle(it->second.hVolume); remove_it=true; } } listener->On_ResetAll(it->first); } else { Server->Log(L"Unknown error for Volume '"+it->first+L"' - update err="+convert((int)err), LL_ERROR); listener->On_ResetAll(it->first); deleteJournalId(it->first); has_error=true; CloseHandle(it->second.hVolume); remove_it=true; error_dirs.push_back(it->first); } } } if(startUsn!=it->second.last_record) { it->second.last_record_update=true; } if(force_write) { q_update_lastusn->Bind(it->second.last_record); q_update_lastusn->Bind(it->first); q_update_lastusn->Write(); q_update_lastusn->Reset(); } if(remove_it) { wdirs.erase(it); break; } } if(started_transaction) { db->EndTransaction(); } }
void MyTimer::Notify() { static bool working=false; if(working==true) { return; } if(Connector::isBusy()) { return; } working=true; wxStandardPaths sp; static wxString cfgDir=sp.GetUserDataDir(); static long starttime=wxGetLocalTime(); static long startuptime_passed=0; static long lastbackuptime=-5*60*1000; static long lastversioncheck=starttime; if(!wxDir::Exists(cfgDir) ) { wxFileName::Mkdir(cfgDir); } if(startuptime_passed==0) { startuptime_passed=atoi(getFile((cfgDir+wxT("/passedtime.cfg") ).ToUTF8().data() ).c_str() ); startuptime_passed+=atoi(getFile((cfgDir+wxT("/passedtime_new.cfg") ).ToUTF8().data() ).c_str() ); writestring(nconvert((int)startuptime_passed), (cfgDir+wxT("/passedtime.cfg") ).ToUTF8().data() ); lastbackuptime=atoi(getFile((cfgDir+wxT("/lastbackuptime.cfg") ).ToUTF8().data() ).c_str() ); if(lastbackuptime==0) lastbackuptime=-5*60*1000; std::string update_intv=getFile((cfgDir+wxT("/incr_updateintervall.cfg") ).ToUTF8().data() ); if(!update_intv.empty()) incr_update_intervall=atoi(update_intv.c_str()); } long ct=wxGetLocalTime(); if(ct-lastversioncheck>600 && !displayed_update_info) { std::string n_version=getFile("version.txt"); std::string c_version=getFile("curr_version.txt"); if(n_version.empty())n_version="0"; if(c_version.empty())c_version="0"; if( atoi(n_version.c_str())>atoi(c_version.c_str())) { #ifndef wxUSE_TASKBARICON_BALLOONS TaskBarBaloon *tbb=new TaskBarBaloon(_("UrBackup: Update verfügbar"), _("Eine neue Version von UrBackup ist verfügbar. Klicken Sie hier um diese zu installieren")); tbb->showBaloon(80000); #else tray->BalloonActionUpgrade(); tray->ShowBalloon(_("UrBackup: Update verfügbar"), _("Eine neue Version von UrBackup ist verfügbar. Klicken Sie hier um diese zu installieren"), 30000, wxICON_INFORMATION); displayed_update_info=true; #endif } ct=wxGetLocalTime(); lastversioncheck=ct; } long passed=( ct-starttime ); writestring(nconvert((int)passed), (cfgDir+wxT("/passedtime_new.cfg") ).ToUTF8().data() ); wxString status_text; SStatus status=Connector::getStatus(); if(Connector::hasError() ) { if(icon_type!=4) { last_status=_("Keine Verbindung zum Backupserver möglich"); if(tray!=NULL) tray->SetIcon(wxIcon(res_path+wxT("backup-bad.")+ico_ext, ico_type), last_status); icon_type=4; } working=false; return; } capa=status.capa; int last_icon_type=icon_type; bool refresh=false; if(status.status==wxT("DONE") ) { writestring(nconvert((int)startuptime_passed+(int)passed), (cfgDir+wxT("/lastbackuptime.cfg") ).ToUTF8().data() ); lastbackuptime=startuptime_passed+passed; icon_type=0; working_status=0; refresh=true; } else if(status.status==wxT("INCR") ) { status_text+=_("Inkrementelles Backup läuft. "); if(!status.pcdone.empty()) { status_text+=status.pcdone; status_text+=_("% fertig. "); } icon_type=1; working_status=1; } else if(status.status==wxT("FULL") ) { status_text+=_("Volles Backup läuft. "); if(!status.pcdone.empty()) { status_text+=status.pcdone; status_text+=_("% fertig. "); } icon_type=1; working_status=2; } else if(status.status==wxT("INCRI") ) { status_text+=_("Inkrementelles Image-Backup läuft. "); if(!status.pcdone.empty()) { status_text+=status.pcdone; status_text+=_("% fertig. "); } icon_type=1; working_status=3; } else if(status.status==wxT("FULLI") ) { status_text+=_("Volles Image-Backup läuft. "); if(!status.pcdone.empty()) { status_text+=status.pcdone; status_text+=_("% fertig. "); } icon_type=1; working_status=4; } else if(startuptime_passed+passed-(long)incr_update_intervall>lastbackuptime) { status_text+=_("Kein aktuelles Backup. "); icon_type=2; working_status=0; } else { icon_type=0; working_status=0; } if(!status.lastbackupdate.Trim().empty() ) status_text+=_("Letztes Backup am ")+status.lastbackupdate; if( icon_type<3 && incr_update_done==false) { unsigned int n_incr_update_intervall=Connector::getIncrUpdateIntervall(); if(!Connector::hasError() && n_incr_update_intervall!=0) { incr_update_done=true; incr_update_intervall=n_incr_update_intervall; writestring(nconvert(incr_update_intervall), (cfgDir+wxT("/incr_updateintervall.cfg") ).ToUTF8().data() ); } } if(status.pause && icon_type==1) { icon_type=3; } if(icon_type!=last_icon_type || last_status!=status_text || refresh) { last_status=status_text; switch(icon_type) { case 0: if(tray!=NULL) tray->SetIcon(wxIcon(res_path+wxT("backup-ok.")+ico_ext, ico_type), status_text); if(timer!=NULL) timer->Start(60000); break; case 1: if(tray!=NULL) tray->SetIcon(wxIcon(res_path+wxT("backup-progress.")+ico_ext, ico_type), status_text); if(timer!=NULL) timer->Start(10000); break; case 2: if(tray!=NULL) tray->SetIcon(wxIcon(res_path+wxT("backup-bad.")+ico_ext, ico_type), status_text); if(timer!=NULL) timer->Start(60000); break; case 3: if(tray!=NULL) tray->SetIcon(wxIcon(res_path+wxT("backup-progress-pause.")+ico_ext, ico_type), status_text); if(timer!=NULL) timer->Start(60000); } } if(!status.new_server.empty()) { #ifndef wxUSE_TASKBARICON_BALLOONS TaskBarBaloon *tbb=new TaskBarBaloon(_("UrBackup: Neuer Server"), _("Ein neuer Backup Server wurde gefunden. Hier klicken um diesen zu benutzen"), status.new_server); tbb->showBaloon(80000); #else tray->BalloonActionNewServer(status.new_server); tray->ShowBalloon(_("UrBackup: Neuer Server"), _("Ein neuer Backup Server wurde gefunden. Hier klicken um diesen zu benutzen"), 80000, wxICON_INFORMATION); #endif } working=false; }
void updateClientSettings(int t_clientid, str_map &GET, IDatabase *db) { IQuery *q_get=db->Prepare("SELECT value FROM settings_db.settings WHERE key=? AND clientid="+nconvert(t_clientid)); IQuery *q_update=db->Prepare("UPDATE settings_db.settings SET value=? WHERE key=? AND clientid="+nconvert(t_clientid)); IQuery *q_insert=db->Prepare("INSERT INTO settings_db.settings (key, value, clientid) VALUES (?,?,"+nconvert(t_clientid)+")"); std::vector<std::wstring> sset=getSettingsList(); sset.push_back(L"allow_overwrite"); for(size_t i=0;i<sset.size();++i) { str_map::iterator it=GET.find(sset[i]); if(it!=GET.end()) { updateSetting(sset[i], it->second, q_get, q_update, q_insert); } } }
bool UrlFactory::sendMail(const MailServer &server, const std::vector<std::string> &to, const std::string &subject, const std::string &message, std::string *errmsg) { CURL *curl=curl_easy_init(); std::string mailfrom=server.mailfrom; if(mailfrom.find("<")==std::string::npos) { mailfrom="<"+mailfrom+">"; } curl_easy_setopt(curl, CURLOPT_URL, ("smtp://"+server.servername+":"+nconvert(server.port)).c_str()); curl_easy_setopt(curl, CURLOPT_USE_SSL, server.ssl_only?CURLUSESSL_ALL:CURLUSESSL_TRY); if(!server.check_certificate) { curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0); } if(!server.username.empty()) { curl_easy_setopt(curl, CURLOPT_USERNAME, server.username.c_str()); curl_easy_setopt(curl, CURLOPT_PASSWORD, server.password.c_str()); } curl_easy_setopt(curl, CURLOPT_MAIL_FROM, mailfrom.c_str()); //curl_easy_setopt(curl, CURLOPT_VERBOSE, 1); curl_slist * recpt=NULL; for(size_t i=0;i<to.size();++i) { recpt=curl_slist_append(recpt, trim(to[i]).c_str()); } curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, recpt); curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback); RDUserS rd; std::string header; header+="From: "+mailfrom+"\r\n" "Subject: "+subject+"\r\n" "Date: "+format_time("%a, %d %b %Y %H:%M:%S %z")+"\r\n" "\r\n"; rd.text=header+message; curl_easy_setopt(curl, CURLOPT_READDATA, &rd); std::string errbuf; errbuf.resize(CURL_ERROR_SIZE*2); curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, (char*)errbuf.c_str()); CURLcode res= curl_easy_perform(curl); if(res!=0) { errbuf.resize(strlen(errbuf.c_str())); if(errmsg==NULL) { Server->Log("Error during cURL operation occured. ec="+nconvert(res)+" -- "+errbuf, LL_DEBUG); } else { *errmsg="ec="+nconvert(res)+" -- "+errbuf; } curl_slist_free_all(recpt); curl_easy_cleanup(curl); return false; } curl_slist_free_all(recpt); curl_easy_cleanup(curl); return true; }
std::wstring os_get_final_path(std::wstring path) { #if (_WIN32_WINNT >= 0x0600) std::wstring ret; if(path.find(L":")==std::string::npos) { path+=L":"; } if(path.find(L"\\")==std::string::npos) { path+=L"\\"; } HANDLE hFile = CreateFileW(path.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, NULL); if( hFile==INVALID_HANDLE_VALUE ) { #ifndef OS_FUNC_NO_SERVER Server->Log(L"Could not open path in os_get_final_path for \""+path+L"\"", LL_ERROR); #endif return path; } DWORD dwBufsize = GetFinalPathNameByHandleW( hFile, NULL, 0, VOLUME_NAME_DOS ); if(dwBufsize==0) { #ifndef OS_FUNC_NO_SERVER Server->Log(L"Error getting path size in in os_get_final_path error="+convert((int)GetLastError())+L" for \""+path+L"\"", LL_ERROR); #endif CloseHandle(hFile); return path; } ret.resize(dwBufsize+1); DWORD dwRet = GetFinalPathNameByHandleW( hFile, (LPWSTR)ret.c_str(), dwBufsize, VOLUME_NAME_DOS ); CloseHandle(hFile); if(dwRet==0) { #ifndef OS_FUNC_NO_SERVER Server->Log("Error getting path in in os_get_final_path error="+nconvert((int)GetLastError()), LL_ERROR); #endif } else if(dwRet<ret.size()) { ret.resize(dwRet); if(ret.find(L"\\\\?\\UNC")==0) { ret.erase(0, 7); ret=L"\\"+ret; } if(ret.find(L"\\\\?\\")==0) { ret.erase(0,4); } /*if(ret.size()>=2 && ret[ret.size()-2]=='.' && ret[ret.size()-1]=='.' ) { ret.resize(ret.size()-2); }*/ return ret; } else { #ifndef OS_FUNC_NO_SERVER Server->Log("Error getting path (buffer too small) in in os_get_final_path error="+nconvert((int)GetLastError()), LL_ERROR); #endif } return path; #else return path; #endif }
void CWorkerThread::ProcessRequest(CClient *client, FCGIRequest *req) { if( req->keep_connection ) { keep_alive=true; } else { keep_alive=false; } if( req->role != FCGIRequest::RESPONDER ) { Server->Log("Role ist not Responder", LL_ERROR); return; } str_map GET,POST; str_nmap::iterator iter=req->params.find("QUERY_STRING"); if( iter!=req->params.end() ) { for(size_t i=0,size=iter->second.size();i<size;++i) { if( iter->second[i]=='+' ) iter->second[i]=' '; } ParseParamStr(iter->second, &GET ); req->params.erase( iter ); } std::string ct=req->params["CONTENT_TYPE"]; std::string lct=ct; strlower(lct); bool postfile=false; POSTFILE_KEY pfkey; if(lct.find("multipart/form-data")==std::string::npos) { if( req->stdin_stream.size()>0 && req->stdin_stream.size()<1048576 ) { for(size_t i=0,size=req->stdin_stream.size();i<size;++i) { if( req->stdin_stream[i]=='+' ) req->stdin_stream[i]=' '; } ParseParamStr(req->stdin_stream, &POST ); } } else { std::string boundary=getafter("boundary=",ct); pfkey=ParseMultipartData(req->stdin_stream, boundary); req->params["POSTFILEKEY"]=nconvert(pfkey); postfile=true; } str_map::iterator iter2=GET.find(L"a"); if( iter2!=GET.end() ) { int starttime=Server->getTimeMS(); str_map::iterator iter3=GET.find(L"c"); std::wstring context; if( iter3!=GET.end() ) context=iter3->second; THREAD_ID tid=Server->Execute(iter2->second, context, GET, POST, req->params, req ); if( tid==0 ) { std::wstring error=L"Error: Unknown action ["+iter2->second+L"]"; Server->Log(error, LL_WARNING); req->write("Content-type: text/html; charset=UTF-8\r\n\r\n"+wnarrow(error)); } starttime=Server->getTimeMS()-starttime; Server->Log("Execution Time: "+nconvert(starttime)+" ms - time="+nconvert(Server->getTimeMS() ), LL_INFO); } else { std::string error="Error: Parameter 'action' not given."; req->write("Content-type: text/html; charset=UTF-8\r\n\r\n"+error); } if(postfile) { Server->clearPostFiles(pfkey); } req->end_request(0, FCGIRequest::REQUEST_COMPLETE); }
bool CClientThread::RecvMessage(void) { _i32 rc; timeval lon; lon.tv_usec=0; lon.tv_sec=60; rc=clientpipe->isReadable(lon.tv_sec*1000)?1:0; if(clientpipe->hasError()) rc=-1; if( rc==0 ) { if(state==CS_NONE) { Log("1 min Timeout deleting Buffers ("+nconvert((NBUFFERS*READSIZE)/1024 )+" KB) and waiting 1h more...", LL_DEBUG); delete bufmgr; bufmgr=NULL; lon.tv_sec=3600; int n=0; while(stopped==false && rc==0 && n<60) { rc=clientpipe->isReadable(lon.tv_sec*1000); if(clientpipe->hasError()) rc=-1; ++n; } } } if( rc<1) { Log("Select Error/Timeout in RecvMessage", LL_DEBUG); return false; } else { rc=(_i32)clientpipe->Read(buffer, BUFFERSIZE, lon.tv_sec*1000); if(rc<1) { Log("Recv Error in RecvMessage", LL_DEBUG); return false; } else { Log("Received data..."); stack.AddData(buffer, rc); } size_t packetsize; char* packet; while( (packet=stack.getPacket(&packetsize)) != NULL ) { Log("Received a Packet.", LL_DEBUG); CRData data(packet, packetsize); bool b=ProcessPacket( &data ); delete[] packet; if( b==false ) return false; } } return true; }
void BackupServer::startClients(FileClient &fc) { std::vector<std::wstring> names; std::vector<sockaddr_in> servers; if(!internet_test_mode) { names=fc.getServerNames(); servers=fc.getServers(); } for(size_t i=0;i<names.size();++i) { names[i]=Server->ConvertToUnicode(conv_filename(Server->ConvertToUTF8(names[i]))); } std::vector<bool> inetclient; inetclient.resize(names.size()); std::fill(inetclient.begin(), inetclient.end(), false); std::vector<std::string> anames=InternetServiceConnector::getOnlineClients(); for(size_t i=0;i<anames.size();++i) { std::wstring new_name=Server->ConvertToUnicode(conv_filename(anames[i])); bool skip=false; for(size_t j=0;j<names.size();++j) { if( new_name==names[j] ) { skip=true; break; } } if(skip) continue; names.push_back(new_name); inetclient.push_back(true); sockaddr_in n; memset(&n, 0, sizeof(sockaddr_in)); servers.push_back(n); } for(size_t i=0;i<names.size();++i) { std::map<std::wstring, SClient>::iterator it=clients.find(names[i]); if( it==clients.end() ) { Server->Log(L"New Backupclient: "+names[i]); ServerStatus::setOnline(names[i], true); IPipe *np=Server->createMemoryPipe(); bool use_reflink=false; #ifndef _WIN32 if(snapshots_enabled) use_reflink=true; #endif BackupServerGet *client=new BackupServerGet(np, servers[i], names[i], inetclient[i], snapshots_enabled, use_reflink); Server->getThreadPool()->execute(client); SClient c; c.pipe=np; c.offlinecount=0; c.addr=servers[i]; c.internet_connection=inetclient[i]; ServerStatus::setIP(names[i], c.addr.sin_addr.s_addr); clients.insert(std::pair<std::wstring, SClient>(names[i], c) ); } else if(it->second.offlinecount<max_offline) { bool found_lan=false; if(inetclient[i]==false && it->second.internet_connection==true) { found_lan=true; } if(it->second.addr.sin_addr.s_addr==servers[i].sin_addr.s_addr && !found_lan) { it->second.offlinecount=0; } else { bool none_fits=true; for(size_t j=0;j<names.size();++j) { if(i!=j && names[j]==names[i] && it->second.addr.sin_addr.s_addr==servers[j].sin_addr.s_addr) { none_fits=false; break; } } if(none_fits || found_lan) { it->second.addr=servers[i]; it->second.internet_connection=inetclient[i]; std::string msg; msg.resize(7+sizeof(sockaddr_in)+1); msg[0]='a'; msg[1]='d'; msg[2]='d'; msg[3]='r'; msg[4]='e'; msg[5]='s'; msg[6]='s'; memcpy(&msg[7], &it->second.addr, sizeof(sockaddr_in)); msg[7+sizeof(sockaddr_in)]=(inetclient[i]==true?1:0); it->second.pipe->Write(msg); char *ip=(char*)&it->second.addr.sin_addr.s_addr; Server->Log("New client address: "+nconvert((unsigned char)ip[0])+"."+nconvert((unsigned char)ip[1])+"."+nconvert((unsigned char)ip[2])+"."+nconvert((unsigned char)ip[3]), LL_INFO); ServerStatus::setIP(names[i], it->second.addr.sin_addr.s_addr); it->second.offlinecount=0; } } } } bool c=true; size_t maxi=0; while(c && !clients.empty()) { c=false; size_t i_c=0; for(std::map<std::wstring, SClient>::iterator it=clients.begin();it!=clients.end();++it) { bool found=false; for(size_t i=0;i<names.size();++i) { if( it->first==names[i] ) { found=true; break; } } if( found==false || it->second.offlinecount>max_offline) { if(it->second.offlinecount==max_offline) { Server->Log(L"Client exitet: "+it->first); it->second.pipe->Write("exit"); ++it->second.offlinecount; ServerStatus::setOnline(it->first, false); } else if(it->second.offlinecount>max_offline) { std::string msg; std::vector<std::string> msgs; while(it->second.pipe->Read(&msg,0)>0) { if(msg!="ok") { msgs.push_back(msg); } else { Server->Log(L"Client finished: "+it->first); ServerStatus::setDone(it->first, true); Server->destroy(it->second.pipe); clients.erase(it); maxi=i_c; c=true; break; } } if( c==false ) { for(size_t i=0;i<msgs.size();++i) { it->second.pipe->Write(msgs[i]); } } else { break; } } else if(i_c>=maxi) { SStatusAction s_action=ServerStatus::getStatus(it->first).statusaction; if(s_action==sa_none) { ++it->second.offlinecount; } } } ++i_c; } } }
void ServerAutomaticArchive::archiveBackups(void) { db_results res_clients=db->Read("SELECT id FROM clients"); for(size_t i=0;i<res_clients.size();++i) { int clientid=watoi(res_clients[i][L"id"]); int r_clientid=clientid; IQuery *q_get=db->Prepare("SELECT value FROM settings_db.settings WHERE clientid=? AND key=?"); q_get->Bind(clientid); q_get->Bind("overwrite"); db_results res=q_get->Read(); q_get->Reset(); if(res.empty() || res[0][L"value"]!=L"true") r_clientid=0; q_get->Bind(clientid); q_get->Bind("overwrite_archive_settings"); res=q_get->Read(); q_get->Reset(); if(res.empty() || res[0][L"value"]!=L"true") r_clientid=0; bool archive_settings_copied=false; q_get->Bind(clientid); q_get->Bind("archive_settings_copied"); res=q_get->Read(); if(!res.empty() && res[0][L"value"]==L"true") archive_settings_copied=true; if(r_clientid==0 && !archive_settings_copied) { copyArchiveSettings(clientid); } IQuery *q_get_archived=db->Prepare("SELECT id, next_archival, interval, length, backup_types, archive_window FROM settings_db.automatic_archival WHERE clientid=?"); q_get_archived->Bind(clientid); db_results res_archived=q_get_archived->Read(); for(size_t j=0;j<res_archived.size();++j) { _i64 next_archival=watoi64(res_archived[j][L"next_archival"]); std::wstring &archive_window=res_archived[j][L"archive_window"]; _i64 curr_time=Server->getTimeSeconds(); if(next_archival<curr_time && (archive_window.empty() || isInArchiveWindow(archive_window)) ) { int backupid=getNonArchivedFileBackup(watoi(res_archived[j][L"backup_types"]), clientid); if(backupid!=0) { int length=watoi(res_archived[j][L"length"]); archiveFileBackup(backupid, length); Server->Log("Archived file backup with id="+nconvert(backupid)+" for "+nconvert(length)+" seconds", LL_INFO); updateInterval(watoi(res_archived[j][L"id"]), watoi(res_archived[j][L"interval"])); } else { Server->Log("Did not find file backup suitable for archiving with backup_type="+nconvert(watoi(res_archived[j][L"backup_types"])), LL_INFO); } } } } }