From 905c85813a24f02050421df8a7b1bf7ffbf4d987 Mon Sep 17 00:00:00 2001
From: Jacek Kowalski <Jacek@jacekk.info>
Date: Sat, 01 Nov 2014 23:52:41 +0000
Subject: [PATCH] [core] Zablokowanie przetwarzania XML External Entities

---
 data/lotto/pobierz.php |  280 +++++++++++++++++++++++++++++++------------------------
 1 files changed, 159 insertions(+), 121 deletions(-)

diff --git a/data/lotto/pobierz.php b/data/lotto/pobierz.php
index 2260d8b..73e7aeb 100644
--- a/data/lotto/pobierz.php
+++ b/data/lotto/pobierz.php
@@ -2,25 +2,41 @@
 echo STAR.'Pobieranie danych...';
 
 class lotto {
+	// Zawartość strony http://lotto.pl/wyniki-gier
+	// jako obiekt DOMDocument
 	protected $strona = NULL;
+	// Powiązany DOMXPath
+	protected $xpath = NULL;
 	
+	// Specjalne zachowania dla gier
+	const NONE = 0;
+	const PLUS = 1;
+	const LOTTOPLUS = 2;
+	const EKSTRA = 3;
+	
+	// Lista gier.
 	protected $gry = array(
-		'lotto' => array(6, FALSE, 'dl'),
-		'mini-lotto' => array(5, FALSE, 'el'),
-		'kaskada' => array(12, FALSE, 'ka'),
-		'multi-multi' => array(20, TRUE, 'mm'),
-		'joker' => array(5, FALSE, 'jk')
+		// nazwa
+		'lotto', 'mini-lotto',
+		'kaskada', 'multi-multi',
+		'joker', 'ekstra-pensja'
 	);
 	
+	// Spróbuj pobrać stronę http://lotto.pl/wyniki-gier
+	// do zmiennej $this->strona z użyciem pliku cache.
 	function __construct() {
 		$cache = 'lotto_cache.txt';
 		
+		// Sprawdź, czy da się skorzystać z pliku cache.
 		if( ( !file_exists($cache) AND !is_writable(dirname($cache)) )
 			OR ( file_exists($cache) AND !(is_writable($cache)) ) ) {
+			// Nie, nie da się.
 			$cache = '';
 		}
 		else
 		{
+			// Tak, da się.
+			// Sprawdź, czy dane są aktualne.
 			if(@filemtime($cache)<strtotime('yesterday 22:45') && time()<=strtotime('14:30')) {
 				$recent = FALSE;
 			}
@@ -34,156 +50,178 @@
 			}
 		}
 		
+		$strona = '';
+		$this->strona = new DOMDocument();
+		
 		if($cache == '' OR !$recent) {
-			$this->strona = @file_get_contents('http://lotto.pl/wyniki-gier');
-			if(!$this->strona) {
+			// Dane są nieaktualne, więc pobieramy je ponownie
+			$strona = @file_get_contents('http://lotto.pl/wyniki-gier');
+			if(!$strona) {
 				throw new Exception('Nie udało się pobrać wyników.');
 			}
 			
+			// Można zapisać do cache'a...
 			if($cache != '') {
-				file_put_contents($cache, $this->strona);
+				// ...więc zapamiętujemy arkusz.
+				file_put_contents($cache, $strona);
 			}
+			
+			@$this->strona->loadHtml($strona);
 		}
 		else
 		{
-			$this->strona = file_get_contents($cache);
-		}
-	}
-	
-	protected function szukaj_poczatku($tresc, $poczatek = 0) {
-		return strpos($this->strona, $tresc, $poczatek);
-	}
-	
-	protected function szukaj_konca($tresc, $poczatek = 0) {
-		$pozycja = strpos($this->strona, $tresc, $poczatek);
-		
-		if($pozycja !== FALSE) {
-			$pozycja += strlen($tresc);
+			// Dane w cache są aktualne, więc załaduj je.
+			@$this->strona->loadHtmlFile($cache);
 		}
 		
-		return $pozycja;
+		$this->xpath = new DOMXPath($this->strona);
 	}
 	
+	// Znajduje odpowiedni element w pliku HTML lub zwraca błąd.
+	protected function wytnij($zapytanie, $gdzie = NULL, $blad = 'Brak danych') {
+		$rezultat = $this->xpath->query($zapytanie, $gdzie);
+		if(!$rezultat OR $rezultat->length <= 0) {
+			throw new Exception($blad);
+		}
+		return $rezultat;
+	}
+	
+	// Zwraca wynik gry (domyślnie lotto).
 	function wynik($gra = 'lotto') {
 		$wyniki = $this->wyniki($gra, 1);
+		if(!isset($wyniki[0])) {
+			throw new Exception('Brak wyników dla gry.');
+		}
 		return $wyniki[0];
 	}
 	
-	function wyniki($gra = 'lotto', $liczba = 100) {
-		if(!isset($this->gry[$gra])) {
+	// Zwraca $liczba ostatnich wyników gry (domyślnie lotto),
+	// jednak nie więcej niż 5 (tyle jest na stronie Totalizatora).
+	function wyniki($gra = 'lotto', $zwroc = 1000) {
+		if(!in_array($gra, $this->gry)) {
 			throw new Exception('Podana gra liczbowa nie jest obsługiwana.');
 		}
 		
-		$wyniki = array();
-		$poczatek = $this->szukaj_konca('<div class="start-wyniki_'.$gra.'">');
-		if($poczatek === FALSE) {
-			throw new Exception('Nie znaleziono wyników dla gry '.$gra.' na stronie.');
+		$rezultaty = array();
+		
+		$dane = $this->wytnij('//div[@class="start-wyniki_'.$gra.'"]', NULL,
+			'Nie znaleziono na stronie wyników dla gry '.$gra);
+		$dane = $dane->item(0);
+		
+		
+		$daty = $this->wytnij('div[contains(concat(" ", @class, " "), " wyniki_data ")]', $dane,
+			'Nie znaleziono informacji o losowanu gry '.$gra);
+		$wyniki = $this->wytnij('div[contains(concat(" ", @class, " "), " glowna_wyniki_'.$gra.' ")]', $dane,
+			'Nie znaleziono wyników losowania gry '.$gra);
+		
+		$plusy = NULL;
+		try {
+			$plusy = $this->wytnij('div[@class="wynik_'.$gra.'_plus"]', $dane);
+		} catch(Exception $e) {}
+		
+		$lottoplusy = NULL;
+		try {
+			$lottoplusy = $this->wytnij('//div[@class="glowna_wyniki_'.$gra.'plus"]', $dane);
+		} catch(Exception $e) {}
+		
+		for($l = 0; $l < $daty->length && $l < $wyniki->length && $l < $zwroc; $l++) {
+			$rezultat = array();
+			
+			// Znajdź $l-tą datę losowania i jego wynik
+			$data = $daty->item($l);
+			$wynik = $wyniki->item($l);
+			
+			try {
+				// Znajdź datę i godzinę
+				$data = $this->wytnij('strong', $data, 'Nie znaleziono '.$l.' daty losowania gry '.$gra);
+				$rezultat['data'] = trim($data->item(0)->textContent);
+				if($data->length > 1) {
+					$rezultat['godzina'] = trim($data->item(1)->textContent);
+				}
+				
+				// Znajdź poszczególne liczby w wyniku
+				$liczby = $this->wytnij('div[@class="wynik_'.$gra.'"]', $wynik,
+					'Nie znaleziono liczb w '.$l.' losowaniu gry '.$gra);
+				$rezultat['liczby'] = array();
+				foreach($liczby as $liczba) {
+					$rezultat['liczby'][] = trim($liczba->textContent);
+				}
+			} catch(Exception $e) {
+				break;
+			}
+			
+			try {
+				// Szukamy plusa
+				if($plusy && $plusy->length > $l) {
+					$rezultat['plus'] = trim($plusy->item($l)->textContent);
+				}
+			} catch(Exception $e) {}
+			
+			try {
+				// Szukamy ekstra liczby
+				$ekstra = $this->wytnij('div[@class="wynik_'.strtr($gra, '-', '_').'"]', $wynik,
+					'Nie znaleziono ekstra w '.$l.' losowaniu gry '.$gra);
+				$rezultat['ekstra'] = trim($ekstra->item(0)->textContent);
+			} catch(Exception $e) {}
+			
+			try {
+				// Szukamy lottoplusa
+				if($lottoplusy && $lottoplusy->length > $l) {
+					$liczby = $this->wytnij('div[@class="wynik_'.$gra.'plus"]', $lottoplusy->item($l),
+						'Nie znaleziono liczb w '.$l.' losowaniu gry '.$gra.'plus');
+					$rezultat['plus'] = array();
+					foreach($liczby as $liczba) {
+						$rezultat['plus'][] = trim($liczba->textContent);
+					}
+				}
+			} catch(Exception $e) {}
+			
+			$rezultaty[] = $rezultat;
 		}
 		
-		for($l = 0; $l < $liczba; $l++) {
-			$poczatek = $this->szukaj_konca('<div class="wyniki_data">', $poczatek);
-			if($poczatek === FALSE) {
-				break;
+		return $rezultaty;
+	}
+	
+	protected $skroty = array(
+		'lotto' => 'dl', 'mini-lotto' => 'el',
+		'kaskada' => 'ka', 'multi-multi' => 'mm',
+		'joker' => 'jk', 'ekstra-pensja' => 'ep'
+	);
+	
+	function pobierz_jeden($skrot, $wynik) {
+		$last_data = @file_get_contents('./last_'.$skrot.'.txt');
+		if($last_data != $wynik['data']) {
+			foreach($wynik['liczby'] as $i => $liczba) {
+				$wynik[$i+1] = $liczba;
 			}
-			
-			$wynik = array();
-			
-			$poczatek = $this->szukaj_konca('<strong>', $poczatek);
-			if($poczatek === FALSE) {
-				break;
-			}
-			$koniec = $this->szukaj_poczatku('</strong>', $poczatek);
-			$wynik['data'] = substr($this->strona, $poczatek, $koniec-$poczatek);
-			if($poczatek === FALSE) {
-				break;
-			}
-			$poczatek = $this->szukaj_konca('<strong>', $poczatek);
-			$koniec = $this->szukaj_poczatku('</strong>', $poczatek);
-			$wynik['godzina'] = substr($this->strona, $poczatek, $koniec-$poczatek);
-			
-			$poczatek = $this->szukaj_konca('<div class="glowna_wyniki_'.$gra.'">', $poczatek);
-			if($poczatek === FALSE) {
-				break;
-			}
-			
-			$wynik['liczby'] = array();
-			for($i = 0; $i < $this->gry[$gra][0]; $i++) {
-				$poczatek = $this->szukaj_konca('<div class="wynik_'.$gra.'">', $poczatek);
-				$koniec = $this->szukaj_poczatku('</div>', $poczatek);
-				$wynik['liczby'][] = substr($this->strona, $poczatek, $koniec-$poczatek);
-			}
-			
-			if($this->gry[$gra][1]) {
-				$poczatek = $this->szukaj_konca('<div class="wynik_'.$gra.'_plus">', $poczatek);
-				$koniec = $this->szukaj_poczatku('</div>', $poczatek);
-				$wynik['plus'] = substr($this->strona, $poczatek, $koniec-$poczatek);
-			}
-			
-			$wyniki[] = $wynik;
+			file_put_contents('./last_'.$skrot.'.txt', $wynik['data']);
+			file_put_contents('./'.$skrot.'.txt', serialize($wynik));
+			file_put_contents('./archiwum/'.$skrot.'_'.date('j.m.Y', strtotime($wynik['data'])).'.txt', serialize($wynik));
+			echo OK;
+		} else {
+			echo NOT;
 		}
-		
-		return $wyniki;
 	}
 	
 	function pobierz() {
-		foreach($this->gry as $gra => $data) {
+		foreach($this->gry as $gra) {
 			echo STAR.'Wyniki gry '.$gra.'...';
 			if($gra == 'multi-multi') {
+				echo "\n";
 				$wyniki = $this->wyniki($gra, 2);
-				$wynik = $wyniki[0];
-				$skrot = $data[2].substr($wynik['godzina'], 0, 2);
-				$last_data = @file_get_contents('./last_'.$skrot.'.txt');
-				if($last_data != $wynik['data']) {
-					$output = array();
-					$output['data'] = $wynik['data'];
-					for($i = 0; $i < $data[0]; $i++) {
-						$output[$i+1] = $wynik['liczby'][$i];
+				foreach($wyniki as $wynik) {
+					$godzina = substr($wynik['godzina'], 0, 2);
+					echo '   '.STAR.'godzina '.$godzina.'...';
+					if($godzina == '21') {
+						$godzina = '22';
 					}
-					if($data[1]) {
-						$output['plus'] = $wynik['plus'];
-					}
-					file_put_contents('./last_'.$skrot.'.txt', $output['data']);
-					file_put_contents('./'.$skrot.'.txt', serialize($output));
-					file_put_contents('./archiwum/'.$skrot.'_'.date('j.m.Y', strtotime($output['data'])).'.txt', serialize($output));
+					$skrot = $this->skroty[$gra].$godzina;
+					
+					$this->pobierz_jeden($skrot, $wynik);
 				}
-				
-				$wynik = $wyniki[1];
-				$skrot = $data[2].substr($wynik['godzina'], 0, 2);
-				$last_data = @file_get_contents('./last_'.$skrot.'.txt');
-				if($last_data != $wynik['data']) {
-					$output = array();
-					$output['data'] = $wynik['data'];
-					for($i = 0; $i < $data[0]; $i++) {
-						$output[$i+1] = $wynik['liczby'][$i];
-					}
-					if($data[1]) {
-						$output['plus'] = $wynik['plus'];
-					}
-					file_put_contents('./last_'.$skrot.'.txt', $output['data']);
-					file_put_contents('./'.$skrot.'.txt', serialize($output));
-					file_put_contents('./archiwum/'.$skrot.'_'.date('j.m.Y', strtotime($output['data'])).'.txt', serialize($output));
-				}
+			} else {
+				$this->pobierz_jeden($this->skroty[$gra], $this->wynik($gra));
 			}
-			else
-			{
-				$wynik = $this->wynik($gra);
-				$skrot = $data[2];
-				$last_data = @file_get_contents('./last_'.$skrot.'.txt');
-				if($last_data != $wynik['data']) {
-					$output = array();
-					$output['data'] = $wynik['data'];
-					for($i = 0; $i < $data[0]; $i++) {
-						$output[$i+1] = $wynik['liczby'][$i];
-					}
-					if($data[1]) {
-						$output['plus'] = $wynik['plus'];
-					}
-					file_put_contents('./last_'.$skrot.'.txt', $output['data']);
-					file_put_contents('./'.$skrot.'.txt', serialize($output));
-					file_put_contents('./archiwum/'.$skrot.'_'.date('j.m.Y', strtotime($output['data'])).'.txt', serialize($output));
-				}
-			}
-			echo OK;
 		}
 	}
 }

--
Gitblit v1.9.1