Strona logowania i brak możliwości zalogowania się

Strona logowania i brak możliwości zalogowania się
KA
  • Rejestracja:ponad 5 lat
  • Ostatnio:około 5 lat
  • Postów:19
0

Dzień dobry w Nowym 2020 Roku.
Tak, przegrzebałam gugla i to dziesiątki razy, znalazłam metody strukturalne, obiektowe, PDO. Obejrzałam kilka filmików na jutubie. Spędziłam naście jak nie dziesiąt godzin klepiąc, poprawiając, testując i patrząc co wylezie w logach bazy danych php-fpm i bazy danych. Przejrzałam - z nadzieją - przyklejony na górze działu wątek ze Skryptami php ale nie znalazłam nic o logowaniu się do aplikacji WWW.
I jestem ciągle na początku - nie działa a wg paru tutoriali powinno.
Problem: po zalogowaniu nie widzę abym była zalogowana, nie wyświetla się pobrany login z bazy jako login zalogowanego użytkownika.

Apache: 2.4.41
PHP. 7.3.12
MariaDB: 10.3.20
Linux: Fedora 31

Żeby nie było - robię to dla siebie, to nie jest żadne zaliczenie do żadnej szkoły i nikt mi za to nie zapłaci.

Poniżej po kolei: struktura bazy danych i tabeli w niej, html z formularzem, i kolejne istotne pliki PHP.

Tabela:

Kopiuj
+-----------------------------+-----------+----------------------+----------------------------------+
| login                       | imie      | nazwisko             | pass                             |
+-----------------------------+-----------+----------------------+----------------------------------+
| jankowalski                 | Jan       | Kowalski             | 02ca50c0dc0680dd7325064d979d3f83 |
| januszwisniewki             | Janusz    | Wiśniewski           | 7e55e7adf9224de1d161ad1782baecf9 |
| grzegorzbrzeczyszczykiewicz | Grzegorz  | Brzęczyszczykiewicz  | 3e0ea140b7f6117df5cd574c72e7b196 |
| marcinkromchalski           | Marcin    | Krochmalski          | a61561482cba57209cd23031f23225cc |
| adambednarz                 | Adam      | Bednarz              | d41d8cd98f00b204e9800998ecf8427e |
| ireneuszkosmiderski         | Ireneusz  | Kośmiderski          | c4ca4238a0b923820dcc509a6f75849b |
| gustawwalczynski            | Gustaw    | Walczyński           | c81e728d9d4c2f636f067f89cc14862c |
| annanowakowska              | Anna      | Nowakowska           | eccbc87e4b5ce2fe28308fd9f2a7baf3 |
| katarzynaotowska            | Katarzyna | Otowska              | a87ff679a2f3e71d9181a67b7542122c |
| test                        | test      | testowy              | test                             |
| ts                          | test      | testowy              | 4d682ec4eed27c53849758bc13b6e179 |
| janek                       | Janek     | kowalczyk            |                                  |
+-----------------------------+-----------+----------------------+----------------------------------+

Formularz:

Kopiuj
<html>
<body>
<form action="form.php" method="post">
<tr>
<td>Login: </td><td> <input type="text" style="border:1px solid #000000" name="user" /></td>
<td>Pass: </td><td><input type="text" style="border:1px solid #000000" name="pass" /></td>
<td></td><td><input type="submit" style="border:1px solid #000000" value="Login" /></td>
</tr>
<br /><br />
</form>
</body>
</html>

form.php - dostaje dane z formularza

Kopiuj
<?php
    $dbhost     = "localhost";
    $dbname     = "site1";
    $dbuser     = "site1";
    $dbpass     = "site1";

    try {
        $db = new PDO('mysql:host=localhost;dbname=site1;charset=utf8mb4', 'site1', 'site1');
        $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);  
    } catch (PDOException $e) {
        echo "Connection failed : ". $e->getMessage();
    }

    $username = trim($_POST['user']);
    $password = trim($_POST['pass']);
    $msg = "";
    if($username == "") {
        echo "Brak podanego loginu!";
//        header("Location: http://localhost/testsec/form.html");
        die();
    }
    
    try {
        $query = "select * from admin where login='$username' and pass='$password'";
        $stmt = $db->prepare($query);
        $stmt->bindParam('username', $username, PDO::PARAM_STR);
        $stmt->bindValue('password', $password, PDO::PARAM_STR);
        $stmt->execute();
        $count = $stmt->rowCount();
        $row =   $stmt->fetch(PDO::FETCH_ASSOC);
        echo '<pre>'; print_r($array); echo '</pre>';

        if ($count == 1 && !empty($row)) { 
            $_SESSION['sess_user_id'] = $row['id'];
            $_SESSION['sess_user_name'] = $row['login'];
            $_SESSION['sess_name'] = $row['nazwisko'];
        } else {
            $msg = "Invalid username and/or password";
        }
    } catch (PDOException $e) {
        echo "Error :".$e->getMessage();
    }
    // debug:
    echo $username.'<br />';
    echo $password.'<br />';
    
    // jeśli się uda to przekierowuję
    header("Location: home.php");

home.php

Kopiuj
<?php
    session_start();
    if(isset($_SESSION['sess_user_id']) && $_SESSION['sess_user_id'] != "") {
        echo '<h2>Witaj '.$_SESSION['sess_name'].'</h2>';
        echo '<h4><a href="logout.php">Logout</a>';
    } else {
        header('location: form.html');
    }
?>

index.php

Kopiuj
<?php
    session_start();
    if(isset($_SESSION['sess_user_id']) && $_SESSION['sess_user_id'] != "") {
        echo '<h2>Witaj '.$_SESSION['sess_name'].'</h2>';
        echo '<h4><a href="logout.php">Logout</a>';
    } else {
        header('location: form.html');
    }
?>

logout.php

Kopiuj
<?php
    session_start();
    $_SESSION['sess_user_id'] = "";
    $_SESSION['sess_username'] = "";
    $_SESSION['sess_name'] = "";
    if (empty($_SESSION['sess_user_id'])) header("location: form.html");
?>
serek
  • Rejestracja:około 11 lat
  • Ostatnio:9 minut
  • Postów:1473
0

Pierwsze co mi do głowy przychodzi to to, że hasła masz zahashowane w bazie, a nie hashujesz hasła z formularza. Chociaż są 2 wyjątki: hasło dla usera test nie jest hashowane, a dla usera janek w ogóle nie istnieje^^

EDIT:
Bindowanie parametrów masz źle:

Kopiuj
$query = "select * from admin where login='$username' and pass='$password'";
$stmt = $db->prepare($query);
$stmt->bindParam('username', $username, PDO::PARAM_STR);
$stmt->bindValue('password', $password, PDO::PARAM_STR);

A powinno być coś takiego:

Kopiuj
$query = "select * from admin where login=:username and pass=:password";
$stmt = $db->prepare($query);
$stmt->bindParam(':username', $username, PDO::PARAM_STR);
$stmt->bindValue(':password', $password, PDO::PARAM_STR);

https://www.php.net/manual/en/pdostatement.bindparam.php

edytowany 1x, ostatnio: serek
KA
  • Rejestracja:ponad 5 lat
  • Ostatnio:około 5 lat
  • Postów:19
0

@serek - dzięki. Wiedziałam, że o czymś zapomnę a więc:

  • hasła dla janka nie ma celowo aby przetestować logowanie bez hasła
  • jeden z userów ma niehashowane hasło aby początkowo ominąć ewentualne dodatkowe problemy z hashowaniem
    Poprawiłam kod i teraz dostaję:
Kopiuj
[01-Jan-2020 11:55:56 UTC] PHP Parse error:  syntax error, unexpected ':' in /var/www/html/testsec/form.php on line 28

Czyli czepia się właśnie tych zmian, które zaproponowałeś.

serek
  • Rejestracja:około 11 lat
  • Ostatnio:9 minut
  • Postów:1473
0

Możesz spróbować też wersji ze znakami zapytania:

Kopiuj
$query = "select * from admin where login = ? and pass = ?";
$stmt = $db->prepare($query);
$stmt->bindParam(1, $username, PDO::PARAM_STR);
$stmt->bindValue(2, $password, PDO::PARAM_STR);
.__.
  • Rejestracja:ponad 5 lat
  • Ostatnio:prawie 5 lat
0

Nie startujesz sesji przed ustawieniem jej w form.php; nie ma nic na zmiennej $array.
Poza tym utworzyłbym nowy plik init.php, w którym startujesz raz sesje, nawiazujesz polaczenie z baza danych i includujesz go do każdego pliku

KA
  • Rejestracja:ponad 5 lat
  • Ostatnio:około 5 lat
  • Postów:19
0

DZIĘKI!!! :)
Działa :) Poprawiony kod poniżej - dla potomnych i innych szukajacych :)

Kopiuj
<?php
    session_start();
    $dbhost     = "localhost";
    $dbname     = "site1";
    $dbuser     = "site1";
    $dbpass     = "site1";

    try {
        $db = new PDO('mysql:host=localhost;dbname=site1;charset=utf8mb4', $dbuser, $dbpass );
        $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);  
    } catch (PDOException $e) {
        echo "Connection failed : ". $e->getMessage();
    }
    $username = trim($_POST['user']);
    $password = trim($_POST['pass']);
    $msg = "";
    if($username == "") {
        echo "Brak podanego loginu!";
//        header("Location: http://localhost/testsec/form.html");
        die();
    }
    
    try {
        $query = "select * from admin where login = ? and pass = ?";
        $stmt = $db->prepare($query);
        $stmt->bindParam(1, $username, PDO::PARAM_STR);
        $stmt->bindValue(2, $password, PDO::PARAM_STR);
        $stmt->execute();
        $count = $stmt->rowCount();
        $row =   $stmt->fetch(PDO::FETCH_ASSOC);
        echo '<pre>'; print_r($row); echo '</pre>';

        if ($count == 1 && !empty($row)) { 
            $_SESSION['sess_user_id'] = $row['id'];
            $_SESSION['sess_user_name'] = $row['login'];
            $_SESSION['sess_name'] = $row['imie'];
        } else {
            $msg = "Invalid username and/or password";
        }
    } catch (PDOException $e) {
        echo "Error :".$e->getMessage();
    }
    
    echo $username.'<br />';
    echo $password.'<br />';
    
    // jeśli się uda to przekierowuję
    header("Location: home.php");
?>

A na koniec jeszcze jedno pytanie - require/_once czy include dla pliku z configiem bazy danych?
I dlaczego?

.__.
  • Rejestracja:ponad 5 lat
  • Ostatnio:prawie 5 lat
0

_once unika powtórnego załadowania pliku w kodzie tzn. powielenia tego samego
include w razie jeśli brakuje pliku, to dostajesz błąd ale kod dalej sie wykonuje
require w razie jeśli brakuje pliku, to dostajesz piekny fatal error i kod dalej się nie wykonuje

require_once będzie najbezpieczniejsze

KA
  • Rejestracja:ponad 5 lat
  • Ostatnio:około 5 lat
  • Postów:19
0
Kopiuj
[01-Jan-2020 13:44:27 UTC] PHP Warning:  Use of undefined constant dbuser - assumed 'dbuser' (this will throw an Error in a future version of PHP) in /var/www/html/testsec/config.php on line 2
[01-Jan-2020 13:44:27 UTC] PHP Warning:  Use of undefined constant dbpass - assumed 'dbpass' (this will throw an Error in a future version of PHP) in /var/www/html/testsec/config.php on line 3
[01-Jan-2020 13:44:27 UTC] PHP Warning:  Use of undefined constant dbname - assumed 'dbname' (this will throw an Error in a future version of PHP) in /var/www/html/testsec/config.php on line 4
[01-Jan-2020 13:44:27 UTC] PHP Warning:  Use of undefined constant dbhost - assumed 'dbhost' (this will throw an Error in a future version of PHP) in /var/www/html/testsec/config.php on line 5
[01-Jan-2020 13:44:27 UTC] PHP Notice:  Undefined variable: dbuser in /var/www/html/testsec/form.php on line 6
[01-Jan-2020 13:44:27 UTC] PHP Notice:  Undefined variable: dbpass in /var/www/html/testsec/form.php on line 6

Niezależnie od tego czy require_once czy include nie chce mi czytać pliku config.php, kod form.php (początek):

I dostaję błąd z phpa z PDO oczywiście:

Kopiuj
Error :SQLSTATE[3D000]: Invalid catalog name: 1046 No database selected
Kopiuj
<?php
    session_start();
        require_once "config.php";

    try {
        $db = new PDO('mysql:$dbhost,$dbname,charset=utf8mb4', $dbuser, $dbpass );
        $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);  
    } catch (PDOException $e) {
        echo "Connection failed : ". $e->getMessage();
    }

config.php

Kopiuj
<?php
define (dbuser, "site1");
define (dbpass, "site1");
define (dbname, "site1");
define (dbhost, "localhost");
?>

Co robię źle i jak podstawić zawartość pobranych zmiennych z config.php do form.php?
Dlaczego PDO nie chce przyjąć zmiennych?

.__.
  • Rejestracja:ponad 5 lat
  • Ostatnio:prawie 5 lat
0

stałych używa się inaczej:

Kopiuj
<?php
define('DB_HOST', 'a');
$dbname = 'b';

$test = "mysql:host=".DB_HOST.",dbname={$dbname},charset=utf8mb4";

echo $test;
PinguVanEx
  • Rejestracja:około 17 lat
  • Ostatnio:ponad 4 lata
0

Dokładnie jak przedmówca napisał, odczyt stały następuje po wpisaniu jego nazwy bez znaku $.
Według dobrych praktyk stałe piszemy zawsze wielkimi literami a zamiast spacji używamy znaku _. (na końcu pliku PHP nie używamy już ?>)

Kopiuj
<?php

define (DB_USER, 'site1');
define (DB_PASS, 'site1');
define (DB_NAME, 'site1');
define (DB_HOST, 'localhost');

Kopiuj
<?php
    session_start();
    require_once 'config.php';

    try {
        $db = new PDO(sprintf('mysql:host=?;dbname=?;charset=utf8mb4', DB_HOST, DB_NAME), DB_USER, DB_PASS);
        $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);  
    } catch (PDOException $e) {
        echo "Connection failed : ". $e->getMessage();
    }

W prezentowanym kodzie jest poważny błąd logiczny

Kopiuj
$db = new PDO('mysql:$dbhost,$dbname,charset=utf8mb4', $dbuser, $dbpass );

Ponieważ string w PDO jest pomiędzy apostrofami, zmienne nie zostaną podmienione na wartości tylko potraktowane jako zwykły string. Zalecam używanie sprintf itp.
Dodatkowo zostały usunięte parametry "host= ... dbname=".

Przy zapytaniach SQL radzę unikać wstrzykiwania bezpośrednio zmiennych, zwłaszcza jak są one pobierane z tablicy $_POST, jest to miejsce podatne na ataki sql injection.

edytowany 1x, ostatnio: PinguVanEx
KA
  • Rejestracja:ponad 5 lat
  • Ostatnio:około 5 lat
  • Postów:19
0

Udało sie i działa - dzielę się działającym kodem. Nie radząc sobie z tym PDO do końca, wspomogłam się jeszcze raz guglem i wynalazłam również to:
, czas: 4:34
form.php

Kopiuj
<?php
    require_once "cfgdb.php";
    session_start();
    try {
        $db = new PDO("mysql:host=$dbhost;dbname=$dbname",$dbuser,$dbpass);
        $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);  
    } catch (PDOException $e) {
        echo "Connection failed : ". $e->getMessage();
    }
    $username = trim($_POST['user']);
    $password = trim($_POST['pass']);
    $msg = "";
    if($username == "") {
        echo "Proszę o wpisanie loginu - <a href='form.html'>powrót do strony logowania</a>.";
        header("refresh:5;url=form.html");
        die();
    }
    try {
	$query = "select * from admin where login = ? and pass = ?";
	$stmt = $db->prepare($query);
	$stmt->bindParam(1, $username, PDO::PARAM_STR);
	$stmt->bindValue(2, md5($password), PDO::PARAM_STR);
        $stmt->execute();
        $count = $stmt->rowCount();
	$row =   $stmt->fetch(PDO::FETCH_ASSOC);
        if ($count == 1 && !empty($row)) { 
            $_SESSION['sess_user_id'] = $row['id'];
            $_SESSION['sess_user_name'] = $row['login'];
	    $_SESSION['sess_name'] = $row['imie'];
	    // jeśli się uda to przekierowuję
	    header("Location: home.php");
        } else {
            $color = "<div style='background-color:red;color:white;padding:1%;'><font size=10px><b>";
            $msg = "Nieprawidłowy login i/lub hasło użytkownika";
            $endcolor = "</b></font></div><br />";
            echo $color,$msg,$endcolor;
            header("refresh:6;url=form.html");
        }
    } catch (PDOException $e) {
        echo "Error :".$e->getMessage();
    }
?>
Kopiuj
<?php
    $dbhost = "localhost";
    $dbuser = "site1";
    $dbname = "site1";
    $dbpass = "site1";
?>

Dzięki za pomoc :)
P.S. @PinguVanEx - a jak ten zmieniony kod ^^?

edytowany 1x, ostatnio: Katrina
PinguVanEx
  • Rejestracja:około 17 lat
  • Ostatnio:ponad 4 lata
0

@Katrina: skoro pytasz, to zrobie szybkie code review (tak wiem, ze dopiero zaczynasz)

Kopiuj
<?php
    $dbhost = "localhost";
    $dbuser = "site1";
    $dbname = "site1";
    $dbpass = "site1";
?>
  • do tego rodzaju danych, na których nie będziemy w kodzie operować zalecam używanie stałych
  • na końcu pliku nie używamy ?>
Kopiuj
<?php
    require_once "cfgdb.php"; 
    session_start();
    try {
        $db = new PDO("mysql:host=$dbhost;dbname=$dbname",$dbuser,$dbpass);
        $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);  
    } catch (PDOException $e) {
        echo "Connection failed : ". $e->getMessage(); **zalecam użycie sprintf do łączenia stringów
        **brakuje zatrzymania aplikacji wraz z wyjątkiem (throw new ...)
    }
    $username = trim($_POST['user']); **warto dodać domyślną wartość w przypadku braku klucza user ($_POST['user'] ?? '')
    $password = trim($_POST['pass']); **warto dodać domyślną wartość w przypadku braku klucza pass ($_POST['user'] ?? '')
    $msg = ""; **po co jest ta zmienna?
    if($username == "") { **jeżeli dodamy wartość domyślną możemy również sprawdzać już typ $username === "" albo użyć wielniejszej ale pewnej funkcji  if(empty($username))
        echo "Proszę o wpisanie loginu - <a href='form.html'>powrót do strony logowania</a>.";
        header("refresh:5;url=form.html"); **przy aktualnym kodzie może być błąd nagłówka ponieważ w przypadku wystąpienia błedu PDO zostanie już wyświetlona treść na ekranie (moża też zrobić złego hack-a z ob_start)
        die();
    }
    try {
    $query = "select * from admin where login = ? and pass = ?";
    $stmt = $db->prepare($query);
    $stmt->bindParam(1, $username, PDO::PARAM_STR);
    $stmt->bindValue(2, md5($password), PDO::PARAM_STR); **hasło w md5 to zły pomysł, polecam bcrypt (https://www.php.net/manual/en/function.password-hash.php)
        $stmt->execute();
        $count = $stmt->rowCount();
    $row =   $stmt->fetch(PDO::FETCH_ASSOC);
        if ($count == 1 && !empty($row)) { **$count === 1, czy instrukcja warunkowa nie jest bez sensu? jezeli krotka nie istnieje (row) to count bedzie 0
            $_SESSION['sess_user_id'] = $row['id'];
            $_SESSION['sess_user_name'] = $row['login'];
        $_SESSION['sess_name'] = $row['imie'];
        // jeśli się uda to przekierowuję
        header("Location: home.php"); 
        } else {
            $color = "<div style='background-color:red;color:white;padding:1%;'><font size=10px><b>";
            $msg = "Nieprawidłowy login i/lub hasło użytkownika";
            $endcolor = "</b></font></div><br />";
            echo $color,$msg,$endcolor;
            header("refresh:6;url=form.html");
        }
    } catch (PDOException $e) {
        echo "Error :".$e->getMessage();
    }
?>
MA
  • Rejestracja:ponad 6 lat
  • Ostatnio:około 5 lat
  • Postów:63
0
KA
  • Rejestracja:ponad 5 lat
  • Ostatnio:około 5 lat
  • Postów:19
0

Dzięki za pomoc :)
Na razie rozwijam aplikacyjkę i md5 chwilowo musi wystarczyć (tylko dla) moich testów, zaszyfrowanie haseł zostawiłam "na potem".

@marchewa - SQL Injection to dla mnie temat dość istotny jak to dla "adminki" którą jestem i do tego tematu będę wracała kiedy tylko skończę robić jak to się nazywa? CRUD? Swoich danych w aplikacyjce.

MA
hasla nie powinno sie szyfrowac lecz haszowac
KA
Dokładnie to miałam na myśli pisząc to co napisałam - hashowanie. Chyba za dużo myślałam ;)
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)