Beispiel #1
0
void CServerList::AutoUpdate() 
{
	
	uint8 url_count = theApp->glob_prefs->adresses_list.GetCount();
	
	if (!url_count) {
		AddLogLineC(_("No server list address entry in 'addresses.dat' found. Please paste a valid server list address into this file in order to auto-update your server list"));
		return;
	}
	// Do current URL. Callback function will take care of the others.
	while ( current_url_index < url_count ) {
		wxString URI = theApp->glob_prefs->adresses_list[current_url_index];
		// We use wxURL to validate the URI
		if ( wxURL( URI ).GetError() == wxURL_NOERR ) {
			// Ok, got a valid URI
			m_URLUpdate = URI;
			wxString strTempFilename =
				theApp->ConfigDir + wxT("server_auto.met");
			AddLogLineC(CFormat(
				_("Start downloading server list from %s")) % URI);
			CHTTPDownloadThread *downloader = new CHTTPDownloadThread(
				URI, strTempFilename, theApp->ConfigDir + wxT("server.met"), HTTP_ServerMetAuto, false, false);
			downloader->Create();
			downloader->Run();
		
			return;
		} else {
			AddLogLineC(CFormat(
				_("WARNING: invalid URL specified for auto-updating of servers: %s") ) % URI);
		}
		current_url_index++;
	}
	AddLogLineC(_("No valid server.met auto-download url on addresses.dat"));
}
Beispiel #2
0
bool CDownloadQueue::IsFileExisting( const CMD4Hash& fileid ) const 
{
	if (CKnownFile* file = theApp->sharedfiles->GetFileByID(fileid)) {
		if (file->IsPartFile()) {
			AddLogLineC(CFormat( _("You are already trying to download the file '%s'") ) % file->GetFileName());
		} else {
			// Check if the file exists, since otherwise the user is forced to 
			// manually reload the shares to download a file again.
			CPath fullpath = file->GetFilePath().JoinPaths(file->GetFileName());
			if (!fullpath.FileExists()) {
				// The file is no longer available, unshare it
				theApp->sharedfiles->RemoveFile(file);
				
				return false;
			}
			
			AddLogLineC(CFormat( _("You already have the file '%s'") ) % file->GetFileName());
		}
		
		return true;
	} else if ((file = GetFileByID(fileid))) {
		AddLogLineC(CFormat( _("You are already trying to download the file %s") ) % file->GetFileName());
		return true;
	}
	
	return false;
}
Beispiel #3
0
bool CamuleDlg::Check_and_Init_Skin()
{
	bool ret = true;
	wxString skinFileName(thePrefs::GetSkin());

	if (skinFileName.IsEmpty() || skinFileName.IsSameAs(_("- default -"))) {
		return false;
	}

	wxString userDir(JoinPaths(GetConfigDir(), wxT("skins")) + wxFileName::GetPathSeparator());

	wxStandardPathsBase &spb(wxStandardPaths::Get());
#ifdef __WINDOWS__ 
	wxString dataDir(spb.GetPluginsDir());
#elif defined(__WXMAC__)
		wxString dataDir(spb.GetDataDir());
#else
	wxString dataDir(spb.GetDataDir().BeforeLast(wxT('/')) + wxT("/amule"));
#endif
	wxString systemDir(JoinPaths(dataDir,wxT("skins")) + wxFileName::GetPathSeparator());


	skinFileName.Replace(wxT("User:"******"System:"), systemDir );

	m_skinFileName.Assign(skinFileName);
	if (!m_skinFileName.FileExists()) {
		AddLogLineC(CFormat(
			_("Skin directory '%s' does not exist")) %
			skinFileName );
		ret = false;
	} else if (!m_skinFileName.IsFileReadable()) {
		AddLogLineC(CFormat(
			_("WARNING: Unable to open skin file '%s' for read")) %
			skinFileName);
		ret = false;
	}

	wxFFileInputStream in(m_skinFileName.GetFullPath());
	wxZipInputStream zip(in);
	wxZipEntry *entry;

	while ((entry = zip.GetNextEntry()) != NULL) {
		wxZipEntry*& current = cat[entry->GetInternalName()];
		delete current;
		current = entry;
	}

	return ret;
}
Beispiel #4
0
bool CKnownFileList::Init()
{
	CFile file;

	CPath fullpath = CPath(theApp->ConfigDir + m_filename);
	if (!fullpath.FileExists()) {
		// This is perfectly normal. The file was probably either
		// deleted, or this is the first time running aMule.
		return false;
	}

	if (!file.Open(fullpath)) {
		AddLogLineC(CFormat(_("WARNING: %s cannot be opened.")) % m_filename);
		return false;
	}

	try {
		uint8 version = file.ReadUInt8();
		if ((version != MET_HEADER) && (version != MET_HEADER_WITH_LARGEFILES)) {
			AddLogLineC(_("WARNING: Known file list corrupted, contains invalid header."));
			return false;
		}

		wxMutexLocker sLock(list_mut);
		uint32 RecordsNumber = file.ReadUInt32();
		AddDebugLogLineN(logKnownFiles, CFormat(wxT("Reading %i known files from file format 0x%2.2x."))
			% RecordsNumber % version);
		for (uint32 i = 0; i < RecordsNumber; i++) {
			CScopedPtr<CKnownFile> record;
			if (record->LoadFromFile(&file)) {
				AddDebugLogLineN(logKnownFiles,
					CFormat(wxT("Known file read: %s")) % record->GetFileName());
				Append(record.release());
			} else {
				AddLogLineC(_("Failed to load entry in known file list, file may be corrupt"));
			}
		}
		AddDebugLogLineN(logKnownFiles, wxT("Finished reading known files"));

		return true;
	} catch (const CInvalidPacket& e) {
		AddLogLineC(_("Invalid entry in known file list, file may be corrupt: ") + e.what());
	} catch (const CSafeIOException& e) {
		AddLogLineC(CFormat(_("IO error while reading %s file: %s")) % m_filename % e.what());
	}

	return false;
}
Beispiel #5
0
void CDownloadQueue::AddDownload(CPartFile* file, bool paused, uint8 category)
{
	wxCHECK_RET(!IsFileExisting(file->GetFileHash()), wxT("Adding duplicate part-file"));

	if (file->GetStatus(true) == PS_ALLOCATING) {
		file->PauseFile();
	} else if (paused && GetFileCount()) {
		file->StopFile();
	}

	{
		wxMutexLocker lock(m_mutex);
		m_filelist.push_back( file );
		DoSortByPriority();
	}

	NotifyObservers( EventType( EventType::INSERTED, file ) );
	if (category < theApp->glob_prefs->GetCatCount()) {
		file->SetCategory(category);
	} else {
		AddDebugLogLineN( logDownloadQueue, wxT("Tried to add download into invalid category.") );
	}
	Notify_DownloadCtrlAddFile( file );
	theApp->searchlist->UpdateSearchFileByHash(file->GetFileHash()); 	// Update file in the search dialog if it's still open
	AddLogLineC(CFormat(_("Downloading %s")) % file->GetFileName() );
}
Beispiel #6
0
void CIP2Country::DownloadFinished(uint32 result)
{
	if (result == HTTP_Success) {
		Disable();
		// download succeeded. Switch over to new database.
		wxString newDat = m_DataBasePath + wxT(".download");

		// Try to unpack the file, might be an archive
		wxWCharBuffer dataBaseName = m_DataBaseName.wc_str();
		const wxChar* geoip_files[] = {
			dataBaseName,
			NULL
		};

		if (UnpackArchive(CPath(newDat), geoip_files).second == EFT_Error) {
			AddLogLineC(_("Download of GeoIP.dat file failed, aborting update."));
			return;
		}

		if (wxFileExists(m_DataBasePath)) {
			if (!wxRemoveFile(m_DataBasePath)) {
				AddLogLineC(CFormat(_("Failed to remove %s file, aborting update.")) % m_DataBaseName);
				return;
			}
		}

		if (!wxRenameFile(newDat, m_DataBasePath)) {
			AddLogLineC(CFormat(_("Failed to rename %s file, aborting update.")) % m_DataBaseName);
			return;
		}

		Enable();
		if (m_geoip) {
			AddLogLineN(CFormat(_("Successfully updated %s")) % m_DataBaseName);
		} else {
			AddLogLineC(_("Error updating GeoIP.dat"));
		}
	} else if (result == HTTP_Skipped) {
		AddLogLineN(CFormat(_("Skipped download of %s, because requested file is not newer.")) % m_DataBaseName);
	} else {
		AddLogLineC(CFormat(_("Failed to download %s from %s")) % m_DataBaseName % thePrefs::GetGeoIPUpdateUrl());
		// if it failed and there is no database, turn it off
		if (!wxFileExists(m_DataBasePath)) {
			thePrefs::SetGeoIPEnabled(false);
		}
	}
}
Beispiel #7
0
void CDownloadQueue::AddSearchToDownload(CSearchFile* toadd, uint8 category)
{
	if ( IsFileExisting(toadd->GetFileHash()) ) {
		return;
	}

	if (toadd->GetFileSize() > OLD_MAX_FILE_SIZE) {
		if (!PlatformSpecific::CanFSHandleLargeFiles(thePrefs::GetTempDir())) {
			AddLogLineC(_("Filesystem for Temp directory cannot handle large files."));
			return;
		} else if (!PlatformSpecific::CanFSHandleLargeFiles(theApp->glob_prefs->GetCatPath(category))) {
			AddLogLineC(_("Filesystem for Incoming directory cannot handle large files."));
			return;
		}
	}

	CPartFile* newfile = NULL;
	try {
		newfile = new CPartFile(toadd);
	} catch (const CInvalidPacket& WXUNUSED(e)) {
		AddDebugLogLineC(logDownloadQueue, wxT("Search-result contained invalid tags, could not add"));
	}
	
	if ( newfile && newfile->GetStatus() != PS_ERROR ) {
		AddDownload( newfile, thePrefs::AddNewFilesPaused(), category );
		// Add any possible sources
		if (toadd->GetClientID() && toadd->GetClientPort()) {
			CMemFile sources(1+4+2);
			sources.WriteUInt8(1);
			sources.WriteUInt32(toadd->GetClientID());
			sources.WriteUInt16(toadd->GetClientPort());
			sources.Reset();
			newfile->AddSources(sources, toadd->GetClientServerIP(), toadd->GetClientServerPort(), SF_SEARCH_RESULT, false);
		}
		for (std::list<CSearchFile::ClientStruct>::const_iterator it = toadd->GetClients().begin(); it != toadd->GetClients().end(); ++it) {
			CMemFile sources(1+4+2);
			sources.WriteUInt8(1);
			sources.WriteUInt32(it->m_ip);
			sources.WriteUInt16(it->m_port);
			sources.Reset();
			newfile->AddSources(sources, it->m_serverIP, it->m_serverPort, SF_SEARCH_RESULT, false);
		}
	} else {
		delete newfile;
	}
}
Beispiel #8
0
bool CDownloadQueue::AddED2KLink( const CED2KFileLink* link, uint8 category )
{
	CPartFile* file = NULL;
	if (IsFileExisting(link->GetHashKey())) {
		// Must be a shared file if we are to add hashes or sources
		if ((file = GetFileByID(link->GetHashKey())) == NULL) {
			return false;
		}
	} else {
		if (link->GetSize() > OLD_MAX_FILE_SIZE) {
			if (!PlatformSpecific::CanFSHandleLargeFiles(thePrefs::GetTempDir())) {
				AddLogLineC(_("Filesystem for Temp directory cannot handle large files."));
				return false;
			} else if (!PlatformSpecific::CanFSHandleLargeFiles(theApp->glob_prefs->GetCatPath(category))) {
				AddLogLineC(_("Filesystem for Incoming directory cannot handle large files."));
				return false;
			}
		}

		file = new CPartFile(link);
	
		if (file->GetStatus() == PS_ERROR) {
			delete file;
			return false;
		}
		
		AddDownload(file, thePrefs::AddNewFilesPaused(), category);
	}
	
	if (link->HasValidAICHHash()) {
		CAICHHashSet* hashset = file->GetAICHHashset();
		
		if (!hashset->HasValidMasterHash() || (hashset->GetMasterHash() != link->GetAICHHash())) {
			hashset->SetMasterHash(link->GetAICHHash(), AICH_VERIFIED);
			hashset->FreeHashSet();
		}
	}
	
	const CED2KFileLink::CED2KLinkSourceList& list = link->m_sources;
	CED2KFileLink::CED2KLinkSourceList::const_iterator it = list.begin();
	for (; it != list.end(); ++it) {
		AddToResolve(link->GetHashKey(), it->addr, it->port, it->hash, it->cryptoptions);
	}

	return true;	
}
Beispiel #9
0
bool CDownloadQueue::AddLink( const wxString& link, uint8 category )
{
	wxString uri(link);

	if (link.compare(0, 7, wxT("magnet:")) == 0) {
		uri = CMagnetED2KConverter(link);
		if (uri.empty()) {
			AddLogLineC(CFormat(_("Cannot convert magnet link to eD2k: %s")) % link);
			return false;
		}
	}

	if (uri.compare(0, 7, wxT("ed2k://")) == 0) {
		return AddED2KLink(uri, category);
	} else {
		AddLogLineC(CFormat(_("Unknown protocol of link: %s")) % link);
		return false;
	}
}
Beispiel #10
0
void CServerList::UpdateServerMetFromURL(const wxString& strURL)
{
	if (strURL.Find(wxT("://")) == -1) {
		AddLogLineC(_("Invalid URL"));
		return;
	}
	m_URLUpdate = strURL;
	wxString strTempFilename(theApp->ConfigDir + wxT("server.met.download"));
	CHTTPDownloadThread *downloader = new CHTTPDownloadThread(strURL, strTempFilename, theApp->ConfigDir + wxT("server.met"), HTTP_ServerMet, false, false);
	downloader->Create();
	downloader->Run();
}
Beispiel #11
0
void CServerWnd::OnBnClickedAddserver(wxCommandEvent& WXUNUSED(evt))
{
	wxString servername = CastChild( IDC_SERVERNAME, wxTextCtrl )->GetValue();
	wxString serveraddr = CastChild( IDC_IPADDRESS, wxTextCtrl )->GetValue();
	long port = StrToULong( CastChild( IDC_SPORT, wxTextCtrl )->GetValue() );

	if ( serveraddr.IsEmpty() ) {
		AddLogLineC(_("Server not added: No IP or hostname specified."));
		return;
	}
	
	if ( port <= 0 || port > 65535 ) {
		AddLogLineC(_("Server not added: Invalid server-port specified."));
		return;
	}
  
	CServer* toadd = new CServer( port, serveraddr );
	toadd->SetListName( servername.IsEmpty() ? serveraddr : servername );
	
	if ( theApp->AddServer( toadd, true ) ) {
		CastChild( IDC_SERVERNAME, wxTextCtrl )->Clear();
		CastChild( IDC_IPADDRESS, wxTextCtrl )->Clear();
		CastChild( IDC_SPORT, wxTextCtrl )->Clear();
	} else {
		CServer* update = theApp->serverlist->GetServerByAddress(toadd->GetAddress(), toadd->GetPort());
		// See note on CServerList::AddServer
		if (update == NULL && toadd->GetIP() != 0) {
			update = theApp->serverlist->GetServerByIPTCP(toadd->GetIP(), toadd->GetPort());
		}		
		
		if ( update ) {
			update->SetListName(toadd->GetListName());
			serverlistctrl->RefreshServer(update);
		}
		delete toadd;
	}
	
	theApp->serverlist->SaveServerMet();
}
Beispiel #12
0
void CFriendList::StartChatSession(CFriend* Friend)
{
	if (Friend) {
		CUpDownClient* client = Friend->GetLinkedClient().GetClient();
		if (!client) {
			client = new CUpDownClient(Friend->GetPort(), Friend->GetIP(), 0, 0, 0, true, true);
			client->SetIP(Friend->GetIP());
			client->SetUserName(Friend->GetName());
			theApp->clientlist->AddClient(client);
			Friend->LinkClient(CCLIENTREF(client, wxT("CFriendList::StartChatSession")));
		}
	} else {
		AddLogLineC(_("CRITICAL - no client on StartChatSession"));
	}
	
}
Beispiel #13
0
void CKnownFileList::Save()
{
	CFile file(theApp->ConfigDir + m_filename, CFile::write_safe);
	if (!file.IsOpened()) {
		return;
	}

	wxMutexLocker sLock(list_mut);
	AddDebugLogLineN(logKnownFiles, CFormat(wxT("start saving %s")) % m_filename);

	try {
		// Kry - This is the version, but we don't know it till
		// we know if any largefile is saved. This allows the list
		// to be compatible with previous versions.
		bool bContainsAnyLargeFiles = false;
		file.WriteUInt8(0);

		file.WriteUInt32(m_knownFileMap.size() + m_duplicateFileList.size());

		// Duplicates handling. Duplicates needs to be saved first,
		// since it is the last entry that gets used.
		KnownFileList::iterator itDup = m_duplicateFileList.begin();
		for ( ; itDup != m_duplicateFileList.end(); ++itDup ) {
			(*itDup)->WriteToFile(&file);
			if ((*itDup)->IsLargeFile()) {
				bContainsAnyLargeFiles = true;
			}
		}

		CKnownFileMap::iterator it = m_knownFileMap.begin();
		for (; it != m_knownFileMap.end(); ++it) {
			it->second->WriteToFile(&file);
			if (it->second->IsLargeFile()) {
				bContainsAnyLargeFiles = true;
			}
		}

		file.Seek(0);
		file.WriteUInt8(bContainsAnyLargeFiles ? MET_HEADER_WITH_LARGEFILES : MET_HEADER);
		file.Close();
	} catch (const CIOFailureException& e) {
		AddLogLineC(CFormat(_("Error while saving %s file: %s")) % m_filename % e.what());
	}
	AddDebugLogLineN(logKnownFiles, CFormat(wxT("finished saving %s")) % m_filename);
}
Beispiel #14
0
void CIP2Country::LoadFlags()
{
	// Load data from xpm files
	for (int i = 0; i < flags::FLAGS_XPM_SIZE; ++i) {
		CountryData countrydata;
		countrydata.Name = wxString(flags::flagXPMCodeVector[i].code, wxConvISO8859_1);
		countrydata.Flag = wxImage(flags::flagXPMCodeVector[i].xpm);

		if (countrydata.Flag.IsOk()) {
			m_CountryDataMap[countrydata.Name] = countrydata;
		} else {
			AddLogLineC(CFormat(_("Failed to load country data for '%s'.")) % countrydata.Name);
			continue;
		}
	}

	AddDebugLogLineN(logGeneral, CFormat(wxT("Loaded %d flag bitmaps.")) % m_CountryDataMap.size());  // there's never just one - no plural needed
}
Beispiel #15
0
void CServerList::DownloadFinished(uint32 result) 
{
	if(result == HTTP_Success) {
		const CPath tempFilename = CPath(theApp->ConfigDir + wxT("server.met.download"));

		// curl succeeded. proceed with server.met loading
		LoadServerMet(tempFilename);
		SaveServerMet();

		// So, file is loaded and merged, and also saved
		CPath::RemoveFile(tempFilename);
		AddLogLineN(CFormat(_("Finished downloading the server list from %s")) % m_URLUpdate);
	} else if (result == HTTP_Skipped) {
		AddLogLineN(CFormat(_("Skipped download of %s, because requested file is not newer.")) % wxT("server.met"));
	} else {
		AddLogLineC(CFormat(_("Failed to download %s from %s")) % wxT("server.met") % m_URLUpdate);
	}
}
Beispiel #16
0
void CLoggerTarget::DoLogText(const wxString &msg)
{
	// prevent infinite recursion
	static bool recursion = false;
	if (recursion) {
		return;
	}
	recursion = true;

	// This is much simpler than manually handling all wx log-types.
	if (msg.StartsWith(_("ERROR: ")) || msg.StartsWith(_("WARNING: "))) {
		AddLogLineC(msg);
	} else {
		AddLogLineN(msg);
	}

	recursion = false;
}
Beispiel #17
0
void COScopeCtrl::PlotHistory(unsigned cntPoints, bool bShiftGraph, bool bRefresh)
{
	wxASSERT(graph_type != GRAPH_INVALID);

	if (graph_type != GRAPH_INVALID) {
		unsigned i;
		unsigned cntFilled;
		std::vector<float *> apf(nTrends);
		try {
			for (i = 0; i < nTrends; ++i) {
				apf[i] = new float[cntPoints];
			}
			double sFinal = (bStopped ? sLastTimestamp : -1.0);
			cntFilled = theApp->m_statistics->GetHistory(cntPoints, sLastPeriod, sFinal, apf, graph_type);
			if (cntFilled >1  ||  (bShiftGraph && cntFilled!=0)) {
				if (bShiftGraph) {  // delayed points - we have an fPrev
					ShiftGraph(cntFilled);
				} else {  // fresh graph, we need to preset fPrev, yPrev
					PlotData_t* ppds = pdsTrends;
					for(i=0; i<nTrends; ++i, ++ppds)
						ppds->yPrev = GetPlotY(ppds->fPrev = *(apf[i] + cntFilled - 1), ppds);
					cntFilled--;
				}
				DrawPoints(apf, cntFilled);
				if (bRefresh)
					Refresh(false);
			}
			for (i = 0; i < nTrends; ++i) {
				delete [] apf[i];
			}
		} catch(std::bad_alloc) {
			// Failed memory allocation
			AddLogLineC(wxString(
				wxT("Error: COScopeCtrl::PlotHistory: Insuficient memory, cntPoints == ")) <<
				cntPoints << wxT("."));
			for (i = 0; i < nTrends; ++i) {
				delete [] apf[i];
			}
		}
	} else {
		// No history (yet) for Kad.
	}
}
Beispiel #18
0
void CamuleDlg::OnBnConnect(wxCommandEvent& WXUNUSED(evt))
{

	bool disconnect = (theApp->IsConnectedED2K() || theApp->serverconnect->IsConnecting())
						#ifdef CLIENT_GUI
						|| theApp->IsConnectedKad()		// there's no Kad running state atm
						#else
						|| (Kademlia::CKademlia::IsRunning())
						#endif
						;
	if (thePrefs::GetNetworkED2K()) {
		if (disconnect) {
			//disconnect if currently connected
			if (theApp->serverconnect->IsConnecting()) {
				theApp->serverconnect->StopConnectionTry();
			} else {
				theApp->serverconnect->Disconnect();
			}
		} else {
			//connect if not currently connected
			AddLogLineC(_("Connecting"));
			theApp->serverconnect->ConnectToAnyServer();
		}
	} else {
		wxASSERT(!theApp->IsConnectedED2K());
	}

	// Connect Kad also
	if (thePrefs::GetNetworkKademlia()) {
		if( disconnect ) {
			theApp->StopKad();
		} else {
			theApp->StartKad();
		}
	} else {
		#ifndef CLIENT_GUI
			wxASSERT(!Kademlia::CKademlia::IsRunning());
		#endif
	}

	ShowConnectionState();
}
Beispiel #19
0
bool CDownloadQueue::AddED2KLink( const wxString& link, uint8 category )
{
	wxASSERT( !link.IsEmpty() );
	wxString URI = link;
	
	// Need the links to end with /, otherwise CreateLinkFromUrl crashes us.
	if ( URI.Last() != wxT('/') ) {
		URI += wxT("/");
	}
	
	try {
		CScopedPtr<CED2KLink> uri(CED2KLink::CreateLinkFromUrl(URI));

		return AddED2KLink( uri.get(), category );
	} catch ( const wxString& err ) {
		AddLogLineC(CFormat( _("Invalid eD2k link! ERROR: %s")) % err);
	}
	
	return false;
}
Beispiel #20
0
void CServerList::FilterServers()
{
	CInternalList::iterator it = m_servers.begin();
	while (it != m_servers.end()) {
		CServer* server = *it++;

		if (server->HasDynIP()) {
			continue;
		}
		
		if (theApp->ipfilter->IsFiltered(server->GetIP(), true)) {
			if (server == theApp->serverconnect->GetCurrentServer()) {
				AddLogLineC(_("Local server is filtered by the IPFilters, reconnecting to a different server!"));
				theApp->serverconnect->Disconnect();
				RemoveServer(server);
				theApp->serverconnect->ConnectToAnyServer();
			} else {
				RemoveServer(server);
			}			
		}
	}
}
Beispiel #21
0
void CServerList::AutoDownloadFinished(uint32 result) 
{
	if (result == HTTP_Success) {
		CPath tempFilename = CPath(theApp->ConfigDir + wxT("server_auto.met"));
		
		// curl succeeded. proceed with server.met loading
		LoadServerMet(tempFilename);
		SaveServerMet();
		
		// So, file is loaded and merged, and also saved
		CPath::RemoveFile(tempFilename);
	} else {
		AddLogLineC(CFormat(_("Failed to download the server list from %s") ) % m_URLUpdate);
	}
	
	++current_url_index;
	
	if (current_url_index < theApp->glob_prefs->adresses_list.GetCount()) {		
		// Next!	
		AutoUpdate();
	}
}
Beispiel #22
0
void CLoggerTarget::DoLogString(const wxChar* msg, time_t)
{
	// prevent infinite recursion
	static bool recursion = false;
	if (recursion) {
		return;
	}
	recursion = true;

	wxCHECK_RET(msg, wxT("Log message is NULL in DoLogString!"));
	
	wxString str(msg);
	
	// This is much simpler than manually handling all wx log-types.
	if (str.StartsWith(_("ERROR: ")) || str.StartsWith(_("WARNING: "))) {
		AddLogLineC(str);
	} else {
		AddLogLineN(str);
	}

	recursion = false;
}
Beispiel #23
0
bool CServerList::AddServer(CServer* in_server, bool fromUser)
{
	if ( !in_server->GetPort() ) {
		if ( fromUser ) {
			AddLogLineC(CFormat( _("Server not added: [%s:%d] does not specify a valid port.") )
					% in_server->GetAddress()
					% in_server->GetPort()
			);
		}

		return false;
	} else if (
				!in_server->HasDynIP() &&
				(
					!IsGoodIP( in_server->GetIP(), thePrefs::FilterLanIPs() ) ||
					(	// don't test for filtered while ipfilter is still loading,
						// it will be filtered when filter loading is finished
						theApp->ipfilter->IsReady()
						&& theApp->ipfilter->IsFiltered(in_server->GetIP(), true))
				)
	          ) {
		if ( fromUser ) {
			AddLogLineC(CFormat( _("Server not added: The IP of [%s:%d] is filtered or invalid.") )
					% in_server->GetAddress()
					% in_server->GetPort()
			);
		}
	
		return false;
	}
	
	CServer* test_server = GetServerByAddress(in_server->GetAddress(), in_server->GetPort());
	// Avoid duplicate (dynIP) servers: If the server which is to be added, is a dynIP-server
	// but we don't know yet it's DN, we need to search for an already available server with
	// that IP.
	if (test_server == NULL && in_server->GetIP() != 0) {
		test_server = GetServerByIPTCP(in_server->GetIP(), in_server->GetPort());
	}
	
	if (test_server) {
		if ( fromUser ) {
			AddLogLineC(CFormat( _("Server not added: Server with matching IP:Port [%s:%d] found in list.") )
					% in_server->GetAddress()
					% in_server->GetPort()
			);
		}
		
		test_server->ResetFailedCount();
		Notify_ServerRefresh( test_server );
		
		return false;
	}

	theStats::AddServer();

	m_servers.push_back(in_server);
	NotifyObservers( EventType( EventType::INSERTED, in_server ) );

	if ( fromUser ) {
		AddLogLineC(CFormat( _("Server added: Server at [%s:%d] using the name '%s'.") )
				% in_server->GetAddress()
				% in_server->GetPort()
				% in_server->GetListName()
		);
	}

	
	return true;
}
Beispiel #24
0
bool CServerList::SaveServerMet()
{
	CPath curservermet = CPath(theApp->ConfigDir + wxT("server.met"));
	
	CFile servermet(curservermet, CFile::write_safe);
	if (!servermet.IsOpened()) {
		AddLogLineN(_("Failed to save server.met!"));
		return false;
	}

	try {
		servermet.WriteUInt8(0xE0);
		servermet.WriteUInt32( m_servers.size() );

		for ( CInternalList::const_iterator it = m_servers.begin(); it != m_servers.end(); ++it) {
			const CServer* const server = *it;

			uint16 tagcount = 12;
			if (!server->GetListName().IsEmpty()) {
				++tagcount;
			}
			if (!server->GetDynIP().IsEmpty()) {
				++tagcount;
			}
			if (!server->GetDescription().IsEmpty()) {
				++tagcount;
			}
			if (server->GetConnPort() != server->GetPort()) {
				++tagcount;
			}

			// For unicoded name, description, and dynip
			if ( !server->GetListName().IsEmpty() ) {
				++tagcount;
			}
			if ( !server->GetDynIP().IsEmpty() ) {
				++tagcount;
			}
			if ( !server->GetDescription().IsEmpty() ) {
				++tagcount;
			}
			if (!server->GetVersion().IsEmpty()) {
				++tagcount;
			}
			
			if (server->GetServerKeyUDP(true)) {
				++tagcount;
			}

			if (server->GetServerKeyUDPIP()) {
				++tagcount;
			}

			if (server->GetObfuscationPortTCP()) {
				++tagcount;
			}

			if (server->GetObfuscationPortUDP()) {
				++tagcount;
			}
			
			servermet.WriteUInt32(server->GetIP());
			servermet.WriteUInt16(server->GetPort());
			servermet.WriteUInt32(tagcount);
						
			if ( !server->GetListName().IsEmpty() ) {
				// This is BOM to keep eMule compatibility
				CTagString( ST_SERVERNAME, server->GetListName()).WriteTagToFile( &servermet,  utf8strOptBOM);
				CTagString( ST_SERVERNAME, server->GetListName()).WriteTagToFile( &servermet );
			}
			
			if ( !server->GetDynIP().IsEmpty() ) {
				// This is BOM to keep eMule compatibility
				CTagString( ST_DYNIP, server->GetDynIP()).WriteTagToFile( &servermet, utf8strOptBOM );
				CTagString( ST_DYNIP, server->GetDynIP()).WriteTagToFile( &servermet );
			}
			
			if ( !server->GetDescription().IsEmpty() ) {
				// This is BOM to keep eMule compatibility
				CTagString( ST_DESCRIPTION, server->GetDescription()).WriteTagToFile( &servermet, utf8strOptBOM );
				CTagString( ST_DESCRIPTION, server->GetDescription()).WriteTagToFile( &servermet );
			}
			
			if ( server->GetConnPort() != server->GetPort() ) {
				CTagString( ST_AUXPORTSLIST,	server->GetAuxPortsList()	).WriteTagToFile( &servermet );
			}
			
			CTagInt32( ST_FAIL,       server->GetFailedCount()   ).WriteTagToFile( &servermet );
			CTagInt32( ST_PREFERENCE, server->GetPreferences()   ).WriteTagToFile( &servermet );
			CTagInt32( wxT("users"),  server->GetUsers()         ).WriteTagToFile( &servermet );
			CTagInt32( wxT("files"),  server->GetFiles()         ).WriteTagToFile( &servermet );
			CTagInt32( ST_PING,       server->GetPing()          ).WriteTagToFile( &servermet );
			CTagInt32( ST_LASTPING,   server->GetLastPingedTime()).WriteTagToFile( &servermet );
			CTagInt32( ST_MAXUSERS,   server->GetMaxUsers()      ).WriteTagToFile( &servermet );
			CTagInt32( ST_SOFTFILES,  server->GetSoftFiles()     ).WriteTagToFile( &servermet );
			CTagInt32( ST_HARDFILES,  server->GetHardFiles()     ).WriteTagToFile( &servermet );
			if (!server->GetVersion().IsEmpty()){
				CTagString( ST_VERSION,	server->GetVersion() ).WriteTagToFile( &servermet, utf8strOptBOM );
				CTagString( ST_VERSION,	server->GetVersion() ).WriteTagToFile( &servermet );
			}
			CTagInt32( ST_UDPFLAGS,   server->GetUDPFlags()      ).WriteTagToFile( &servermet );
			CTagInt32( ST_LOWIDUSERS, server->GetLowIDUsers()    ).WriteTagToFile( &servermet );
			
			if (server->GetServerKeyUDP(true)) {
				CTagInt32(ST_UDPKEY, server->GetServerKeyUDP(true)).WriteTagToFile( &servermet );
			}

			if (server->GetServerKeyUDPIP()) {
				CTagInt32(ST_UDPKEYIP, server->GetServerKeyUDPIP()).WriteTagToFile( &servermet );
			}

			if (server->GetObfuscationPortTCP()) {
				CTagInt16(ST_TCPPORTOBFUSCATION, server->GetObfuscationPortTCP()).WriteTagToFile( &servermet );
			}

			if (server->GetObfuscationPortUDP()) {
				CTagInt16(ST_UDPPORTOBFUSCATION, server->GetObfuscationPortUDP()).WriteTagToFile( &servermet );
			}
			
		}
		// Now server.met.new is ready to be closed and renamed to server.met.
		// But first rename existing server.met to server.met.bak (replacing old .bak file).
		const CPath oldservermet = CPath(theApp->ConfigDir + wxT("server.met.bak"));
		if (curservermet.FileExists()) {
			CPath::RenameFile(curservermet, oldservermet, true);
		}

		servermet.Close();

	} catch (const CIOFailureException& e) {
		AddLogLineC(wxT("IO failure while writing 'server.met': ") + e.what());
		return false;
	}
	
	return true;
}
Beispiel #25
0
bool CServerList::LoadServerMet(const CPath& path)
{
	AddLogLineN(CFormat(_("Loading server.met file: %s")) % path);
	
	bool merge = !m_servers.empty();
	
	if (!path.FileExists()) {
		AddLogLineN(_("Server.met file not found!"));
		return false;
	}

	// Try to unpack the file, might be an archive
	const wxChar* mets[] = { wxT("server.met"), NULL };
	// Try to unpack the file, might be an archive
	if (UnpackArchive(path, mets).second != EFT_Met) {
		AddLogLineC(CFormat(_("Failed to load server.met file '%s', unknown format encountered.")) % path);
		return false;
	}	

	CFile servermet(path, CFile::read);
	if ( !servermet.IsOpened() ){ 
		AddLogLineN(_("Failed to open server.met!") );
		return false;
	}

	
	try {
		Notify_ServerFreeze();
		
		byte version = servermet.ReadUInt8();
		
		if (version != 0xE0 && version != MET_HEADER) {
			AddLogLineC(CFormat(_("Server.met file corrupt, found invalid versiontag: 0x%x, size %i")) % version % sizeof(version));
			Notify_ServerThaw();
			return false;
		}

		uint32 fservercount = servermet.ReadUInt32();

		ServerMet_Struct sbuffer;
		uint32 iAddCount = 0;

		for ( uint32 j = 0; j < fservercount; ++j ) {
			sbuffer.ip		= servermet.ReadUInt32();
			sbuffer.port		= servermet.ReadUInt16();
			sbuffer.tagcount	= servermet.ReadUInt32();
			
			CServer* newserver = new CServer(&sbuffer);

			// Load tags
			for ( uint32 i = 0; i < sbuffer.tagcount; ++i ) {
				newserver->AddTagFromFile(&servermet);
			}

			// Server priorities are not in sorted order
			// High = 1, Low = 2, Normal = 0, so we have to check 
			// in a less logical fashion.
			int priority = newserver->GetPreferences();
			if (priority < SRV_PR_MIN || priority > SRV_PR_MAX) {
				newserver->SetPreference(SRV_PR_NORMAL);
			}
			
			// set listname for server
			if ( newserver->GetListName().IsEmpty() ) {
				newserver->SetListName(wxT("Server ") +newserver->GetAddress());
			}
			
			
			if ( !theApp->AddServer(newserver) ) {
				CServer* update = GetServerByAddress(newserver->GetAddress(), newserver->GetPort());
				if(update) {
					update->SetListName( newserver->GetListName());
					if(!newserver->GetDescription().IsEmpty()) {
						update->SetDescription( newserver->GetDescription());
					}
					Notify_ServerRefresh(update);
				}
				delete newserver;
			} else {
				++iAddCount;
			}

		}
		
		Notify_ServerThaw();
    
		if (!merge) {
			AddLogLineC(CFormat(wxPLURAL("%i server in server.met found", "%i servers in server.met found", fservercount)) % fservercount);
		} else {
			AddLogLineC(CFormat(wxPLURAL("%d server added", "%d servers added", iAddCount)) % iAddCount);
		}
	} catch (const CInvalidPacket& err) {
		AddLogLineC(_("Error: the file 'server.met' is corrupted: ") + err.what());
		Notify_ServerThaw();
		return false;
	} catch (const CSafeIOException& err) {
		AddLogLineC(_("IO error while reading 'server.met': ") + err.what());
		Notify_ServerThaw();
		return false;
	}
	
	return true;
}
Beispiel #26
0
void CamuleDlg::OnToolBarButton(wxCommandEvent& ev)
{
	static int lastbutton = ID_BUTTONDOWNLOADS;

	// Kry - just if the GUI is ready for it
	if ( m_is_safe_state ) {

		// Rehide the handler if needed
		if ( lastbutton == ID_BUTTONSEARCH && !thePrefs::GetFED2KLH() ) {
			if (ev.GetId() != ID_BUTTONSEARCH) {
				ShowED2KLinksHandler( false );
			} else {
				// Toogle ED2K handler.
				ToogleED2KLinksHandler();
			}
		}

		if ( lastbutton != ev.GetId() ) {
			switch ( ev.GetId() ) {
				case ID_BUTTONNETWORKS:
					SetActiveDialog(DT_NETWORKS_WND, m_serverwnd);
					// Set serverlist splitter position
					CastChild( wxT("SrvSplitterWnd"), wxSplitterWindow )->SetSashPosition(m_srv_split_pos, true);
					break;

				case ID_BUTTONSEARCH:
					// The search dialog should always display the handler
					if ( !thePrefs::GetFED2KLH() )
						ShowED2KLinksHandler( true );

					SetActiveDialog(DT_SEARCH_WND, m_searchwnd);
					break;

				case ID_BUTTONDOWNLOADS:
					SetActiveDialog(DT_TRANSFER_WND, m_transferwnd);
					// Prepare the dialog, sets the splitter-position
					m_transferwnd->Prepare();
					break;

				case ID_BUTTONSHARED:
					SetActiveDialog(DT_SHARED_WND, m_sharedfileswnd);
					break;

				case ID_BUTTONMESSAGES:
					m_BlinkMessages = false;
					SetActiveDialog(DT_CHAT_WND, m_chatwnd);
					break;

				case ID_BUTTONSTATISTICS:
					SetActiveDialog(DT_STATS_WND, m_statisticswnd);
					break;

				// This shouldn't happen, but just in case
				default:
					AddLogLineC(wxT("Unknown button triggered CamuleApp::OnToolBarButton().") );
					break;
			}
		}

		m_wndToolbar->ToggleTool(lastbutton, lastbutton == ev.GetId() );
		lastbutton = ev.GetId();
	}
}
Beispiel #27
0
CamuleDlg::CamuleDlg(
	wxWindow* pParent,
	const wxString &title,
	wxPoint where,
	wxSize dlg_size)
:
wxFrame(
	pParent, -1, title, where, dlg_size,
	wxCAPTION|wxRESIZE_BORDER|wxSYSTEM_MENU|wxDIALOG_NO_PARENT|
	wxRESIZE_BORDER|wxMINIMIZE_BOX|wxMAXIMIZE_BOX|wxCLOSE_BOX,
	wxT("aMule")),
m_activewnd(NULL),
m_transferwnd(NULL),
m_serverwnd(NULL),
m_sharedfileswnd(NULL),
m_searchwnd(NULL),
m_chatwnd(NULL),
m_statisticswnd(NULL),
m_kademliawnd(NULL),
m_prefsDialog(NULL),
m_srv_split_pos(0),
m_imagelist(16,16),
m_tblist(32,32),
m_prefsVisible(false),
m_wndToolbar(NULL),
m_wndTaskbarNotifier(NULL),
m_nActiveDialog(DT_NETWORKS_WND),
m_is_safe_state(false),
m_BlinkMessages(false),
m_CurrentBlinkBitmap(24),
m_last_iconizing(0),
m_skinFileName(),
m_clientSkinNames(CLIENT_SKIN_SIZE)
{
	// Initialize skin names
	m_clientSkinNames[Client_Green_Smiley]            = wxT("Transfer");
	m_clientSkinNames[Client_Red_Smiley]              = wxT("Connecting");
	m_clientSkinNames[Client_Yellow_Smiley]           = wxT("OnQueue");
	m_clientSkinNames[Client_Grey_Smiley]             = wxT("A4AFNoNeededPartsQueueFull");
	m_clientSkinNames[Client_White_Smiley]            = wxT("StatusUnknown");
	m_clientSkinNames[Client_ExtendedProtocol_Smiley] = wxT("ExtendedProtocol");
	m_clientSkinNames[Client_SecIdent_Smiley]         = wxT("SecIdent");
	m_clientSkinNames[Client_BadGuy_Smiley]           = wxT("BadGuy");
	m_clientSkinNames[Client_CreditsGrey_Smiley]      = wxT("CreditsGrey");
	m_clientSkinNames[Client_CreditsYellow_Smiley]    = wxT("CreditsYellow");
	m_clientSkinNames[Client_Upload_Smiley]           = wxT("Upload");
	m_clientSkinNames[Client_Friend_Smiley]           = wxT("Friend");
	m_clientSkinNames[Client_eMule_Smiley]            = wxT("eMule");
	m_clientSkinNames[Client_mlDonkey_Smiley]         = wxT("mlDonkey");
	m_clientSkinNames[Client_eDonkeyHybrid_Smiley]    = wxT("eDonkeyHybrid");
	m_clientSkinNames[Client_aMule_Smiley]            = wxT("aMule");
	m_clientSkinNames[Client_lphant_Smiley]           = wxT("lphant");
	m_clientSkinNames[Client_Shareaza_Smiley]         = wxT("Shareaza");
	m_clientSkinNames[Client_xMule_Smiley]            = wxT("xMule");
	m_clientSkinNames[Client_Unknown]                 = wxT("Unknown");
	m_clientSkinNames[Client_InvalidRating_Smiley]    = wxT("InvalidRatingOnFile");
	m_clientSkinNames[Client_PoorRating_Smiley]       = wxT("PoorRatingOnFile");
	m_clientSkinNames[Client_GoodRating_Smiley]       = wxT("GoodRatingOnFile");
	m_clientSkinNames[Client_FairRating_Smiley]       = wxT("FairRatingOnFile");
	m_clientSkinNames[Client_ExcellentRating_Smiley]  = wxT("ExcellentRatingOnFile");
	m_clientSkinNames[Client_CommentOnly_Smiley]      = wxT("CommentOnly");
	m_clientSkinNames[Client_Encryption_Smiley]       = wxT("Encrypted");

	// wxWidgets send idle events to ALL WINDOWS by default... *SIGH*
	wxIdleEvent::SetMode(wxIDLE_PROCESS_SPECIFIED);
	wxUpdateUIEvent::SetMode(wxUPDATE_UI_PROCESS_SPECIFIED);
	wxInitAllImageHandlers();
	Apply_Clients_Skin();

#ifdef __WINDOWS__ 
	wxSystemOptions::SetOption(wxT("msw.remap"), 0);
#endif

#if !(wxCHECK_VERSION(2, 9, 0) && defined(__WXMAC__))
	// this crashes on Mac with wx 2.9
	SetIcon(wxICON(aMule));
#endif

	srand(time(NULL));

	// Create new sizer and stuff a wxPanel in there.
	wxFlexGridSizer *s_main = new wxFlexGridSizer(1);
	s_main->AddGrowableCol(0);
	s_main->AddGrowableRow(0);

	wxPanel* p_cnt = new wxPanel(this, -1, wxDefaultPosition, wxDefaultSize);
	s_main->Add(p_cnt, 0, wxGROW|wxEXPAND, 0);
	muleDlg(p_cnt, false, true);
	SetSizer(s_main, true);

	m_serverwnd = new CServerWnd(p_cnt, m_srv_split_pos);
	AddLogLineN(wxEmptyString);
	AddLogLineN(wxT(" - ") +
		CFormat(_("This is aMule %s based on eMule.")) % GetMuleVersion());
	AddLogLineN(wxT("   ") +
		CFormat(_("Running on %s")) % wxGetOsDescription());
	AddLogLineN(wxT(" - ") +
		wxString(_("Visit http://www.amule.org to check if a new version is available.")));
	AddLogLineN(wxEmptyString);

#ifdef ENABLE_IP2COUNTRY
	m_GeoIPavailable = true;
	m_IP2Country = new CIP2Country(thePrefs::GetConfigDir());
#else
	m_GeoIPavailable = false;
#endif
	m_searchwnd = new CSearchDlg(p_cnt);
	m_transferwnd = new CTransferWnd(p_cnt);
	m_sharedfileswnd = new CSharedFilesWnd(p_cnt);
	m_statisticswnd = new CStatisticsDlg(p_cnt, theApp->m_statistics);
	m_chatwnd = new CChatWnd(p_cnt);
	m_kademliawnd = CastChild(wxT("kadWnd"), CKadDlg);

	m_serverwnd->Show(false);
	m_searchwnd->Show(false);
	m_transferwnd->Show(false);
	m_sharedfileswnd->Show(false);
	m_statisticswnd->Show(false);
	m_chatwnd->Show(false);

	// Create the GUI timer
	gui_timer=new wxTimer(this,ID_GUI_TIMER_EVENT);
	if (!gui_timer) {
		AddLogLineN(_("FATAL ERROR: Failed to create Timer"));
		exit(1);
	}

	// Set transfers as active window
	Create_Toolbar(thePrefs::VerticalToolbar());
	SetActiveDialog(DT_TRANSFER_WND, m_transferwnd);
	m_wndToolbar->ToggleTool(ID_BUTTONDOWNLOADS, true );

	bool override_where = (where != wxDefaultPosition);
	bool override_size = (
		(dlg_size.x != DEFAULT_SIZE_X) ||
		(dlg_size.y != DEFAULT_SIZE_Y) );
	if (!LoadGUIPrefs(override_where, override_size)) {
		// Prefs not loaded for some reason, exit
		AddLogLineC(wxT("Error! Unable to load Preferences") );
		return;
	}

	// Prepare the dialog, sets the splitter-position (AFTER window size is set)
	m_transferwnd->Prepare();

	m_is_safe_state = true;

	// Init statistics stuff, better do it asap
	m_statisticswnd->Init();
	m_kademliawnd->Init();
	m_searchwnd->UpdateCatChoice();

	if (thePrefs::UseTrayIcon()) {
		CreateSystray();
	}

	Show(true);
	// Must we start minimized?
	if (thePrefs::GetStartMinimized()) {
		DoIconize(true);
	}

	// Set shortcut keys
	wxAcceleratorEntry entries[] = {
		wxAcceleratorEntry(wxACCEL_CTRL, wxT('Q'), wxID_EXIT)
	};

	SetAcceleratorTable(wxAcceleratorTable(itemsof(entries), entries));
	ShowED2KLinksHandler( thePrefs::GetFED2KLH() );

	wxNotebook* logs_notebook = CastChild( ID_SRVLOG_NOTEBOOK, wxNotebook);
	wxNotebook* networks_notebook = CastChild( ID_NETNOTEBOOK, wxNotebook);

	wxASSERT(logs_notebook->GetPageCount() == 4);
	wxASSERT(networks_notebook->GetPageCount() == 2);

	for (uint32 i = 0; i < logs_notebook->GetPageCount(); ++i) {
		m_logpages[i].page = logs_notebook->GetPage(i);
		m_logpages[i].name = logs_notebook->GetPageText(i);
	}

	for (uint32 i = 0; i < networks_notebook->GetPageCount(); ++i) {
		m_networkpages[i].page = networks_notebook->GetPage(i);
		m_networkpages[i].name = networks_notebook->GetPageText(i);
	}

	DoNetworkRearrange();
}
Beispiel #28
0
wxThread::ExitCode CPartFileConvert::Entry()
{
    int imported = 0;

    for (;;)
    {
        // search next queued job and start it
        {
            wxMutexLocker lock(s_mutex);
            s_pfconverting = NULL;
            for (std::list<ConvertJob*>::iterator it = s_jobs.begin(); it != s_jobs.end(); ++it) {
                if ((*it)->state == CONV_QUEUE) {
                    s_pfconverting = *it;
                    break;
                }
            }
        }

        if (s_pfconverting) {
            {
                wxMutexLocker lock(s_mutex);
                s_pfconverting->state = CONV_INPROGRESS;
            }

            Notify_ConvertUpdateJobInfo(s_pfconverting);

            ConvStatus convertResult = performConvertToeMule(s_pfconverting->folder);
            {
                wxMutexLocker lock(s_mutex);
                s_pfconverting->state = convertResult;
            }

            if (s_pfconverting->state == CONV_OK) {
                ++imported;
            }

            Notify_ConvertUpdateJobInfo(s_pfconverting);

            AddLogLineC(CFormat(_("Importing %s: %s")) % s_pfconverting->folder % GetConversionState(s_pfconverting->state));

            if (TestDestroy()) {
                wxMutexLocker lock(s_mutex);
                DeleteContents(s_jobs);
                break;
            }
        } else {
            break; // nothing more to do now
        }
    }

    // clean up
    Notify_ConvertClearInfos();

    if (imported) {
        theApp->sharedfiles->PublishNextTurn();
    }

    AddDebugLogLineN(logPfConvert, wxT("No more jobs on queue, exiting from thread."));

    s_convertPfThread = NULL;

    return NULL;
}