Kategoria: webmajsterka

webmajsterka, czyli wszystko co związane ze stronami internetowymi oraz PHP

wordpress 2.8.5 poprawka bezpieczeństwa

wordpress 2.8.5 poprawka bezpieczeństwa

Jako że WordPress rozpędził się z poprawkami to czemu ja nie miałbym robić tego samego…

Zawsze najnowszą wersje można pobrać ze strony: http://wordpress.org/download/

Lecz obstawiam że wyjdzie wersja wordpress 2.8.5, bo coś od wersji 2.8 ciekawe błędy odnajdują. Tylko pytanie kiedy ktokolwiek im powie gdzie są te błędy…

Często łatwiej coś zrobić od nowa niźli w nieskończoność naprawiać. Ale cóż albo doczekamy się poprawek albo wersji 2.9 która zapewne coś poprawi…

Szatan

Szatańska przepowiednia się spełniła WordPress 2.8.5 nie na marne skorzystałem z musku…

tablica ze statusami błędów http

Tablica ze statusami błędów HTTP + tłumaczenie po polsku oraz wpisy do pliku .htaccess z tymi błędami:

//Tablica ze statusami błędów by tosiek ( https://tosiek.pl/ )
$errors = array(
	//Client errors - po stronie klienta
	'400'=>array('Bad Request','Błędne żądanie'),
	'401'=>array('Unauthorized','Brak autoryzacji'),
	'402'=>array('Payment Required','Wymagana opłata'),
	'403'=>array('Forbidden','Dostęp zabroniony'),
	'404'=>array('Not Found','Nie znaleziono'),
	'405'=>array('Method Not Allowed','Metoda nie dozwolona'),
	'406'=>array('Not Acceptable','Brak akceptacji'),
	'407'=>array('Proxy Authentication Required','Wymagana autoryzacja proxy'),
	'408'=>array('Request Time-out','Zapytanie przekroczyło czas oczekiwania'),
	'409'=>array('Conflict','Konflikt'),
	'410'=>array('Gone','Zniknął'),
	'411'=>array('Length Required','Wymagana długość'),
	'412'=>array('Precondition Failed','Nie spełniono warunku wstępnego'),
	'413'=>array('Request Entity Too Large','Zbyt duże żądanie'),
	'414'=>array('Request-URI Too Large','Adres URI zapytania jest zbyt długi'),
	'415'=>array('Unsupported Media Type','Niewspierany typ medium'),
	'416'=>array('Requested range not satisfiable','Żądany zakres nie obsługiwany'),
	'417'=>array('Expectation Failed','Niepowodzenie oczekiwania'),
	//Server errors - po stronie serwera
	'500'=>array('Internal Server Error','Wewnętrzny błąd serwera'),
	'501'=>array('Not Implemented','Niezaimplementowane'),
	'502'=>array('Bad Gateway','Błąd bramy'),
	'503'=>array('Service Unavailable','Usługa niedostępna'),
	'504'=>array('Gateway Time-out','Przekroczony czas oczekiwania bramy'),
	'505'=>array('HTTP Version not supported','Brak wsparcia dla tej wersji HTTP'),
	'509'=>array('Bandwidth Limit Exceeded','Przekroczono limit transferu'),
);

Do tablicy odnosimy się:
$errors[numer_błędu][jezyk_opisu]
(gdzie jezyk_opisu to: 1 – polski, 0 – angielski który jest także nagłówkiem dla przeglądarki)

Więc dla polskiego opisu dla błędu 404:
$errors[404][‘1’]

Dla angielskiego opisu dla błędu 404: (angielski opis jest takze nagłówkiem wysyłanym do przeglądarki)
$errors[404][‘0’]

Wpisy do pliku .htaccess ze wszystkimi wyżej wymienionymi błędami HTTP:

#Bledy numeryczne na error.php
RewriteRule ^([0-9][0-9][0-9])+$ /errorek.php?error=$1 [L,NC]
#Bledy HTTP - wlasna strona bledu
#Client error - po stronie klienta
ErrorDocument 400 /400
ErrorDocument 401 /401
ErrorDocument 402 /402
ErrorDocument 403 /403
ErrorDocument 404 /404
ErrorDocument 405 /405
ErrorDocument 406 /406
ErrorDocument 407 /407
ErrorDocument 408 /408
ErrorDocument 409 /409
ErrorDocument 410 /410
ErrorDocument 411 /411
ErrorDocument 412 /412
ErrorDocument 413 /413
ErrorDocument 414 /414
ErrorDocument 415 /415
ErrorDocument 416 /416
ErrorDocument 417 /417
#Server error - po stronie serwera
ErrorDocument 500 /500
ErrorDocument 501 /501
ErrorDocument 502 /502
ErrorDocument 503 /503
ErrorDocument 504 /504
ErrorDocument 505 /505
ErrorDocument 509 /509

Jak widać powyżej strony błędów są pobierane z adresu /XXX gdzie XXX to numer błędu. Natomiast reguła RewriteRule wczytuje dokument errorek.php ze zmienną GET error=$1 gdzie $1 to numer błedu jak i adres wywołanej strony.

kody odpowiedzi statusów http 1.1

kody błędów odpowiedzi statusów http 1.1

Status Code Definitions HTTP/1.1 – HTTP Request and Response Header – dotyczą one:

Client Error 4xx

Klasa statusów 4xx jest przeznaczona do przypadków w których klient powoduje błąd. Z wyjątkiem sytuacji gdy odpowiada na zapytanie HEAD, serwer powinien zawierać stosowną jednostkę wyjaśniająca zaistniałą sytuację (błąd), i czy jest to stan tymczasowy lub stały. Te kody odpowiedzi mają zastosowanie do każdej metody zapytania. User Agent (przeglądarka) powinien wyświetlić dowolną jednostkę użytkownikowi.

Jeśli klient przesyła dane, a serwer realizuje zapytanie przy użyciu protokołu TCP powinien być ostrożny, aby zapewnić iż klient otrzyma pakiet(y) zawierające odpowiedzi, zanim serwer zamknie połączenie wejściowe. Jeśli klient nadal wysyła dane po zamknięciu, serwer TCP wysyła pakiet resetujący do klienta, który może skasować klienta nieuznanego bufora wejścia przed ich odczytaniem i zinterpretowaniem przez aplikację HTTP.

  • 400 Bad Request ( Błędne żądanie )
  • 401 Unauthorized ( Brak autoryzacji )
  • 402 Payment Required ( Wymagana opłata )
  • 403 Forbidden ( Dostęp zabroniony )
  • 404 Not Found ( Nie znaleziono )
  • 405 Method Not Allowed ( Metoda nie dozwolona )
  • 406 Not Acceptable ( Brak akceptacji )
  • 407 Proxy Authentication Required ( Wymagana autoryzacja proxy )
  • 408 Request Time-out ( Zapytanie przekroczyło czas oczekiwania )
  • 409 Conflict ( Konflikt )
  • 410 Gone ( Zniknął )
  • 411 Length Required ( Wymagana długość )
  • 412 Precondition Failed ( Nie spełniono warunku wstępnego )
  • 413 Request Entity Too Large ( Zbyt duże żądanie )
  • 414 Request-URI Too Large ( Adres URI zapytania jest zbyt długi )
  • 415 Unsupported Media Type ( Niewspierany typ medium )
  • 416 Requested range not satisfiable ( Żądany zakres nie obsługiwany )
  • 417 Expectation Failed ( Niepowodzenie oczekiwania )
  • 666 Welcome in Home ( Witamy w domu )
  • 616 Go to Home ( Idź do domu )

Server Error 5xx

Kody odpowiedzi rozpoczynające się od cyfry “5” wskazują przypadki w których serwer jest świadomy iż popełnił błąd lub jest niezdolny do wykonania zapytania. Z wyjątkiem sytuacji, gdy odpowiadając na wniosek HEAD, serwer powinien zawierać informacje wyjaśniające zaistniały błąd, i czy stan tego jest tymczasowy lub stały. User agent (przeglądarka) powinien wyświetlić stosowną jednostkę. Te kody odpowiedzi mają zastosowanie do każdej metody zapytania.

  • 500 Internal Server Error ( Wewnętrzny błąd serwera )
  • 501 Not Implemented ( Niezaimplementowane )
  • 502 Bad Gateway ( Błąd bramy )
  • 503 Service Unavailable ( Usługa niedostępna )
  • 504 Gateway Time-out ( Przekroczony czas oczekiwania bramy )
  • 505 HTTP Version not supported ( Brak wsparcia dla tej wersji HTTP )
  • 509 Bandwidth Limit Exceeded ( Przekroczono limit transferu )

Z czego 509 nie znajduje się w specyfikacji lecz jest używany przez serwery do wyświetlenia błędu z informacją o wyczerpaniu przyznanego transferu, choć nie jest to regułą.

Dokumentacja specyfikacji: Definicje kodów statusu HTTP/1.1

usuwanie stopki phpbb by przemo

usuwanie stopki phpbb by przemo

Żaden ze znanych skryptów nie blokuje zmiany stopki ani jej usunięcia oprócz phpbb by przemo. Usunięcie stopki jest możliwe oraz jej modyfikacje.
Lecz tutaj po zmianie stopki wyświetla się komunikat i jakby tego mało wysyła email do przema… To nie jest instrukcja typu zrób to i tamto !

Jak jest wyświetlana stopka ?

Zaczynamy od tego iż stopka jest wyświetlana z pliku overall_footer.tpl za pomocą zmiennej stylu: {PAGE_LOAD_PLEASE_WAIT} (w uproszczonej stopce simple_footer.tpl usunięcie lub zmiana stopki nie powoduje wyświetlenia ostrzeżenia).

I jakakolwiek modyfikacja stopki lub usunięcie powoduje wyświetlenie ostrzeżenia.

Stopka forum została zmodyfikowana, forum nie będzie działać prawidłowo!
Ustaw prawidłowo stopkę w pliku overall_footer.tpl, musi być ona widoczna w przegladarce, nie może zawierać “sztuczek” maskujacych.

Wzór: Powered by <a href="http://www.phpbb.com" target="_blank" class="copyright">phpBB</a> modified by <a href="http://www.przemo.org/phpBB2/" class="copyright" target="_blank">Przemo</a> &copy; 2003 phpBB Group

Lecz ostrzeżenie wyświetla się tylko podczas wysyłania postu lub prywatnej wiadomości, a za to odpowiada plik posting.php lub includes/functions_post.php.

Niestety na darmo możemy szukać zmiennej stylu {PAGE_LOAD_PLEASE_WAIT} w pliku includes/page_tail.php (odpowiada ona za generowanie stopki), ale znajdziemy ją w pliku includes/page_header.php (odpowiada za generowanie headera – topu forum):

'PAGE_LOAD_PLEASE_WAIT' => append_sid('<a href="index.'.$phpEx.'?mode=tloading">' . $lang['Page_loading_wait'] . '</a>'),

Więc szukamy funkcji append_sid, znajduje się w pliku includes/sessions.php

function append_sid($url, $non_html_amp = false, $subdir_off = false)
{
	global $SID, $subdirectory;
 
	if ( !empty($SID) && !preg_match('#sid=#', $url) )
	{
		$url .= ( ( strpos($url, '?') !== false ) ?  ( ( $non_html_amp ) ? '&' : '&amp;' ) : '?' ) . $SID;
	}
 
	if ( isset($subdirectory) && !$subdir_off )
	{
		$url = $subdirectory . $url;
	}
 
	$sid1 = base64_decode('aGFzaF8x');
	$sid_s = base64_decode('aGFzaF8y');
 
	global $$sid1, $$sid_s;
 
	return (strpos($url, base64_decode('bW9kZT10bG9hZGluZw==')) !== false) ? base64_decode(base64_decode(str_replace('si', '', $$sid1))) : ((strpos($url, base64_decode('bW9kZT1lbG9hZGluZw==')) !== false) ? base64_decode(base64_decode($$sid_s)) : $url);
}

Na pierwszy rzut oka coś związanego z adresami i ID sesji… lecz base64_decode() i do tego podwójne budzi ciekawość więc sprawdźmy i zdekodujmy:

$sid1 = hash_1;
$sid_s = hash_2;

Co ciekawsze hash_1 i hash_2 to zmienne globalne (zmienne bo należy zwrócić uwagę na dwa $$ przed nazwą):

global $$sid1, $$sid_s;

Więc tak naprawdę mamy:

global $hash_1, $hash_2;

a te zmienne znajdują się w pliku includes/constans.php:

// Forum unique hash
$hash_1 = 'VUc5M1pYSmxaQ0JpZVNBOFlTQm9jbVZtUFNKb2RIUndPaTh2ZDNkM0xuQm9jR0ppTG1OdmJTSWdkR0Z5WjJWMFBTSmZZbXhoYm1zaUlHsiTnNZWE56UFNKamIzQjVjbWxuYUhRaVBuQm9jRUpDUEM5aFBpQnRiMlJwWm1sbFpDQmllU0E4WVNCb2NtVm1QU0pvZEhSd09pOHZkM2QzTG5CeWVtVnRieTV2Y21jdmNHaHdRa0l5THlJZ1kyeGhjM005SW1OdmNIbHlhV2RvZENJZ2RHRnlaMlYwUFNKZllteGhibXNpUGxCeWVtVnRiend2WVQ0Z0ptTnZjSGs3SURJd01ETWdjR2h3UWtJZ1IzSnZkWEE9';
$hash_2 = 'UENFdExTQlFiM2RsY21Wa0lHSjVJSEJvY0VKQ0lHMXZaR2xtYVdWa0lIWXhMamtnWW5rZ2NISjZaVzF2SUNnZ2FIUjBjRG92TDNkM2R5NXdjbnBsYlc4dWIzSm5MM0JvY0VKQ01pOGdLU0F0TFQ0PQ==';

Następnie funkcja zwraca nam wartość ale zależną od tego co znajdzie w $url (należy najpierw pamiętać o usunięciu si w $hash_1):

return (strpos($url, 'mode=tloading') !== false) ? 'Powered by <a href="http://www.phpbb.com" target="_blank" class="copyright">phpBB</a> modified by <a href="http://www.przemo.org/phpBB2/" class="copyright" target="_blank">Przemo</a> © 2003 phpBB Group' : ((strpos($url, 'mode=eloading') !== false) ? '<!-- Powered by phpBB modified v1.9 by przemo ( http://www.przemo.org/phpBB2/ ) -->' : $url);

Oczywiście nas interesuje to co zwróci dla mode=tloading, a zwróci stopkę z $hash_1.

To już wiemy jak jest wyświetlana stopka.

Jak jest sprawdzana poprawność stopki ?

W pliku lang_main.php znajdziemy ostrzeżenie dotyczące stopki:

$lang['footer'] = 'Stopka forum została zmodyfikowana, forum nie będzie działać prawidłowo!<br />Ustaw prawidłowo stopkę w pliku overall_footer.tpl, musi być ona widoczna w przegladarce, nie może zawierać "sztuczek" maskujacych.<br /><br />Wzór: <b>Powered by &lt;a href=&quot;http://www.phpbb.com&quot; target=&quot;_blank&quot; class=&quot;copyright&quot;&gt;phpBB&lt;/a&gt; modified by &lt;a href=&quot;http://www.przemo.org/phpBB2/&quot; class=&quot;copyright&quot; target=&quot;_blank&quot;&gt;Przemo&lt;/a&gt; &amp;copy; 2003 phpBB Group</b>';

Skoro wiemy jak jest wyświetlana stopka i że ostrzeżenie pojawia się podczas pisania więc poszukajmy w pliku includes/functions_post.php naszej znajomej zmiennej:

$$sid1

Zaprowadzi nas to do funkcji correct_file() lecz zacznijmy od początku:

//code to get rid of some quick-reply-mod problems
	$crf = base64_decode('Y29ycmVjdF9maWxl');

po zdekodowaniu wywołuje funkcję correct_file:

$crf = correct_file;

Lecz następnie jest losowana liczba z pewnego przedziału:

$cr_file = rand(4,8);

Wiec szukamy co korzysta ze zmiennej $cr_file:

if ( $cr_file == 5 ) @$crf(false);

Jeśli wylosuje się 5 to stopka nie zostanie sprawdzona.

Funkcja correct_file()

function correct_file($file = true)
{
	global $board_config, $phpEx, $lang;
 
	$server_name = preg_replace('#^\/?(.*?)\/?$#', '\1', trim($board_config['server_name']));
	$btf = base64_decode('bWFpbA==');
	$script_name = preg_replace('#^\/?(.*?)\/?$#', '\1', trim($board_config['script_path']));
	$script_name = ($script_name == '') ? $script_name. '/login.'.$phpEx : '/' . $script_name. '/login.'.$phpEx;
	$server_protocol = ($board_config['cookie_secure']) ? 'https://' : 'http://';
	$server_port = trim($board_config['server_port']);
 
	$sid1 = base64_decode('aGFzaF8x');
 
	global $$sid1;
	$$sid1 = str_replace('si', '', $$sid1);
	$cont = get_url($server_name, $script_name, trim($board_config['server_port']));
	$cont = $cont[1];
	$th_ch = base64_decode(base64_decode($$sid1));
	if ( @eregi('username', $cont) && @eregi('password', $cont) )
	{
		$lmk = false;
		if ( !($pos = @strpos($cont, $th_ch)) || !(@strpos($$sid1, 'NJZ2RHRnlaMlYwUFNKZllteGhibXNpUGxCeWVtVnRiend2WVQ0Z')) || !(@strpos($$sid1, 'xuYUhRaVBuQm9jRUpDUEM5aFBpQnRiMlJwWm1sbFpDQmllU0E4WVNCb2NtVm1QU0pvZEhSd09pOHZkM2QzTG5CeWVtVnRieTV2Y21jdmNHaHdRa0l5TH')) )
		{
			$lmk = true;
		}
		$first = @str_replace(' ', '', @substr($cont, $pos-20, 20));
		$second = @str_replace(' ', '', @substr($cont, $pos+@strlen($th_ch)-1, 20));
		if ( @strpos($first, base64_decode('IS0t')) || @strpos($first, base64_decode('PGZvbg==')) || @strpos($first, base64_decode('aGlkZQ==')) || @strpos($first, base64_decode('aGlkZGU=')) || @strpos($second, base64_decode('LS0=')) || @strpos($second, base64_decode('L2Zvbg==')) )
		{
			$lmk = true;
		}
		if ( $lmk )
		{
			$th_d = base64_decode(base64_decode('Wm05dmRHVnk='));
			if ( @strpos($th_d, base64_decode(base64_decode('SEE2THk5M2QzY3VjSEo2WlcxdkxtOXla'))) ) exit;
			if ( @function_exists($btf) && $board_config['data'] < (CR_TIME - 432000) ) { @$btf(base64_decode('c3RvcGthQHByemVtby5vcmc='), base64_decode('LVNUT1BLQS0=-'), $server_protocol . $server_name . $server_port . '/' . preg_replace('#^\/?(.*?)\/?$#', '\1', trim($board_config['script_path'])) . "\r\n" . $board_config['board_email']); update_config('data', CR_TIME); }die($lang[$th_d]);
		}
	}
	return true;
}

Wiec po kolei, zmienna $btf

$btf = mail;

(jakby nie patrzeć będzie wysyłany email)
Odniesienie do naszego wzorcu stopki:

$sid1 = hash_1;

Potem z naszego wzoru stopki usuwane są frazy si oraz nasz wzorzez jest dwa razy dekodowany i otrzymujemy:

$th_ch = 'Powered by <a href="http://www.phpbb.com" target="_blank" class="copyright">phpBB</a> modified by <a href="http://www.przemo.org/phpBB2/" class="copyright" target="_blank">Przemo</a> © 2003 phpBB Group';

I co ciekawe jest pobierana treść strony logowania i jeśli znajdą sie tam dwie frazy password oraz username to tylko wtedy sprawdzana jest poprawność stopki.

Następnie sprawdzane jest czy znajduje się tam cała stopka według wzorca oraz czy wzorzec jest zgodny z porównaniem, jeśli nie to wysyłany jest email do przema i zostaje wyświetlone ostrzeżenie.

Dodatkowo sprawdzane są sztuczki maskujące (komentowanie stopki, jak i znacznik oraz hidden w CSS) takim if-em, jeśli zostaną znalezione w pobliżu stopki także wyświetlane jest ostrzeżenie i wysłany zostaje email do przema:

if ( @strpos($first, '!--') || @strpos($first, '<fon') || @strpos($first, 'hide') || @strpos($first, 'hidde') || @strpos($second, '--') || @strpos($second, '/fon') )

Oczywiście wysyłanie maila wygląda tak:

$th_d = footer;
			if ( @function_exists(mail) && $board_config['data'] < (CR_TIME - 432000) ) { 
@mail('stopka@przemo.org', '-STOPKA-', $server_protocol . $server_name . $server_port . '/' . preg_replace('#^\/?(.*?)\/?$#', '\1', trim($board_config['script_path'])) . "\r\n" . $board_config['board_email']); 
update_config('data', CR_TIME); 
}
die($lang[$th_d]);

I po wysłaniu maila wyświetlane jest ostrzeżenie:

die('footer');

Wszystko jest wysyłane na email……………….

Jak wyłączyć sprawdzanie stopki ?

W pliku overall_footer.tpl zmieniamy:

{PAGE_LOAD_PLEASE_WAIT}

na:

<br><a href="http://www.phpbb.com" target="_blank" class="copyright">phpBB</a> &amp; <a href="http://www.przemo.org/phpBB2/" target="_blank" class="copyright">Przemo</a>

W pliku includes/functions_post.php znajdź:

$crf = base64_decode('Y29ycmVjdF9maWxl');

zamień na:

//$crf = base64_decode('Y29ycmVjdF9maWxl');

znajdź:

$cr_file = rand(4,8);

zamień na:

//$cr_file = rand(4,8);

znajdź:

if ( $cr_file == 5 ) @$crf(false);

zamień na:

//if ( $cr_file == 5 ) @$crf(false);

To wszystko, nigdzie więcej stopka nie jest sprawdzana lecz nie jestem w stanie tego zagwarantować iż jakieś maile nie są jeszcze wysyłane.

Jak usunąć stopkę phpbb by przemo – prostszy sposób

Aby usunąć stopkę wystarczy zaingerować w plik: includes/sessions.php, otwieramy go
Szukamy funkcji append_sid

function append_sid

Następnie trochę niżej linijek:

$sid1 = base64_decode('aGFzaF8x');
	$sid_s = base64_decode('aGFzaF8y');
 
	global $$sid1, $$sid_s;
 
	return (strpos($url, base64_decode('bW9kZT10bG9hZGluZw==')) !== false) ? base64_decode(base64_decode(str_replace('si', '', $$sid1))) : ((strpos($url, base64_decode('bW9kZT1lbG9hZGluZw==')) !== false) ? base64_decode(base64_decode($$sid_s)) : $url);

Zmieniamy je na:

return $url;

Bardzo proste, od teraz stopka nie będzie się wyświetlała ze zmiennej {PAGE_LOAD_PLEASE_WAIT}, dlatego należy pamiętać by usunąć sprawdzanie stopki.

Zapomniałem napisać ale dzięki temu (wyłączeniu sprawdzania stopki) zwiększa się szybkość wysyłania postów!

wordpress 2.8.4 poprawka bezpieczeństwa

wordpress 2.8.4 poprawka bezpieczeństwa

Poprawka poprawki, coś ostatnio nie mogą przestać…

Wczoraj odkryto lukę: specjalnie spreparowany adres URL może być wywołany, co pozwoli atakującemu na ominięcie zabezpieczeń w celu potwierdzenia prośby o przypomnienie hasła. W wyniku, pierwsze konto bez klucza w bazie danych (zwykle jest to konto administratora) jego hasło zostaje zresetowane i nowe hasło zostanie wysłane e-mailem na konto właściciela. To nie pozwala na zdalny dostęp, ale to jest bardzo denerwujące.

Ustaliliśmy ten problem ostatniej nocy, zostały przetestowane poprawki i szukamy innych problemów, od tamtego czasu. Po adresem: http://wordpress.org/download/ znajduje się Wersja 2.8.4, która naprawia wszystkie aktualnie znane problemy jest już dostępna do pobrania i jest wysoce zalecana dla wszystkich użytkowników WordPress.

Oryginalny wpis Matt Mullenweg:

Yesterday a vulnerability was discovered: a specially crafted URL could be requested that would allow an attacker to bypass a security check to verify a user requested a password reset. As a result, the first account without a key in the database (usually the admin account) would have its password reset and a new password would be emailed to the account owner. This doesn’t allow remote access, but it is very annoying.

We fixed this problem last night and have been testing the fixes and looking for other problems since then. Version 2.8.4 which fixes all known problems is now available for download and is highly recommended for all users of WordPress.

compress CSS code – compressor

compress CSS code – compressor

Kompresja kodu CSS, gotowa funkcja PHP która za pomocą wyrażeń regularnych usuwa zbędne znaki z kaskadowego arkusza stylów – CSS tym samym zmniejszając jego rozmiar, co prowadzi do szybszego wczytania strony (stylów) jak i zmniejszenia zużycia transferu (należy pamiętać że plik ze stylem jest wczytywany z każdym żądaniem przeglądarki, dlatego nawet mała różnica rozmiaru ma znaczenie)

Działanie można przetestować na: Kompresja CSS

Aktualnie funkcja usuwa wszystko co nie potrzebne, zachowuje składnię CSS. Dzięki zachowaniu składni arkusz po kompresji będzie działał prawidłowo.

Aktualnie usuwane zbędne rzeczy takie jak:

  • Tabulatory – TAB – 0×09 (\t, \x09)
  • Tabulator Pionowy – vertical tab – 0×0B (\x0B)
  • Znak nowej linii – 0×0A (\n, \x0A)
  • Znak powrotu karetki – 0×0D (\r, \x0D)
  • Puste znaki – 0×00 (\0, \x00)
  • Każdą podwójną spację (i więcej np. 3, 4 i tak dalej) 0×20 0×20 – (\x20\x20)
  • Każdą pojedynczą spację, lecz tylko w wybranych i dozwolonych miejscach (zmienna $char_css)
  • Wszystkie komentarze
  • Skraca kolory o ile to możliwe w zapisie HEX z np. z #aaffaa na #afa
  • Usuwa średnik z ostatniej reguły, ponieważ jest zbędny

Zostało dodane usuwanie zbędnych spacji po znaku @ (małpa) oraz zmiana tabulatorów od jednego w górę na pojedynczą spację, oraz zamiana spacji od dwóch w górę na jedną

function compress_css($css_code) {
/*********************
//
//Compress CSS by tosiek - https://tosiek.pl/
//
*********************/
//Special CSS characters after and before the spaces are removed
//do not use ')' !!! - this causes a bug in Internet Explorer
	$char_css='{|}|(|;|:|,|\'|"|@';
	//pattern to shortening hex colour
	$hex_char='[a-f0-9]';
	//
	// Arrays
	//
	//array with pattern
	$pattern=array(
		//new lines(\n and \r)
		"/\x0A/","/\x0D/",
		//vertical tab and tab
		"/\x0B/","/\x09{1,}/",
		//NULL bytes (\0)
		"/\\x00/",
		//double spaces and more, more
		"/\x20{2,}/",
		//remove spaces with $char_css, after and before
		"/([{$char_css}]+)\x20/","/\x20([{$char_css}]+)/",
		//remove all comments
		"!/\*[^*]*\*+([^/][^*]*\*+)*/!",
		//short hex colour
		"/#({$hex_char})\\1({$hex_char})\\2({$hex_char})\\3/i",
		//remove last ';'
		"/;}/",
	);
	//array with replacement
	$replacement=array(
		//new lines(\n and \r)
		'','',
		//vertical tab and tab
		'',"\x20",
		//NULL bytes (\0)
		'',
		//double spaces and more, more
		"\x20",
		//remove spaces with $char_css, after and before
		'$1','$1',
		//remove all comments
		'',
		//short hex colour
		'#\1\2\3',
		//remove last ';'
		"}",
	);
	// strlen() before compress
	$start=strlen($css_code);
	//Compress CSS with regular expressions
	$replace=preg_replace($pattern,$replacement,$css_code,-1);
	// strlen() after compress
	$final=strlen($replace);
	//counts the difference in characters
	$exhed=$start-$final;
	//counts the difference in percentages
	$compression=round(($exhed)/$start*100,2);
	//Return compress CSS code with info (comment) in new line
	return $replace."\n".'/* Poczatkowy rozmiar: '.$start.' bajtow; Po kompresji: '.$final.' bajtow; Zmniejszono o: '.$exhed.' bajtow ('.$compression.'% procent) */';
}

przykładowe wykorzystanie z użyciem pliku style.css:

<?php
$style = file_get_contents(dirname(__FILE__).'style.css');
$style = compress_css($style);
echo $style;
?>

Podany powyżej kod po wywołaniu go, wyświetli nam skompresowany kod z pliku style.css wraz z informacją o rozmiarze przed i po kompresji oraz oszczędności w procentach.

/* Poczatkowy rozmiar: 37 bajtow; Po kompresji: 14 bajtow; Zmniejszono o: 23 bajtow (62.16% procent) */

Przykładowy kod przed kompresją (należy zwrócić uwagę na niewidoczne znaki takie jak spacje, tabulatory i przejścia do nowych linii – entery)

	*  {
margin:   0		 6;
  }

Oraz po kompresji:

*{margin:0 6}
/* Poczatkowy rozmiar: 37 bajtow; Po kompresji: 13 bajtow; Zmniejszono o: 24 bajtow (64.86% procent) */