コード例 #1
0
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
	}
}
コード例 #2
0
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;
}
コード例 #3
0
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;
}
コード例 #4
0
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;
	}
}
コード例 #5
0
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);
}
コード例 #6
0
CMutex::~CMutex(void)
{
	int rc;
	if( (rc=pthread_mutex_destroy(&ptmutex))!=0)
	{
		Server->Log("Error destroying mutex rc="+nconvert(rc), LL_ERROR);
	}
}
コード例 #7
0
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;
}
コード例 #8
0
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;
}
コード例 #9
0
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'");
	}
}
コード例 #10
0
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;
}
コード例 #11
0
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;
}
コード例 #12
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);
}
コード例 #13
0
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;
}
コード例 #14
0
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;
	}
}
コード例 #15
0
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();
	}
}
コード例 #16
0
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;
}
コード例 #17
0
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);
		}
	}
}
コード例 #18
0
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;
}
コード例 #19
0
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
}
コード例 #20
0
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);
}
コード例 #21
0
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;
}
コード例 #22
0
ファイル: server.cpp プロジェクト: Averroes/urbackup_backend
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;
		}
	}
}
コード例 #23
0
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);
				}
			}
		}
	}
}