Beiträge von cottton

    Was scatello sagt oder gleich ne min-length bestimmen.

    Code
    $minLength = 3;
    if(isset($_POST['search']) and strlen($_POST['search']) >= $minLength){
    // ...
    }


    EDIT: und natürlich Leerzeichen am Anfang and Ende entfernen

    Code
    $minLength = 3;
    $search = '';
    if (isset($_POST['search'])) {
        $search = trim($_POST['search']);
    }
    
    if (strlen($search) >= $minLength) {
        // ... ab hier gehts weiter - aber nutze $search, nicht mehr $_POST['search']
    }
    Code
    Ich würde es gerne verstehen

    Sehr gut!


    Man schreibt keine Variablen in die Query.

    Das sind Sicherheitslücken.

    Suche mal im Netz nach "SQL injections".


    Wenn Du Platzhalter (richtig) verwendest, dann ist eine SQL-Injection praktisch ausgeschlossen.


    Bsp:

    SQL
    SELECT * FROM `users` WHERE `trackingid` LIKE ?;

    ? ist hier ein Platzhalter.

    Bei der Ausführung übergibst Du dann die Values für die Platzhalter:

    PHP
    $stmt = $pdo->prepare("SELECT * FROM `users` WHERE `trackingid` LIKE ?;");
    $stmt->bindValue(1, "%{$search}%", PDO::PARAM_STR);
    $stmt->execute();

    Oder:

    PHP
    $stmt = $pdo->prepare("SELECT * FROM `users` WHERE `trackingid` LIKE :search;");
    $stmt->execute( 
        array(
            'search' => "%{$search}%"
            // die doppelpunkte muss man nicht mit angeben, kann man aber:
            // ':search' => "%{$search}%"
        )
    );
    // info: mit execute übergebene parameter werden immer als string eingefügt

    Siehe: http://php.net/manual/de/pdost…tatement.execute-examples



    Du hast es schon richtig gehabt, hast dann aber ::bindValue übergangen, in dem Du die Value direct in die Query geschrieben hast.

    Hätte von PHP eigtl einen Fehler erwartet - ~"number of parameters bound to ... does not match ...".




    Zur 2ten Frage:

    ALLE DATEN SIND BÖSE! <<--- merken =)

    $_POST, $_GET, aus Dateien, selbst in Deiner eigenen Datenbank ...

    alle Daten müssen als böse betrachtet werden.


    Bsp Browserausgabe:

    Alles mit (zB) htmlspecialchars() maskieren.

    PHP
    <?php
    // some code ...
    ?><div><?php echo htmlspecialchars($results['id']) ?></div>
    <div><?php echo htmlspecialchars($results['email']) ?></div>
    ?>
    // ...


    Mal angenommen ich hab beim Registrieren als email

    Code
    <script>alert('lulz');</script>

    angegeben. Und aus irgendeinem Grund ging das so in Deine db. (Oder jemand hatte zugriff auf die db ... wie auch immer...)

    Dann würde der Browser das hier bekommen:

    PHP
    <?php
    // some code ...
    ?><div>1</div>
    <div><script>alert('lulz');</script></div>
    ?>
    // ...

    ... und JS wird ausgeführt.



    ---

    Also:

    Alle Daten sind böse.

    SQL nie mit Variablen direkt füttern, sondern Platzhalter verwenden.

    HTML-Ausgaben immer mit zB htmlspecialchars() maskieren.

    Du müsstest eigtl. ein Fehler bekommen.

    Du bindest den Param `$search` aber schreibst ihn direct in die Query.


    KEINE VARS in die Query!


    SQL
    select * from users where trackingid LIKE :search LIMIT 0 ,10;
    
    -- oder
    
    select * from users where trackingid LIKE ? LIMIT 0 ,10;

    Wenn es funktionier - gut.

    Finde die Ausführung aber sehr einfach und (kommt drauf an, für was es genutzt wird) unsicher.


    Hier mal ein Konzept (Thema Sicherheit und Validierung):

    Was Du da hast, ist ein JSON string.


    PHP
    $jsonString = '{"st":"http:\/\/bak01-edge01.itdc.ge\/idman\/mono.m3u8?token=P0jpHZXQF4B4qlrmrSJAMU2j2pjqPnyAeRW0siVvjJ4*"}';
    $data = json_decode($jsonString, true);
    $url = $data['st'];
    $parts = parse_url($url);
    parse_str($parts['query'], $query);
    $token = $query['token'];
    
    echo $token; // P0jpHZXQF4B4qlrmrSJAMU2j2pjqPnyAeRW0siVvjJ4*
    Code
    MySQL meldet: 
    Dokumentation #1452 - 
    Kann Kind-Zeile nicht hinzufügen oder aktualisieren: 
        eine Fremdschlüsselbedingung schlägt fehl 
        (
        `bilder`.`bilder`, CONSTRAINT `bilder_ibfk_1` 
        FOREIGN KEY (`m_show_id`) 
        REFERENCES `gallerie` (`m_show_id`)
        )

    Du hast einen Fremdschlüssel (foreign key, abkz. "fk") in `gallerie` definiert.

    Du wolltest in bilder eine m_show_id einfügen, die es in gallerie nicht gibt.



    Was mir nicht klar ist:

    Wenn es eine show_id gibt, sollte es dann nicht eine Tabelle show geben?


    Um mehr dazu sagen zu können, brauch ich Bsp Daten. :/

    Es gibt kein zurück.

    Mit der header() sagst Du dem Browser bescheid, dass er wo anders hin soll,

    was er dann auch macht.

    Üblicherweise beendet man das script nach header() - zB mit exit(0).


    Alles was Du jetzt noch in diesem Script

    ausführst, wird ausgeführt,

    ausgibst, wird nicht mehr beachtet.

    Denkfehler =)

    Jetzt willst Du Dir alle Beiträge ausgeben lassen, die vom user :user sind:

    SQL
    -- vereinfacht
    SELECT 
        `beitrag`.`id`,
        `beitrag`.`user_id`,
        `beitrag`.`text`, 
        `beitrag_pictures`.`image`,
        FROM `beitrag` 
        LEFT JOIN `beitrag_pictures` ON `beitrag`.`id` = `beitrag_pictures`.`beitrag_id`
        WHERE `beitrag`.`user_id` = :user_id LIMIT 10;

    Das heißt Du bekommst in etwa so eni Ergebnis:

    Code
    id | user_id | text  | image
    -------------------------------
    1  | 12      | Hallo | Tier.png <---- per row `beitrag` kann man nur ein bild adden

    Un hier ist das Problem: Du kannst nicht 2 rows in eine selecten =)


    1:n Beziehung. Per 1 Beitrag kann es n Bilder geben.


    Was Du wolltest ist

    Code
    id | user_id | text  | image
    -------------------------------
    1  | 12      | Hallo | Tier.png
       |         |       | Auth.png

    die beiden Bilder in eine row selecten. Geht aber nicht.



    Eine Lösung könnte hier sein (wenn Du nur eine SQL Anfrage ansenden willst)

    die Bilder zusammenzufügen.

    Code
    id | user_id | text  | images
    -------------------------------
    1  | 12      | Hallo | Tier.png,Auth.png

    Per PHP könntest Du den String dann wieder teilen (explode(',', $row['images'])).



    ----------------------

    Da mich das auch interessiert hat - hier mal ein Bsp Schritt für Schritt:

    Test tbl erstellen:

    Erstmal simples ausgeben aller Beiträge von einem user:

    Jetzt wollen wir die Bilder dazu:

    Geht natürlich nicht so einfach.

    Wir erstellen also einen String aus n Bildern:

    GROUP_CONCAT

    Aber hier fehlen Beiträge!

    Wir gruppieren nach Beiträgen:

    TADA!

    Jetzt noch den user dazu (obwohl ich das für unnötig halte)


    Nein. Dann würdest Du mehr Parameter übergeben, als Du Platzhalter angegeben hast.

    Das führt dann (zum Glück) zu einem Fehler (also Abbruch).


    Das hier könnte man dann machen:


    Oder (wenn es nicht auf Geschwindigkeit ankommt) man baut das Ganze dann übersichtlicher

    damit andere und man selbst später noch durchsieht

    PHP
    $data = [
        ['country' => 'DE', 'city' => 'Berlin'],
        ['country' => 'DE', 'city' => 'Dresden'],
        ['country' => 'DE', 'city' => 'München'],
    ];
    foreach ($data as $array) {
        $sql = "INSERT INTO `table_name` SET `country` = :country, `city` = :city;";
        $stmt = $pdo->prepare($sql);
        $stmt->execute($array);   
    }

    Ich hab das Komma vergessen :D

    Opps :D

    SQL
    INSERT INTO `city` (`city`) VALUES (?), (?), (?);


    http://sandbox.onlinephpfuncti…91bcde0ea49c75a05981f7574

    Will nur erwähnen, wenn das Problem dann gelöst ist, bitte :platzhalter in der Query verwenden.

    Beipiele: https://stackoverflow.com/a/14767651/3411766


    PHP
    // eine möglichkeit:
    $placeholdersArray  = str_repeat('?,', count($cities) - 1) . '?'; // zB "?,?,?,?,?" bei 5 cities
    $sql = "Select `city` from `dataset` where `city` in ({$placeholdersArray})";
    $stm = $db->prepare($sql);
    $stm->execute($cities);
    $data = $stm->fetchAll();

    Ich empfehle beim Verbindungsaufbau als ini-command

    SQL
    sql_mode = 'STRICT_ALL_TABLES';

    mitzugeben.

    Das verhindert, dass die Daten verändert eingefügt werden.


    Hier im Fall hättest Du dann einen Fehler bekommen, der DIr sagt, dass die Value zu lang ist.

    Bsp:

    Code
    ERROR 1406 (22001): Data too long for column 'nachricht' ...


    Default versucht der MySQL-Server die Daten "reinzuquetschen".

    Bei Zahlen wird dann schon mal aus -1 eine 1, was ganz böse ausgehen kann :)

    Naja, der <head> tag ist ja da, denk ich.

    Also einfach per str_replace() reingehauen :D

    Test: http://sandbox.onlinephpfuncti…40e5d2b4c776aed4c107b2623


    EDIT: vorher aber BACKUP von allen Files machen!

    Und evtl nen check einbauen, ob der content ("<head>\r\n{$contentToAdd}") schon existiert.

    Also werden Websites (also einzelne Seiten) per PHP erstellt

    und dort soll jetzt überall per PHP zB ein JS code eingebunden werden?


    Like:

    PHP
    <!DOCTYPE html>
    <html>
    <head>
    <title><?php echo $title ?></title>
    <?php /* HIER SOLL IN JEDE DATEI EIN INCLUDE|REQUIRE ? */ ?>
    </head>
    <body>
    ...
    </body>
    </html>

    Da sowas wieder vorkommen kann|wird, solltest Du Dir ein "System" ausdenken.

    Order wie Sempervivum sagte: suchen und ersetzen mit Editor.

    ohne diese in diese einzubinden?

    Ich hoffe nicht :)


    Du könntest aber register_shutdown_function nutzen, um es am ende ausführen zu lassen.

    Oder auto_append_file (hab ich selbst noch nie genutzt - frag mich nicht :D)


    Oder Du hängst Dich in nen autoloader mit rein.

    Siehe: http://php.net/manual/de/language.oop5.autoload.php

    Wird eine Klasse geladen, dann führst Du ein require_once aus, welches ja nur ein Mal ausführt.

    Ist aber lame :)


    Oder auf einer Klasse in den __construct. Was auch lame ist :)


    Frage ist halt, was soll passieren?

    Und sieht man dann noch durch? Wird da evtl etwas zu sehr verschleiert?

    Wenn man sich an paar Regeln hält, dann ist es eigtl ganz einfach:


    Daten kommen rein.

    Daten werden unverändert (zB) in der Datenbank gespeichert.

    User ruft Seite auf - Daten sollen ausgegeben werden -

    Daten werden aus der Datenbank geladen.

    Daten werden (zB) in HTML eingefügt und via htmlspecialchars() maskiert.

    Wir sind sicher.


    Das Prinzip ist: alle Daten sind unsicher. Auch die aus Deiner eigenen Datenbank.

    Du kannst Prüfen und Validieren wie ein Weltmeister - es kann immer etwas übersehen worden sein.


    Auch von Dir selbst erzeugte Daten - eine csv, eine erstelltes array mit Zahlen, ...

    Alle Daten sind unsicher.


    BTW: Nicht nur bei der "Ausgabe" (HTML, ...),

    sondern generell bei der Verwendung der Daten.

    ZB in einer MySQL-Query müssen alle Daten (Values) als unsicher angesehen werden.

    Deswegen nutzen wir ja auch alle Platzhalter (:username oder ? bei PDO bzw mysqli_ -Funktionen).



    Sanitize (Desinfizieren) - nur bedingt:

    Super Bsp: Passwort

    User gibt ein Passwort ein.

    User wollte ein Leerzeichen am Anfang seines Passwortes - also dürfen wir zB kein trim() auf $_POST['password'] anwenden.

    Es wird so wie es reinkommt gespeichert.


    Chat (Textbox)

    User gibt einen Haufen Mist ein (das Ganze Netz ist voll davon).

    Der eine gibt aus Versehen ein "<" ein, ein Anderer versucht etwas zu "Hacken".

    Der gesamte Text wird evtl auf "verbotene" Zeichen geprüft. Oder doppelte Leerzeichen werden entfernt ... Vlt auch komprimiert ...

    Aber am Ende geht der Text halbwegs unverändert in die Datenbank.

    Bei der Verwendung (zB Ausgabe HTML) wird dann darauf geachtet, dass der gesamte Text maskiert wird (htmlspecialchars()).