Serwis używa plików cookies do analizy ruchu i poprawy działania. Szczegóły
EE.09-03-22.01-SGStyczeń 2022 · 43 kroki · ok. 80 min · 34 kryteria z klucza
Rozwiązanie krok po kroku: Dodawanie zespołu pogotowia ratunkowego (Wersja podstawowa)
Portal pogotowia ratunkowego: baza ee09 z tabelami zespołów ratowniczych, dyspozytorów i zgłoszeń (import z pliku baza3.sql), cztery zapytania - dopisanie zespołu (INSERT), zgłoszenia przyjęte przez dyspozytora o id 4, utworzenie użytkownika bazy (CREATE USER) i nadanie mu uprawnień do tabeli (GRANT). Do tego zdjęcie karetki przeskalowane do wysokości 100 px, strona ratownicy.html z formularzem dodania zespołu, odnośnikiem i listą numerów alarmowych, style w styl3.css oraz skrypt dodanie.php, który zapisuje zespół w bazie i wypisuje wysłane zapytanie.
To arkusz EE.09 ze stycznia 2022 - kwalifikacji formuły 2017, którą zastąpiła INF.03. Kroki idą zdanie po zdaniu za treścią arkusza - przy każdym jest polecenie z arkusza, a kod pokazuje dokładnie te linie, które je spełniają. Skrypt jest najpierw napisany najprościej, funkcjami mysqli z tabeli 1 arkusza, a na końcu sprawdzony na prawdziwych atakach i zabezpieczony.
To jest wersja podstawowa. W zakładce „Nowoczesny kod (flex, PDO)” jest drugi sposób rozwiązania tego samego arkusza: semantyczne znaczniki, etykiety <label>, układ banera i stopki we flex, PDO z zapytaniem przygotowanym i sprawdzaniem danych - obie wersje są zgodne z kluczem.
Baza i zdjęcie pochodzą z oryginalnego archiwum CKE pliki3.zip (załącznik do pobrania na stronie arkusza, hasło w treści zadania). Zapytania i zrzuty są policzone na MariaDB 10.4 - tej samej, która jest w XAMPP. Podgląd skryptu to wynik prawdziwego uruchomienia kodu w PHP 8.2 (klucz każe sprawdzać w XAMPP 8.0.7 - użyte funkcje działają w obu wersjach tak samo).
Jak liczą się punkty. Klucz ma 34 kryteria (R.1.1 - R.5.5), każde za 1 punkt. Próg zdania części praktycznej to 75%, czyli 26 punktów (75% z 34 to 25,5, zaokrąglone w górę) - można stracić 8 kryteriów i nadal zdać. Przy każdym kroku jest napisane, które kryteria spełnia.
Suwak i strzałki obok niego - albo ←→ na klawiaturze - przechodzą krok po kroku; wyjaśnienie, pliki i podgląd zmieniają się razem z krokiem.
Lista „Etap” przenosi od razu do wybranego etapu.
„Rozwiązuję samodzielnie” chowa rozwiązanie kroku - najpierw własna próba, potem odsłonięcie.
„Tryb prezentacji” pokazuje same kroki, bez menu strony - na rzutnik.
Etap 1: Baza danych
Kroki 1-7 · po tym etapie masz 6 z 34 kryteriów (pkt)
Krok 1: Folder zdającego i archiwum pliki3.zip
ok. 2 min
Polecenie z arkusza
Należy utworzyć folder o nazwie odpowiadającej numerowi PESEL zdającego lub w przypadku jego braku innemu numerowi, którym został podpisany arkusz. Archiwum należy rozpakować do tego folderu.
Na pulpicie tworzysz folder nazwany numerem PESEL - w tym rozwiązaniu w jego miejscu stoi imię i nazwisko autora, Bartosz Bryniarski. Archiwum pliki3.zip rozpakowujesz do tego folderu, podając hasło ##Pogotowi3$ (dwa krzyżyki na początku, cyfra 3 zamiast litery i znak dolara na końcu). W środku są dwa pliki: baza3.sql (tabele do importu) i obraz.jpg (zdjęcie karetki).
Do tego folderu trafia wszystko, co powstanie: zrzuty, kwerendy.txt, pliki strony, stylów i skryptu.
Typowe błędy
Pliki zapisane poza folderem zdającego (np. tylko w htdocs) nie trafią na płytę - a ocenia się tylko to, co jest na płycie.
Krok 2: XAMPP i baza ee09
ok. 2 min
Polecenie z arkusza
Uruchom usługi MySQL i Apache za pomocą XAMPP Control Panel. Za pomocą narzędzia phpMyAdmin wykonaj podane operacje na bazie danych: Utwórz bazę danych o nazwie ee09
W XAMPP Control PanelStart przy Apache i MySQL, w przeglądarce http://localhost/phpmyadmin. Nowa w lewym panelu, nazwa ee09 (małe litery, dwie cyfry 0 i 9), porównywanie np. utf8mb4_polish_ci, Utwórz.
Typowe błędy
Nazwa bazy musi brzmieć dokładnie ee09 - skrypt łączy się z bazą po nazwie (R.5.1), a klucz sprawdza import do tej bazy (R.1.1). Litera O zamiast cyfry 0 to inna baza.
Krok 3: Import pliku baza3.sql i zrzut import.png
Kryteria:
R.1.1 Wykonano import tabel do bazy danych ee09 , czynność udokumentowano plikiem o nazwie import w formacie PNG
ok. 3 min
Polecenie z arkusza
Do bazy ee09 zaimportuj tabele z pliku baza3.sql z rozpakowanego archiwum. Wykonaj zrzut ekranu po imporcie. Zrzut zapisz w folderze z numerem PESEL lub w przypadku jego braku w folderze z innym numerem, którym został podpisany arkusz, w formacie PNG i nazwij import. Nie kadruj zrzutu. Powinien on obejmować cały ekran monitora, z widocznym paskiem zadań. Na zrzucie powinny być widoczne elementy wskazujące na poprawnie wykonany import tabel
Zaznacz bazę ee09, karta Import, Wybierz plik → baza3.sql, Wykonaj. Po komunikacie „Import zakończył się sukcesem” w lewym panelu jest 12 tabel - zadanie używa trzech: ratownicy (4 zespoły), dyspozytorzy (4 osoby) i zgloszenia (7 zgłoszeń). Reszta to tabele z innych zadań tej sesji.
Zrzut całego ekranu z komunikatem i listą tabel zapisz jako import.png. Plik tworzy tabele z kodowaniem latin1 - zostaje tak, jak jest w archiwum.
Typowe błędy
Ten zrzut ma format PNG, zrzuty zapytań - JPEG. Wykadrowany zrzut albo zrzut bez paska zadań nie jest oceniany (uwaga w kluczu przy R.1).
Podgląd strony po tym kroku
Krok 4: Zapytanie 1: nowy zespół karetki 20
Kryteria: ,
R.1.2 Zapisano plik tekstowy o nazwie kwerendy zawierający co najmniej jedno zapytanie SQL, wynikające z treści zadania
R.1.3 Utworzono zapytanie 1 dodające rekord do tabeli ratownicy o kolejnych wartościach pól : NULL, 20, Adam Nowak, Jan Kowalski, Anna Nowakowska. Możliwe również zamiast NULL pominięcie pola id. W pliku z kwerendami lub na zrzucie istnieje zapis np.: INSERT INTO ratownicy VALUES (NULL, 20, 'Adam Nowak', 'Jan Kowalski', 'Anna Nowakowska'); oraz wynik działania zapytania udokumentowano zrzutem, na którym jest widoczne poprawne wykonane zapytanie lub tabela z dodanymi danymi
ok. 4 min
Polecenie z arkusza
Zapytanie 1: dodające rekord do tabeli ratownicy o wartościach: nrKaretki - 20, ratownicy, kolejno - Adam Nowak, Jan Kowalski, Anna Nowakowska. Baza powinna sama nadać wartość pola id dla tabeli
Zaznacz bazę ee09 i otwórz kartę SQL. Zapytanie po kolei:
INSERT INTO ratownicy - do której tabeli,
VALUES (NULL, ...) - wartości dla wszystkich pięciu kolumn w kolejności z tabeli: id, nrKaretki, ratownik1, ratownik2, ratownik3. NULL w kolumnie id z AUTO_INCREMENT oznacza „nadaj sam” - tak baza „sama nadaje wartość pola id”,
numer karetki 20 jako liczba (kolumna typu INT), imiona i nazwiska w apostrofach.
Wynik: „1 wiersz wstawiony”, nowy zespół ma id 5 (w tabeli były cztery). Zapytanie kopiujesz do pliku kwerendy.txt w folderze zdającego (R.1.2), a zrzut całego ekranu zapisujesz jako kw1.jpg - na zrzucie widać komunikat i tabelę z dodanym rekordem.
Typowe błędy
Bez listy kolumn trzeba podać wartość dla każdej kolumny - pominięcie NULL na początku daje błąd #1136 (liczba kolumn nie odpowiada liczbie wartości). Wpisanie konkretnego id, np. 5, odbiera punkt - arkusz każe nadać je bazie.
Krok 5: Zapytanie 2: zgłoszenia dyspozytora o id 4
Kryteria:
R.1.4 Utworzono zapytanie 2 wybierające jedynie pola id, adres oraz ratownicy_id z tabeli zgloszenia, dla pola dyspozytorzy_id = 4. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT id, adres, ratownicy_id FROM zgloszenia WHERE dyspozytorzy_id = 4; oraz wynik działania zapytania udokumentowano zrzutem, na którym widoczne są jedynie pola id, adres i ratownicy_id dla dokładnie 3 rekordów o id = 1, 2, 6
ok. 2 min
Polecenie z arkusza
Zapytanie 2: wybierające jedynie pola id, adres oraz ratownicy_id z tabeli zgloszenia, dla zgłoszeń przyjętych przez dyspozytora o id 4
SELECT id, adres, ratownicy_id - tylko trzy kolumny, „jedynie” wyklucza SELECT *,
FROM zgloszenia,
WHERE dyspozytorzy_id = 4 - „dyspozytor o id 4” to w tabeli zgłoszeń kolumna dyspozytorzy_id (klucz obcy do tabeli dyspozytorzy), a nie id zgłoszenia. Relacja nie jest tu potrzebna - numer dyspozytora jest w samej tabeli zgłoszeń.
Wynik: 3 zgłoszenia o id 1, 2 i 6 (Marszałkowska, Postępu i Nowowiejska) - dokładnie te z klucza. Dyspozytorem o id 4 jest Jan Winny. Zrzut: kw2.jpg.
Typowe błędy
WHERE id = 4 zwraca jedno zgłoszenie - to o numerze 4 - zamiast zgłoszeń przyjętych przez dyspozytora numer 4.
kwerendy.txtTekstzmienione: 3 linie
-- Zapytanie 1INSERT INTO ratownicy VALUES (NULL, 20, 'Adam Nowak', 'Jan Kowalski', 'Anna Nowakowska');-- Zapytanie 2SELECT id, adres, ratownicy_id FROM zgloszenia WHERE dyspozytorzy_id = 4;
Podgląd strony po tym kroku
Krok 6: Zapytanie 3: użytkownik adam z hasłem
Kryteria:
R.1.5 Utworzono zapytanie 3 tworzące użytkownika adam z hasłem Adam6& W pliku z kwerendami lub na zrzucie istnieje zapis np.: CREATE USER 'adam' IDENTIFIED BY 'Adam6&'; (możliwe też z @'localhost') oraz wynik działania zapytania udokumentowano zrzutem wskazującym na dodanie tego użytkownika z hasłem
ok. 3 min
Polecenie z arkusza
Zapytanie 3: tworzące użytkownika adam z hasłem Adam6&
CREATE USER 'adam' - konto użytkownika serwera bazy. Arkusz nie podaje hosta, więc zostaje domyślny % - logowanie z dowolnego komputera. Klucz przyjmuje też 'adam'@'localhost',
IDENTIFIED BY 'Adam6&' - hasło w apostrofach; wielka litera, cyfra i znak & są jego częścią. Baza nie przechowuje hasła wprost, tylko jego skrót.
Samo CREATE USER kończy się komunikatem „MySQL zwrócił pusty wynik”. Żeby zrzut kw3.jpg wskazywał na dodanego użytkownika z hasłem, w tej samej karcie SQL dopisz pod spodem zapytanie sprawdzające SELECT User, Host, Password FROM mysql.user WHERE User = 'adam'; - phpMyAdmin pokaże wiersz z kontem adam, hostem % i skrótem hasła *C3DAB70D…. Konto widać też w zakładce Konta użytkowników. Do kwerendy.txt trafia tylko zapytanie 3.
Typowe błędy
Hasło bez apostrofów (IDENTIFIED BY Adam6&) to błąd składni. Puste pole Password na zrzucie oznacza konto bez hasła - wtedy brak punktu.
kwerendy.txtTekstzmienione: 3 linie
-- Zapytanie 1INSERT INTO ratownicy VALUES (NULL, 20, 'Adam Nowak', 'Jan Kowalski', 'Anna Nowakowska');-- Zapytanie 2SELECT id, adres, ratownicy_id FROM zgloszenia WHERE dyspozytorzy_id = 4;-- Zapytanie 3CREATE USER 'adam' IDENTIFIED BY 'Adam6&';
Podgląd strony po tym kroku
Krok 7: Zapytanie 4: prawa CREATE, ALTER i DROP do tabeli ratownicy
Kryteria:
R.1.6 Utworzono zapytanie 4 nadające dla użytkownika adam zestaw praw CREATE, ALTER, DROP albo zestaw praw INSERT, UPDATE, DELETE dla tabeli ratownicy . W pliku z kwerendami lub na zrzucie istnieje zapis np.: GRANT CREATE, ALTER, DROP ON ratownicy TO 'adam'; lub GRANT INSERT, UPDATE, DELETE ON ratownicy TO 'adam'; oraz wynik działania zapytania udokumentowano zrzutem wskazującym dodanie zestawu praw na tabeli ratownicy dla użytkownika adam
ok. 3 min
Polecenie z arkusza
Zapytanie 4: nadające dla użytkownika adam prawa tworzenia obiektu, edycji struktury obiektu i usuwania obiektu dla tabeli ratownicy
Trzy opisy z arkusza to trzy uprawnienia SQL:
„tworzenie obiektu” - CREATE,
„edycja struktury obiektu” - ALTER (zmiana kolumn, a nie danych),
„usuwanie obiektu” - DROP.
GRANT CREATE, ALTER, DROP ON ratownicy TO 'adam' - nazwa tabeli bez nazwy bazy oznacza tabelę w bazie, która jest zaznaczona, czyli ee09.ratownicy. Zrzut kw4.jpg: pod zapytaniem dopisz SHOW GRANTS FOR 'adam'; - drugi wiersz wyniku to GRANT CREATE, DROP, ALTER ONee09.ratownicyTOadam@%``. Kolejność praw wypisuje sam serwer.
Klucz przyjmuje też zestaw INSERT, UPDATE, DELETE (opis „tworzenie, edycja, usuwanie” można odczytać jako operacje na rekordach), ale słowo „obiekt” i „edycja struktury” wskazują na tabelę jako obiekt bazy, a więc na CREATE, ALTER i DROP.
Typowe błędy
Zapytanie 4 wykonane przed zapytaniem 3 kończy się błędem - konto adam jeszcze nie istnieje. Zapis ON ee09.* daje prawa do całej bazy, a arkusz mówi o jednej tabeli.
kwerendy.txtTekstzmienione: 3 linie
-- Zapytanie 1INSERT INTO ratownicy VALUES (NULL, 20, 'Adam Nowak', 'Jan Kowalski', 'Anna Nowakowska');-- Zapytanie 2SELECT id, adres, ratownicy_id FROM zgloszenia WHERE dyspozytorzy_id = 4;-- Zapytanie 3CREATE USER 'adam' IDENTIFIED BY 'Adam6&';-- Zapytanie 4GRANT CREATE, ALTER, DROP ON ratownicy TO 'adam';
Podgląd strony po tym kroku
Etap 2: Grafika i strona HTML
Kroki 8-25 · po tym etapie masz 18 z 34 kryteriów (pkt)
Krok 8: Zdjęcie karetki: wysokość 100 px
Kryteria:
R.2.1 Plik obraz.jpg przeskalowano z zachowaniem proporcji tak, że jego wysokość wynosi dokładnie 100 px, odpowiadająca temu szerokość wynosi 167 px ±5 px
ok. 2 min
Polecenie z arkusza
Plik obraz.jpg, wypakowany z archiwum, należy przeskalować z zachowaniem proporcji tak, aby jego wysokość wynosiła dokładnie 100 px
Oryginał ma 566 × 339 px. W GIMP-ie Obraz → Skaluj obraz, łańcuch między szerokością a wysokością zamknięty, wysokość 100 px - szerokość przelicza się na 566 × 100 / 339 = 167 px (klucz: 167 px ±5). Zapis: Plik → Nadpisz obraz.jpg. Wysokość równa wysokości bloków banera (100 px) - zdjęcie wypełni prawy blok od góry do dołu.
Typowe błędy
Otwarty łańcuch i wpisana sama wysokość zgniatają obraz (566 × 100 px) - proporcje nie są zachowane i punkt przepada.
Podgląd strony po tym kroku
Krok 9: Plik ratownicy.html i kodowanie polskich znaków
Kryteria:
R.2.2 Witrynę internetową zapisano w pliku HTML o nazwie ratownicy oraz zastosowano właściwy standard kodowania polskich znaków
ok. 2 min
Polecenie z arkusza
Składa się ze strony o nazwie ratownicy.html oraz skryptu dodanie.php. Poniższe wymagania dotyczą tylko pliku ratownicy.html. Zastosowany właściwy standard kodowania polskich znaków
Nowy plik ratownicy.html w folderze zdającego. <meta charset="UTF-8"> w <head> i plik zapisany w UTF-8 - nazwa pliku i kodowanie to razem R.2.2. Skrypt dodanie.php powstanie na końcu, po stylach.
Typowe błędy
W Notatniku przy Zapisz jako typ pliku „Wszystkie pliki” - inaczej powstanie ratownicy.html.txt.
R.3.5 Strona zawiera działające połączenie z zewnętrznym arkuszem stylów o nazwie styl3.css , formatowanie pochodzi jedynie z tego arkusza Uwaga: kryterium to nie jest spełnione również, gdy źle przypisano co najmniej jeden selektor do bloku (np. kropka zamiast #)
ok. 1 min
Polecenie z arkusza
Arkusz stylów w pliku o nazwie styl3.css prawidłowo połączony z kodem strony
<link rel="stylesheet" href="styl3.css"> w <head>. Plik stylów powstanie po HTML-u; całe formatowanie będzie tylko w nim (R.3.5).
Typowe błędy
Klucz odbiera R.3.5 także wtedy, gdy choć jeden selektor nie trafia w blok - np. kropka w CSS zamiast # przy bloku z identyfikatorem.
R.2.4 Wygląd strony zdefiniowano dzieląc ją na bloki: trzy bloki banera, blok główny, trzy bloki stopki. Zastosowano znaczniki sekcji
ok. 2 min
Polecenie z arkusza
Podział strony na bloki: na górze trzy bloki banera: lewy, środkowy, prawy, poniżej blok główny, na dole trzy bloki stopki: lewy, środkowy, prawy. Podział zrealizowany za pomocą znaczników sekcji tak, aby po uruchomieniu w przeglądarce wygląd układu bloków był zgodny z Obrazem 2
Siedem znaczników <section> w kolejności z obrazu 2 (R.2.4). Każdy ma identyfikator, bo w CSS bloki dostaną różne szerokości: banner-left, banner-middle, banner-right, main, footer-left, footer-middle i footer-right (nazwy po angielsku - arkusz ich nie narzuca). Ułożenie bloków obok siebie zrobi CSS.
Krok 14: Środkowy blok banera: kontakt z łamaniem linii
ok. 1 min
Polecenie z arkusza
Zawartość środkowego bloku banera: akapit (paragraf) o treści „Kontakt: 022 222 11 333”, łamanie linii po słowie „Kontakt:”
Jeden paragraf <p>, a w środku znacznik <br> zaraz po dwukropku - numer telefonu przechodzi do nowej linii, jak na obrazie 2. Spacja między „Kontakt:” a numerem nie jest potrzebna, bo i tak zaczyna się nowa linia.
Typowe błędy
Dwa osobne paragrafy zamiast <br> to dwa akapity, a arkusz wymaga jednego akapitu z łamaniem linii.
Krok 15: Prawy blok banera: zdjęcie z tekstem alternatywnym
Kryteria:
R.2.7 W prawym bloku banera umieszczono obraz.jpg wraz z tekstem alternatywnym "Ratownicy"
ok. 1 min
Polecenie z arkusza
Zawartość prawego bloku banera: obraz.jpg z tekstem alternatywnym o treści: „Ratownicy”
<img> z przeskalowanym plikiem i alt="Ratownicy" - tekst, który czytnik ekranu przeczyta zamiast zdjęcia i który pokaże się, gdy plik się nie wczyta (R.2.7). Znacznik <img> w HTML5 nie ma znacznika zamykającego.
Krok 17: Formularz wysyłający dane metodą POST do dodanie.php
Kryteria:
R.3.4 Formularz wysyła dane metodą POST do pliku dodanie.php
ok. 2 min
Polecenie z arkusza
Formularz wysyłający dane metodą POST do pliku dodanie.php zawierający pola
action="dodanie.php" - adres, pod który przeglądarka wyśle dane po kliknięciu przycisku wysyłającego,
method="post" - dane jadą w treści żądania, a nie w adresie strony; w PHP odczyta je tablica $_POST (R.3.4).
Formularz sprawdza się tylko przez serwer: stronę otwierasz jako http://localhost/…/ratownicy.html, a nie dwuklikiem z dysku - inaczej przeglądarka pokaże kod dodanie.php zamiast go wykonać.
Typowe błędy
method="get" dopisze dane do adresu (dodanie.php?nrKaretki=...), a skrypt czytający $_POST nic nie dostanie.
Pole edycyjne typu numerycznego podpisane powyżej tekstem: „Numer karetki:”
„Podpisane powyżej” - napis, złamanie linii <br>, a pole w nowej linii, jak na obrazie 2. type="number" daje pole, do którego da się wpisać tylko liczbę, ze strzałkami w górę i w dół. name="nrKaretki" - tak jak kolumna w tabeli ratownicy - to klucz, pod którym wartość trafi do PHP: $_POST['nrKaretki'].
Typowe błędy
type="text" wygląda podobnie, ale klucz wymaga, by pierwsze pole było typu number (R.3.3).
Krok 19: Trzy pola na imiona i nazwiska ratowników
ok. 2 min
Polecenie z arkusza
Trzy pola edycyjne podpisane powyżej tekstem, kolejno: „Imię i nazwisko pierwszego ratownika:”, „Imię i nazwisko drugiego ratownika:”, „Imię i nazwisko trzeciego ratownika:”
Ten sam układ trzy razy: napis, <br>, pole tekstowe, <br>. Nazwy pól ratownik1, ratownik2 i ratownik3 odpowiadają kolumnom tabeli - łatwo w skrypcie nie pomylić kolejności.
ratownicy.htmlHTMLzmienione: 6 linii
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <title>Zespoły ratownicze</title> <linkrel="stylesheet"href="styl3.css"></head><body> <sectionid="banner-left"> <h2>Dodanie zespołu ratowniczego</h2> </section> <sectionid="banner-middle"> <p>Kontakt:<br>022 222 11 333</p> </section> <sectionid="banner-right"> <imgsrc="obraz.jpg"alt="Ratownicy"> </section> <sectionid="main"> <h3>Dodaj nowy zespół</h3> <formaction="dodanie.php"method="post"> Numer karetki:<br> <inputtype="number"name="nrKaretki"><br> Imię i nazwisko pierwszego ratownika:<br> <inputtype="text"name="ratownik1"><br> Imię i nazwisko drugiego ratownika:<br> <inputtype="text"name="ratownik2"><br> Imię i nazwisko trzeciego ratownika:<br> <inputtype="text"name="ratownik3"><br> </form> </section> <sectionid="footer-left"> </section> <sectionid="footer-middle"> </section> <sectionid="footer-right"> </section></body></html>
Podgląd strony po tym kroku (ratownicy.html)
Krok 20: Przycisk „CZYŚĆ”
ok. 1 min
Polecenie z arkusza
Przycisk czyszczący zawartość formularza z etykietą „CZYŚĆ”
<input type="reset"> przywraca polom formularza wartości początkowe - tutaj puste. Napis na przycisku to value. Nie potrzeba do tego ani linijki JavaScriptu.
ratownicy.htmlHTMLzmienione: 1 linia
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <title>Zespoły ratownicze</title> <linkrel="stylesheet"href="styl3.css"></head><body> <sectionid="banner-left"> <h2>Dodanie zespołu ratowniczego</h2> </section> <sectionid="banner-middle"> <p>Kontakt:<br>022 222 11 333</p> </section> <sectionid="banner-right"> <imgsrc="obraz.jpg"alt="Ratownicy"> </section> <sectionid="main"> <h3>Dodaj nowy zespół</h3> <formaction="dodanie.php"method="post"> Numer karetki:<br> <inputtype="number"name="nrKaretki"><br> Imię i nazwisko pierwszego ratownika:<br> <inputtype="text"name="ratownik1"><br> Imię i nazwisko drugiego ratownika:<br> <inputtype="text"name="ratownik2"><br> Imię i nazwisko trzeciego ratownika:<br> <inputtype="text"name="ratownik3"><br> <inputtype="reset"value="CZYŚĆ"> </form> </section> <sectionid="footer-left"> </section> <sectionid="footer-middle"> </section> <sectionid="footer-right"> </section></body></html>
Podgląd strony po tym kroku (ratownicy.html)
Krok 21: Przycisk „DODAJ”
Kryteria: ,
R.2.8 W bloku głównym umieszczono formularz z czterema polami edycyjnymi oraz dwoma przyciskami "CZYŚĆ" i "DODAJ"
R.3.3 Pierwsze pole formularza jest typu number oraz pierwszy przycisk czyści zawartość formularza, drugi przycisk wysyła dane z formularza (input z typem submit lub button)
ok. 1 min
Polecenie z arkusza
Przycisk wysyłający zawartość formularza z etykietą „DODAJ”
<input type="submit"> wysyła formularz pod adres z action. Formularz jest kompletny: cztery pola edycyjne i dwa przyciski (R.2.8); pierwsze pole jest typu number, pierwszy przycisk czyści, drugi wysyła (R.3.3).
Typowe błędy
<input type="button"> wygląda tak samo, ale niczego nie wysyła - brak punktu R.3.3. Kolejność ma znaczenie: klucz mówi o pierwszym przycisku czyszczącym i drugim wysyłającym.
ratownicy.htmlHTMLzmienione: 1 linia
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <title>Zespoły ratownicze</title> <linkrel="stylesheet"href="styl3.css"></head><body> <sectionid="banner-left"> <h2>Dodanie zespołu ratowniczego</h2> </section> <sectionid="banner-middle"> <p>Kontakt:<br>022 222 11 333</p> </section> <sectionid="banner-right"> <imgsrc="obraz.jpg"alt="Ratownicy"> </section> <sectionid="main"> <h3>Dodaj nowy zespół</h3> <formaction="dodanie.php"method="post"> Numer karetki:<br> <inputtype="number"name="nrKaretki"><br> Imię i nazwisko pierwszego ratownika:<br> <inputtype="text"name="ratownik1"><br> Imię i nazwisko drugiego ratownika:<br> <inputtype="text"name="ratownik2"><br> Imię i nazwisko trzeciego ratownika:<br> <inputtype="text"name="ratownik3"><br> <inputtype="reset"value="CZYŚĆ"> <inputtype="submit"value="DODAJ"> </form> </section> <sectionid="footer-left"> </section> <sectionid="footer-middle"> </section> <sectionid="footer-right"> </section></body></html>
Podgląd strony po tym kroku (ratownicy.html)
Krok 22: Lewy blok stopki: odnośnik do kwerendy.txt
Kryteria:
R.3.2 Po wybraniu odnośnika "Zobacz kwerendy" otwiera się lub pobiera plik kwerendy
ok. 1 min
Polecenie z arkusza
Zawartość lewego bloku stopki: odnośnik o treści „Zobacz kwerendy”, jego kliknięcie otwiera lub pobiera plik kwerendy.txt
href="kwerendy.txt" - ścieżka względna: plik leży w tym samym folderze co strona. Przeglądarka otworzy go jako tekst albo zaproponuje pobranie (R.3.2). Dlatego kwerendy.txt musi być w folderze strony.
ratownicy.htmlHTMLzmienione: 1 linia
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <title>Zespoły ratownicze</title> <linkrel="stylesheet"href="styl3.css"></head><body> <sectionid="banner-left"> <h2>Dodanie zespołu ratowniczego</h2> </section> <sectionid="banner-middle"> <p>Kontakt:<br>022 222 11 333</p> </section> <sectionid="banner-right"> <imgsrc="obraz.jpg"alt="Ratownicy"> </section> <sectionid="main"> <h3>Dodaj nowy zespół</h3> <formaction="dodanie.php"method="post"> Numer karetki:<br> <inputtype="number"name="nrKaretki"><br> Imię i nazwisko pierwszego ratownika:<br> <inputtype="text"name="ratownik1"><br> Imię i nazwisko drugiego ratownika:<br> <inputtype="text"name="ratownik2"><br> Imię i nazwisko trzeciego ratownika:<br> <inputtype="text"name="ratownik3"><br> <inputtype="reset"value="CZYŚĆ"> <inputtype="submit"value="DODAJ"> </form> </section> <sectionid="footer-left"> <ahref="kwerendy.txt">Zobacz kwerendy</a> </section> <sectionid="footer-middle"> </section> <sectionid="footer-right"> </section></body></html>
Podgląd strony po tym kroku (ratownicy.html)
Krok 23: Środkowy blok stopki: nagłówek piątego stopnia
Kryteria:
R.2.5 W lewym bloku banera zapisano nagłówek h2: "Dodanie zespołu ratowniczego" oraz w bloku głównym zapisano nagłówek h3: "Dodaj nowy zespół" oraz w środkowym bloku stopki nagłówek h5: "Przypominamy numery alarmowe" oraz zapisano przynajmniej jeden paragraf
ok. 1 min
Polecenie z arkusza
Zawartość środkowego bloku stopki: Nagłówek piątego stopnia o treści: „Przypominamy numery alarmowe”
<h5> - przeglądarka rysuje go mniejszą czcionką niż tekst akapitu, jak na obrazie 2. Strona ma teraz nagłówki <h2>, <h3> i <h5> oraz paragraf w banerze (R.2.5).
ratownicy.htmlHTMLzmienione: 1 linia
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <title>Zespoły ratownicze</title> <linkrel="stylesheet"href="styl3.css"></head><body> <sectionid="banner-left"> <h2>Dodanie zespołu ratowniczego</h2> </section> <sectionid="banner-middle"> <p>Kontakt:<br>022 222 11 333</p> </section> <sectionid="banner-right"> <imgsrc="obraz.jpg"alt="Ratownicy"> </section> <sectionid="main"> <h3>Dodaj nowy zespół</h3> <formaction="dodanie.php"method="post"> Numer karetki:<br> <inputtype="number"name="nrKaretki"><br> Imię i nazwisko pierwszego ratownika:<br> <inputtype="text"name="ratownik1"><br> Imię i nazwisko drugiego ratownika:<br> <inputtype="text"name="ratownik2"><br> Imię i nazwisko trzeciego ratownika:<br> <inputtype="text"name="ratownik3"><br> <inputtype="reset"value="CZYŚĆ"> <inputtype="submit"value="DODAJ"> </form> </section> <sectionid="footer-left"> <ahref="kwerendy.txt">Zobacz kwerendy</a> </section> <sectionid="footer-middle"> <h5>Przypominamy numery alarmowe</h5> </section> <sectionid="footer-right"> </section></body></html>
Podgląd strony po tym kroku (ratownicy.html)
Krok 24: Lista numerowana numerów alarmowych
Kryteria:
R.2.6 W środkowym bloku stopki umieszczono listę numerowaną z dwoma elementami, zastosowano znaczniki <ol>, <li> oraz ich zamknięcia
Lista numerowana (uporządkowana) to <ol>, każdy numer w <li> (R.2.6). Na obrazie 2 punktory to litery „a.” i „b.” - to zrobi CSS, w HTML-u zostaje zwykła lista numerowana.
Typowe błędy
<ul> to lista punktowana - klucz wymaga <ol> i <li> wraz z ich zamknięciami. Litery a, b nie wpisuje się ręcznie do treści elementów.
ratownicy.htmlHTMLzmienione: 4 linie
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <title>Zespoły ratownicze</title> <linkrel="stylesheet"href="styl3.css"></head><body> <sectionid="banner-left"> <h2>Dodanie zespołu ratowniczego</h2> </section> <sectionid="banner-middle"> <p>Kontakt:<br>022 222 11 333</p> </section> <sectionid="banner-right"> <imgsrc="obraz.jpg"alt="Ratownicy"> </section> <sectionid="main"> <h3>Dodaj nowy zespół</h3> <formaction="dodanie.php"method="post"> Numer karetki:<br> <inputtype="number"name="nrKaretki"><br> Imię i nazwisko pierwszego ratownika:<br> <inputtype="text"name="ratownik1"><br> Imię i nazwisko drugiego ratownika:<br> <inputtype="text"name="ratownik2"><br> Imię i nazwisko trzeciego ratownika:<br> <inputtype="text"name="ratownik3"><br> <inputtype="reset"value="CZYŚĆ"> <inputtype="submit"value="DODAJ"> </form> </section> <sectionid="footer-left"> <ahref="kwerendy.txt">Zobacz kwerendy</a> </section> <sectionid="footer-middle"> <h5>Przypominamy numery alarmowe</h5> <ol> <li>112</li> <li>999</li> </ol> </section> <sectionid="footer-right"> </section></body></html>
Podgląd strony po tym kroku (ratownicy.html)
Krok 25: Prawy blok stopki: autor strony
ok. 1 min
Polecenie z arkusza
Zawartość prawego bloku stopki: akapit (paragraf) o treści: „Autor”, łamanie linii, dalej wstawiony numer PESEL zdającego lub w przypadku jego braku inny numer, którym został podpisany arkusz
Na egzaminie po <br> wpisujesz swój numer PESEL. W tym rozwiązaniu w jego miejscu stoi imię i nazwisko autora: Bartosz Bryniarski. HTML jest kompletny - teraz arkusz stylów.
ratownicy.htmlHTMLzmienione: 1 linia
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <title>Zespoły ratownicze</title> <linkrel="stylesheet"href="styl3.css"></head><body> <sectionid="banner-left"> <h2>Dodanie zespołu ratowniczego</h2> </section> <sectionid="banner-middle"> <p>Kontakt:<br>022 222 11 333</p> </section> <sectionid="banner-right"> <imgsrc="obraz.jpg"alt="Ratownicy"> </section> <sectionid="main"> <h3>Dodaj nowy zespół</h3> <formaction="dodanie.php"method="post"> Numer karetki:<br> <inputtype="number"name="nrKaretki"><br> Imię i nazwisko pierwszego ratownika:<br> <inputtype="text"name="ratownik1"><br> Imię i nazwisko drugiego ratownika:<br> <inputtype="text"name="ratownik2"><br> Imię i nazwisko trzeciego ratownika:<br> <inputtype="text"name="ratownik3"><br> <inputtype="reset"value="CZYŚĆ"> <inputtype="submit"value="DODAJ"> </form> </section> <sectionid="footer-left"> <ahref="kwerendy.txt">Zobacz kwerendy</a> </section> <sectionid="footer-middle"> <h5>Przypominamy numery alarmowe</h5> <ol> <li>112</li> <li>999</li> </ol> </section> <sectionid="footer-right"> <p>Autor<br>Bartosz Bryniarski</p> </section></body></html>
Podgląd strony po tym kroku (ratownicy.html)
Etap 3: Styl CSS
Kroki 26-34 · po tym etapie masz 29 z 34 kryteriów (pkt)
Krok 26: Plik styl3.css: krój Arial dla całej strony
Kryteria:
R.4.1 Ustawiono domyślny krój czcionki dla całej strony na Arial (dla selektora * lub body lub html lub kontenera całej strony)
ok. 1 min
Polecenie z arkusza
Cechy formatowania CSS: Są zawarte wyłącznie w zewnętrznym arkuszu stylów. Domyślne dla całej strony: krój czcionki Arial
Nowy plik styl3.css w folderze zdającego - każda reguła tylko tutaj, bez atrybutów style w HTML-u. Selektor * z font-family: Arial obejmuje wszystkie elementy, także pola i przyciski formularza (R.4.1).
styl3.cssCSSnowy plik
* {font-family: Arial;}
Podgląd strony po tym kroku (ratownicy.html)
Krok 27: Wspólny styl bloków banera i stopki
Kryteria: ,
R.4.3 Ustawiono biały kolor czcionki dla wszystkich bloków banera i stopki
R.4.4 Ustawiono wysokość dla wszystkich bloków banera i stopki na 100px
ok. 2 min
Polecenie z arkusza
Wspólne dla wszystkich bloków banera i stopki: kolor tła SaddleBrown, biały kolor czcionki, wysokość 100 px
Sześć selektorów identyfikatorów po przecinku i jedna reguła. SaddleBrown to nazwa koloru CSS (brąz, #8B4513) - wielkość liter w nazwie koloru nie ma znaczenia. Wszystkie bloki banera i stopki mają biały tekst (R.4.3) i wysokość 100 px (R.4.4) - tyle co zdjęcie karetki.
Typowe błędy
Pominięty jeden blok w liście selektorów to brak punktów R.4.3 i R.4.4 - kryteria mówią o „wszystkich” blokach.
Krok 28: Lewe bloki: szerokość 55% i większa czcionka
Kryteria:
R.4.8 Ustawiono rozmiar czcionki 120% dla lewych bloków banera i stopki
ok. 1 min
Polecenie z arkusza
Dodatkowo dla lewego bloku banera i lewego bloku stopki: szerokość 55%, rozmiar czcionki 120%
Druga reguła dla tych samych bloków dokłada nowe właściwości do wspólnych. font-size: 120% powiększa tekst bloku o jedną piątą względem domyślnego - także nagłówek <h2> i odnośnik, bo ich rozmiar liczy się od rodzica (R.4.8).
Krok 30: Prawe bloki: szerokość 20% i tekst do prawej
Kryteria: ,
R.4.5 Ustawiono szerokość lewych bloków banera i stopki na 55%, środkowych bloków banera i stopki na 25% oraz prawych bloków banera i stopki na 20%
R.4.6 Ustawiono wyrównanie tekstu do prawej strony dla prawych bloków banera i stopki
ok. 1 min
Polecenie z arkusza
Dodatkowo dla prawego bloku banera i prawego bloku stopki: szerokość 20%, wyrównanie tekstu do prawej strony
Szerokości w każdym rzędzie: 55 + 25 + 20 = 100% (R.4.5). text-align: right dociska do prawej krawędzi i tekst stopki, i zdjęcie karetki - obraz jest elementem liniowym, więc wyrównanie tekstu też go przesuwa (R.4.6).
Krok 31: Blok główny: tło Snow i marginesy wewnętrzne
Kryteria: ,
R.4.2 Ustawiono kolor tła SaddleBrown dla wszystkich bloków banera i stopki oraz kolor Snow dla bloku głównego
R.4.7 Ustawiono dla bloku głównego marginesy wewnętrzne (padding): 70px
ok. 1 min
Polecenie z arkusza
Dla bloku głównego: kolor tła Snow, marginesy wewnętrzne 70 px
Snow to prawie biały kolor z odrobiną różu (#FFFAFA). Wszystkie kolory tła bloków są ustawione (R.4.2). Marginesy wewnętrzne to padding - odsuwają formularz od brzegów bloku o 70 px z każdej strony (R.4.7).
Typowe błędy
margin: 70px to margines zewnętrzny - odsunie cały blok od sąsiadów, a tło Snow się nie powiększy.
Krok 32: Odnośnik: kropkowana ramka, tło i wysokość linii
Kryteria:
R.4.9 Ustawiono styl odnośnika: obramowanie 2px dotted SaddleBrown, kolor tła Snow, kolor czcionki SaddleBrown, padding: 20px, wysokość linii 100px (dla selektora a lub indentyfikatora lub klasy)
ok. 2 min
Polecenie z arkusza
Dla odnośnika: obramowanie linią kropkowaną o szerokości 2 px i kolorze SaddleBrown, kolor tła Snow, kolor czcionki SaddleBrown, marginesy wewnętrzne 20 px, wysokość linii 100 px
Selektor znacznika a - odnośnik na stronie jest jeden (R.4.9):
border: 2px dotted SaddleBrown - szerokość, linia kropkowana, kolor,
tło Snow i tekst SaddleBrown - odwrotnie niż w bloku, dlatego odnośnik wygląda jak jasny przycisk na brązowym tle,
padding: 20px - odstęp tekstu od ramki,
line-height: 100px - wysokość linii równa wysokości bloku stopki, więc tekst odnośnika stoi w pionie mniej więcej pośrodku bloku, jak na obrazie 2.
Krok 33: Lista numerowana: małe litery jako punktory
Kryteria:
R.4.10 Ustawiono styl listy (list-style-type): mała litera jako punktor
ok. 1 min
Polecenie z arkusza
Dla listy numerowanej: punktor jako mała litera
list-style-type: lower-alpha - elementy listy dostają kolejno „a.”, „b.”, „c.” zamiast „1.”, „2.” (R.4.10). Wielkie litery to upper-alpha, a małe cyfry rzymskie - lower-roman.
R.3.1 Układ bloków po uruchomieniu strony w przeglądarce jest zgodny z Obrazem 2 w arkuszu egzaminacyjnym (prawidłowo zastosowano właściwości CSS układające bloki na stronie, np. float i clear albo display flex albo grid)
ok. 2 min
Polecenie z arkusza
Podział zrealizowany za pomocą znaczników sekcji tak, aby po uruchomieniu w przeglądarce wygląd układu bloków był zgodny z Obrazem 2
Sześć bloków banera i stopki dostaje float: left - w każdym rzędzie trzy bloki o szerokościach 55, 25 i 20% wypełniają razem całą szerokość strony.
Blok główny zajmuje całą szerokość i musi zacząć się pod banerem - stąd clear: both. Bez niego wsunąłby się pod pływające bloki banera. Bloki stopki stoją po bloku głównym, który nie pływa, więc same zaczynają nowy rząd (R.3.1). Klucz przyjmuje też flex albo grid - wersja nowoczesna pokazuje układ we flex.
Typowe błędy
Bez clear na bloku głównym formularz ląduje w jednym rzędzie z banerem, a tło Snow chowa się pod brązowymi blokami.
Kroki 35-39 · po tym etapie masz 34 z 34 kryteriów (pkt)
Krok 35: Plik dodanie.php i połączenie z bazą ee09
Kryteria:
R.5.1 Skrypt realizuje połączenie z serwerem bazy danych i wybór bazy ee09
ok. 3 min
Polecenie z arkusza
Napisany w języku PHP, w pliku dodanie.php. Skrypt łączy się z serwerem bazodanowym na localhost, użytkownik root bez hasła, baza danych o nazwie ee09
Nowy plik dodanie.php w folderze zdającego - ten sam, który wskazuje action formularza. Cały plik to skrypt między <?php a ?>.
Pierwsza instrukcja: mysqli_connect z tabeli 1 arkusza - kolejno serwer localhost, użytkownik root, puste hasło '' i nazwa bazy ee09. Połączenie trafia do zmiennej $connection, z której skorzystają kolejne funkcje (R.5.1). Podgląd pokazuje na razie formularz z ratownicy.html - po wysłaniu skrypt jeszcze niczego nie robi.
R.5.3 Skrypt pobiera dane z formularza za pomocą tablicy $_POST (lub za pomocą $_REQUEST gdy sprawdzono, że REQUEST_METHOD jest równe POST)
ok. 2 min
Polecenie z arkusza
Skrypt działa na danych przesłanych z formularza
Cztery wartości z formularza trafiają do zmiennych o tych samych nazwach. Kluczem w $_POST jest atrybut name pola: $_POST['nrKaretki'], $_POST['ratownik1'], $_POST['ratownik2'], $_POST['ratownik3'] (R.5.3). Tablica $_POST istnieje, bo formularz ma method="post".
Typowe błędy
Nazwa w nawiasie musi być identyczna z name w HTML-u, łącznie z wielkością liter: $_POST['nrkaretki'] nie znajdzie pola nrKaretki i PHP zgłosi ostrzeżenie „Undefined array key”.
Krok 37: Zmodyfikowane zapytanie 1 z danymi z formularza
Kryteria:
R.5.4 Skrypt wysyła do bazy danych zmodyfikowane zapytanie 1, jego wartości wypełnione są danymi z formularza. Należy sprawdzić w phpMyAdmin czy rekord został wstawiony
ok. 3 min
Polecenie z arkusza
Skrypt wysyła do bazy danych zapytanie wstawiające rekord do tabeli ratownicy z danymi pobranymi z formularza (zmodyfikowane zapytanie 1, opisane w punkcie „Operacje na bazie danych”)
Zapytanie 1 z kwerendy.txt, w którym w miejsce 20 i trzech nazwisk stoją zmienne. Numer karetki bez apostrofów ($nrKaretki), bo kolumna jest liczbowa, a nazwiska w apostrofach: '$ratownik1'. Pierwsze NULL zostaje: id nadaje baza. Całe zapytanie jest w cudzysłowie "…", więc PHP podstawia wartości zmiennych.
Treść zapytania trafia najpierw do zmiennej $query - skrypt wypisze ją w następnym kroku - a dopiero potem mysqli_query wysyła ją do bazy. Sprawdzenie, jak każe klucz (R.5.4): formularz z danymi 7, Marek Lis, Ewa Sowa, Piotr Kos i w phpMyAdmin nowy wiersz 5 - podgląd pokazuje tabelę po wysłaniu.
Typowe błędy
Zapytanie w apostrofach 'INSERT ... '$ratownik1' ...' - PHP nie podstawi zmiennych i do bazy pójdzie dosłowny napis $ratownik1 (albo błąd składni).
Tabela z archiwum ma kodowanie latin1, które nie zna liter ą, ć, ę, ł, ń, ś, ź, ż - ratownik Łukasz Żółć zapisał się jako „?ukasz ?ó??”. To nie jest błąd skryptu i nie traci się za to punktu: klucz sprawdza import pliku bez zmian, więc kodowania tabeli nie zmieniasz.
R.5.5 Skrypt wyświetla tekst: „Do bazy zostało wysłane zapytanie: <zapytanie>”, gdzie <zapytanie> oznacza treść zapytania, które zostało wysłane skryptem do bazy danych
ok. 2 min
Polecenie z arkusza
Skrypt wypisuje tekst: „Do bazy zostało wysłane zapytanie: <zapytanie>”, gdzie <zapytanie> oznacza treść zapytania, które zostało wysłane skryptem do bazy danych
echo z tą samą zmienną $query, którą dostała mysqli_query - dlatego na ekranie jest dokładnie to zapytanie, które poszło do bazy, z wartościami z formularza (R.5.5). Podgląd to prawdziwy wynik skryptu po wysłaniu formularza z danymi 7, Marek Lis, Ewa Sowa, Piotr Kos:
Wypisanie stałego tekstu zapytania z kwerendy.txt (z liczbą 20 i Adamem Nowakiem) nie spełnia R.5.5 - komunikat ma pokazać zapytanie z danymi z formularza.
dodanie.phpPHPzmienione: 1 linia
<?php$connection = mysqli_connect('localhost', 'root', '', 'ee09');$nrKaretki = $_POST['nrKaretki'];$ratownik1 = $_POST['ratownik1'];$ratownik2 = $_POST['ratownik2'];$ratownik3 = $_POST['ratownik3'];$query = "INSERT INTO ratownicy VALUES (NULL, $nrKaretki, '$ratownik1', '$ratownik2', '$ratownik3');";mysqli_query($connection, $query);echo"Do bazy zostało wysłane zapytanie: $query";?>
Podgląd strony po tym kroku (dodanie.php)
Krok 39: Zamknięcie połączenia z bazą
Kryteria:
R.5.2 Ostatnią operacją na bazie jest jej zamknięcie (zgodne ze składnią)
ok. 1 min
Polecenie z arkusza
Na końcu działania skrypt zamyka połączenie z serwerem.
mysqli_close($connection) jako ostatnia instrukcja skryptu - po zapytaniu i komunikacie (R.5.2). echo nie jest operacją na bazie, więc może stać przed zamknięciem. Skrypt spełnia wszystkie kryteria arkusza. Dalej trzy kroki o zabezpieczeniach - klucz ich nie wymaga.
Typowe błędy
mysqli_close przed mysqli_query sprawia, że zapytanie dostaje zamknięte połączenie i PHP kończy się błędem - a klucz wymaga, by zamknięcie było ostatnią operacją na bazie.
dodanie.phpPHPzmienione: 1 linia
<?php$connection = mysqli_connect('localhost', 'root', '', 'ee09');$nrKaretki = $_POST['nrKaretki'];$ratownik1 = $_POST['ratownik1'];$ratownik2 = $_POST['ratownik2'];$ratownik3 = $_POST['ratownik3'];$query = "INSERT INTO ratownicy VALUES (NULL, $nrKaretki, '$ratownik1', '$ratownik2', '$ratownik3');";mysqli_query($connection, $query);echo"Do bazy zostało wysłane zapytanie: $query";mysqli_close($connection);?>
Kroki 40-42 · po tym etapie masz 34 z 34 kryteriów (pkt)
Krok 40: Zabezpieczenie: liczba jako liczba, napisy ze znakami ucieczki
ok. 5 min
Polecenie z arkusza
Skrypt wysyła do bazy danych zapytanie wstawiające rekord do tabeli ratownicy z danymi pobranymi z formularza (zmodyfikowane zapytanie 1, opisane w punkcie „Operacje na bazie danych”)
Dane z formularza trafiają do zapytania wprost. Sprawdzone na wersji z poprzednich kroków:
puste pole numeru - zapytanie zaczyna się od VALUES (NULL, , 'Marek Lis'… i jest błędne składniowo. PHP 8.1 i nowsze zgłaszają wyjątek mysqli_sql_exception i zamiast strony widać „Fatal error” ze ścieżką pliku na serwerze; w PHP 8.0 z klucza skrypt po cichu nic nie zapisuje, a i tak wypisuje „wysłane zapytanie”,
nazwisko z apostrofem, np. Ewa O'Neill - apostrof kończy napis w SQL i zapytanie się rozpada,
SQL injection - w pole trzeciego ratownika wpisano Piotr Kos'), (NULL, 1, 'Fikcyjny', 'Fikcyjny', 'Fikcyjny') --. Do tabeli trafiły dwa rekordy: zespół z formularza i wymyślony zespół karetki 1.
Poprawka bez zmiany sensu komunikatu z R.5.5:
(int) zamienia numer karetki na liczbę całkowitą - puste pole albo tekst dają 0, a nie dziurę w zapytaniu,
mysqli_real_escape_string dopisuje ukośnik przed apostrofem i innymi znakami specjalnymi - O'Neill trafia do zapytania jako 'Ewa O\'Neill' i jest zwykłym napisem,
trim zdejmuje spacje z brzegów, a ?? '' chroni przed brakującym kluczem.
Podgląd: ten sam atak zapisuje już jeden rekord, w którym cały wpisany tekst jest nazwiskiem trzeciego ratownika. Zapytanie nadal powstaje w zmiennej $query, więc komunikat pokazuje dokładnie to, co poszło do bazy. Stare linie zostają w komentarzu. Na egzaminie wystarczy wersja wcześniejsza - klucz tego nie sprawdza.
Pełniejszym zabezpieczeniem są zapytania przygotowane (mysqli_prepare ze znakami ?), w których treść zapytania i dane jadą do bazy osobno. Pokazuje je wersja nowoczesna - razem z tym, jak wypisać wysłane zapytanie.
Typowe błędy
mysqli_real_escape_string wymaga otwartego połączenia - dlatego te linie stoją po mysqli_connect. Funkcja addslashes wygląda podobnie, ale nie zna kodowania połączenia.
Krok 41: Zabezpieczenie: htmlspecialchars przy wypisywaniu zapytania
ok. 3 min
Polecenie z arkusza
Skrypt wypisuje tekst: „Do bazy zostało wysłane zapytanie: <zapytanie>”, gdzie <zapytanie> oznacza treść zapytania, które zostało wysłane skryptem do bazy danych
Komunikat wypisuje dane wpisane przez użytkownika - to drugie miejsce ataku. Sprawdzone: w pole pierwszego ratownika wpisano <script>alert("XSS")</script>, a strona z wersji egzaminacyjnej wykonała ten skrypt, bo przeglądarka dostała go jako zwykły kod HTML. Zamiast okienka może to być skrypt, który wykrada ciasteczka sesji.
htmlspecialchars zamienia <, >, & i cudzysłowy na encje (<, >…) - przeglądarka pokazuje znaki, ale ich nie wykonuje. Zasada: escapowanie do SQL przy zapytaniu, htmlspecialcharsna wyjściu, tuż przed echo. Podgląd przy zwykłych danych wygląda tak samo jak wcześniej - w źródle strony apostrofy są teraz zapisane jako ', ale przeglądarka pokazuje je normalnie.
Typowe błędy
htmlspecialchars przed zapisem do bazy (zamiast przy wypisywaniu) zapisuje w tabeli < zamiast < - dane w bazie przestają być prawdziwe.
Zapytanie 3: tworzące użytkownika adam z hasłem Adam6&
Dwie rzeczy, które na egzaminie są w porządku, a w prawdziwym serwisie nie:
skrypt łączy się jako root bez hasła - administrator całego serwera baz danych. W XAMPP do nauki tak jest domyślnie, a arkusz tego wymaga (R.5.1). Na serwerze strona łączy się kontem z prawami tylko do potrzebnej tabeli, np. GRANT INSERT ON ee09.ratownicy TO … - wtedy nawet udane wstrzyknięcie nie usunie ani nie odczyta innych tabel,
konto adam z zapytania 3 dostało host %, czyli logowanie z dowolnego komputera, i krótkie hasło Adam6& (6 znaków, imię i cyfra). Konto, które zmienia strukturę tabel, ogranicza się do 'adam'@'localhost' i daje mu się długie losowe hasło.
Do plików egzaminacyjnych nic z tego nie przenosisz - zapytania i połączenie zostają takie, jak każe arkusz. Plik skryptu bez zmian.
Krok 43 · po tym etapie masz 34 z 34 kryteriów (pkt)
Krok 43: Plik przeglądarka.txt i nagranie płyty
ok. 5 min
Polecenie z arkusza
UWAGA: po zakończeniu pracy utwórz w folderze z numerem PESEL lub w przypadku jego braku w folderze z innym numerem, którym został podpisany arkusz plik tekstowy o nazwie przeglądarka.txt. Zapisz w nim nazwę przeglądarki internetowej, w której weryfikowano poprawność działania witryny. Nagraj płytę z rezultatami pracy.
W przeglądarka.txt wpisujesz nazwę przeglądarki, w której sprawdzasz stronę przez http://localhost/…/ratownicy.html.
W folderze z numerem zdającego muszą być: dodanie.php, import.png, kw1.jpg, kw2.jpg, kw3.jpg, kw4.jpg, kwerendy.txt, obraz.jpg, przeglądarka.txt, ratownicy.html i styl3.css (plik baza3.sql z archiwum może zostać). Nagraj płytę, sprawdź jej odczyt w obecności przewodniczącego zespołu nadzorującego i opisz ją numerem zdającego. Pusta lub nieczytelna płyta to zero punktów za wszystkie pięć rezultatów.
przeglądarka.txtTekstnowy plik
Google Chrome
Podgląd strony po tym kroku (dodanie.php)
Podgląd
Symulacja ekranu w przeglądarce - w Android Studio / Visual Studio wygląd może się nieco różnić.
To jedno z możliwych rozwiązań. Egzaminator ocenia spełnienie kryteriów z klucza odpowiedzi, a nie zgodność z tym kodem - inna, poprawna droga też daje punkty.
Autor rozwiązania: Bartosz Bryniarski. Licencja CC BY-NC 4.0 - kopiowanie i przeróbki do celów niekomercyjnych, z podaniem autora i źródła (link do tej strony) (zasady wykorzystania). Treść arkusza i klucza oceniania pochodzi z CKE.