Beiträge von cottton
-
-
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:
? 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
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:
... 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.
-
-
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):
Code
Alles anzeigentbl user -- successfully registered users id int primary key auto increment email string unique email password_hash string the hashed password nickname string unique nickname is_active bool indicates if th user is active created_at ... updated_at ... -- uidx email; uidx nickname -- note: would use tbl user_login to store logins (id, user_id, password_hash, is_active, created_at, updated_at) -- note: missing user email confirmation at all user_invitation -- users invite new users (1:n) id int primary key auto increment user_id int fk (foreign key) user.id invitation_token string the unique invitation token|hash is_active bool indicates if th user-invitation is active valid_until datetime the datetime string until the invitation is valid redeemed_at null|datetime the datetime string the invitation has been successfully accepted created_at ... updated_at ... -- uidx invitation_token ----- INPUT data = // POST data of new user to create invitationToken = // POST data of invitation token provided ----- // CHECK INPUT if !strlen(invitationToken) throw invalid invitation exception --invalid token // todo: check new user data ... like email validation, already exists by nick and email, .... ----- CHECK INVITATION invitation = ... SELECT * FROM user_invitation WHERE invitation_token = :invitation_token LIMIT 1; // limit 1 to load the 1st always in case of duplicates (duplicates gets ignored that way) // check if invitation actually exists if !is_array(invitation) or !invitation.id throw invalid invitation exception --not exist // check if invitation is active if !(bool)invitation.is_active throw invalid invitation exception --disabled // check if invitation is still valid if invitation.valid_until < NOW throw invalid invitation exception --expired // check if invitation has been already redeemed if strlen(invitation.redeemed) throw invalid invitation exception --already redeemed --- hostUserId = invitation.user_id --- CHECK HOST // check if user who invited the new user is valid host = ... SELECT * FROM user WHERE user_id = :host_user_id LIMIT 1; //limit 1 to load the 1st always in case of duplicates (duplicates gets ignored that way) // check if host actually exists if !is_array(host) or !host.id throw invalid invitation exception --host not exist // check if host is active if !(bool)host.is_active throw invalid invitation exception --host disabled // todo: check if host (user) is allowed to invite new users --- REGISTER NEW USER try // insert new user INSERT INTO ... // set redeemed_at datetime to now UPDATE user_invitation SET redeemed_at = NOW WHERE invitation_token = :invitation_token; // no limit 1 - on dublicates all get redeemed on purpose // todo: would start new user email confirmation process here return success catch error handling ... return failure
-
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*
-
Was Du suchst ist eine Pagination.
Hatte da mal was schrieben: Einfache Seitennavigation (Pagination)
Oder Du suchst mal im Netz nach "php pagination".
-
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:
Code
Alles anzeigentbl model id model_id model_name show_id collection datum --warum ist id nicht die model_id? --was ist eine show_id? Vom Bsp aus "001" - sagt mir nix. tbl gallerie id m_show_id gallerie --würde namen ausschreiben - statt m_show_id model_show_id (wobei ich erwarten würde, dass model_show_id auf tbl model column id (model.id) zeigt) --was ist (in) gallerie? tbl bilder id m_show_id bilder (order bild?) --siehe m_show_id hinweis bei gallerie
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.
-
Wie sieht denn die query jetzt aus?
-
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:
Codeid | 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
Codeid | 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.
Codeid | 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:
SQL
Alles anzeigenCREATE TABLE `user` ( `id` INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, `username` VARCHAR(18) NOT NULL ); CREATE TABLE `beitrag` ( `id` INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, `user_id` INT UNSIGNED NOT NULL, `text` VARCHAR(18) NOT NULL ); CREATE TABLE `beitrag_pictures` ( `id` INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, `beitrag_id` INT UNSIGNED NOT NULL, `image` VARCHAR(255) NOT NULL ); -- not adding idx or fk here INSERT INTO `user` SET `username` = 'cottton'; INSERT INTO `beitrag` SET `user_id` = 1, `text` = 'text 1'; INSERT INTO `beitrag` SET `user_id` = 1, `text` = 'text 2'; INSERT INTO `beitrag` SET `user_id` = 1, `text` = 'text 3'; INSERT INTO `beitrag_pictures` SET `beitrag_id` = 2, `image` = '1.png'; INSERT INTO `beitrag_pictures` SET `beitrag_id` = 2, `image` = '2.png'; INSERT INTO `beitrag_pictures` SET `beitrag_id` = 2, `image` = '3.png'; select * from user; +----+----------+ | id | username | +----+----------+ | 1 | cottton | +----+----------+ select * from beitrag; +----+---------+--------+ | id | user_id | text | +----+---------+--------+ | 1 | 1 | text 1 | | 2 | 1 | text 2 | | 3 | 1 | text 3 | +----+---------+--------+ select * from beitrag_pictures; +----+------------+-------+ | id | beitrag_id | image | +----+------------+-------+ | 1 | 2 | 1.png | | 2 | 2 | 2.png | | 3 | 2 | 3.png | +----+------------+-------+
Erstmal simples ausgeben aller Beiträge von einem user:
SQL
Alles anzeigenSELECT `b`.`id`, `b`.`user_id`, `b`.`text` FROM `beitrag` AS `b` WHERE `b`.`user_id` = 1; +----+---------+--------+ | id | user_id | text | +----+---------+--------+ | 1 | 1 | text 1 | | 2 | 1 | text 2 | | 3 | 1 | text 3 | +----+---------+--------+
Jetzt wollen wir die Bilder dazu:
SQL
Alles anzeigenSELECT `b`.`id`, `b`.`user_id`, `b`.`text`, `p`.`image` FROM `beitrag` AS `b` LEFT JOIN `beitrag_pictures` AS `p` ON `p`.`beitrag_id` = `b`.`id` WHERE `b`.`user_id` = 1; +----+---------+--------+-------+ | id | user_id | text | image | +----+---------+--------+-------+ | 2 | 1 | text 2 | 1.png | <- | 2 | 1 | text 2 | 2.png | <- | 2 | 1 | text 2 | 3.png | <- | 1 | 1 | text 1 | NULL | | 3 | 1 | text 3 | NULL | +----+---------+--------+-------+
Geht natürlich nicht so einfach.
Wir erstellen also einen String aus n Bildern:
GROUP_CONCAT
SQL
Alles anzeigenSELECT `b`.`id`, `b`.`user_id`, `b`.`text`, GROUP_CONCAT(`p`.`image` SEPARATOR ',') AS `image_string` FROM `beitrag` AS `b` LEFT JOIN `beitrag_pictures` AS `p` ON `p`.`beitrag_id` = `b`.`id` WHERE `b`.`user_id` = 1; +----+---------+--------+-------------------+ | id | user_id | text | image_string | +----+---------+--------+-------------------+ | 2 | 1 | text 2 | 1.png,2.png,3.png | oO? +----+---------+--------+-------------------+
Aber hier fehlen Beiträge!
Wir gruppieren nach Beiträgen:
SQL
Alles anzeigenSELECT `b`.`id`, `b`.`user_id`, `b`.`text`, GROUP_CONCAT(`p`.`image` SEPARATOR ',') AS `image_string` FROM `beitrag` AS `b` LEFT JOIN `beitrag_pictures` AS `p` ON `p`.`beitrag_id` = `b`.`id` WHERE `b`.`user_id` = 1 GROUP BY `b`.`id`; +----+---------+--------+-------------------+ | id | user_id | text | image_string | +----+---------+--------+-------------------+ | 1 | 1 | text 1 | NULL | | 2 | 1 | text 2 | 1.png,2.png,3.png | | 3 | 1 | text 3 | NULL | +----+---------+--------+-------------------+
TADA!
Jetzt noch den user dazu (obwohl ich das für unnötig halte)
SQL
Alles anzeigenSELECT `b`.`id`, `b`.`user_id`, `b`.`text`, GROUP_CONCAT(`p`.`image` SEPARATOR ',') AS `image_string`, `u`.`username` FROM `beitrag` AS `b` LEFT JOIN `user` AS `u` ON `u`.`id` = `b`.`user_id` LEFT JOIN `beitrag_pictures` AS `p` ON `p`.`beitrag_id` = `b`.`id` WHERE `b`.`user_id` = 1 GROUP BY `b`.`id`; +----+---------+--------+-------------------+----------+ | id | user_id | text | image_string | username | +----+---------+--------+-------------------+----------+ | 1 | 1 | text 1 | NULL | cottton | | 2 | 1 | text 2 | 1.png,2.png,3.png | cottton | | 3 | 1 | text 3 | NULL | cottton | +----+---------+--------+-------------------+----------+
-
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:
PHP
Alles anzeigen$data = [ ['country' => 'DE', 'city' => 'Berlin'], ['country' => 'DE', 'city' => 'Dresden'], ['country' => 'DE', 'city' => 'München'], ]; $params = []; $sql = "INSERT INTO `table_name` (`country`, `city`) VALUES "; $values = []; foreach ($data as $array) { $params[] = $array['country']; $params[] = $array['city']; $values[] = "(?, ?)"; } $sql .= implode(', ', $values); $sql .= ";"; var_dump($sql); //$stmt = $pdo->prepare($sql); //$stmt->execute($params);
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
Opps
PHP
Alles anzeigen// simulate POST input $_POST['city'] = ['Berlin', 'Dresden', 'München']; $params = []; $sql = "INSERT INTO `city` (`city`) VALUES "; $values = []; foreach ($_POST['city'] as $city) { $params[] = $city; $values[] = "(?)"; } $sql .= implode(', ', $values); $sql .= ";"; var_dump($sql); //$stmt = $pdo->prepare($sql); //$stmt->execute($params);
-
PHP
Alles anzeigen// simulate POST input $_POST['city'] = ['Berlin', 'Dresden', 'München']; $params = []; $sql = "INSERT INTO `city` (`city`) VALUES"; foreach ($_POST['city'] as $city) { $params[] = $city; $sql .= " (?)"; } $sql .= ";"; var_dump($sql); //$stmt = $pdo->prepare($sql); //$stmt->execute($params);
-
Will nur erwähnen, wenn das Problem dann gelöst ist, bitte :platzhalter in der Query verwenden.
Beipiele: https://stackoverflow.com/a/14767651/3411766
-
Ich empfehle beim Verbindungsaufbau als ini-command
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:
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
PHP
Alles anzeigen<?php $fileContentArray = [ '<!DOCTYPE html> <html> <head> <title>Page Title</title> </head> <body> <h1>This is a Heading</h1> <p>This is a paragraph.</p> </body> </html>', ]; $contentToAdd = ' <script> var i = 1; </script> '; foreach ($fileContentArray as &$content) { $content = str_replace('<head>', "<head>\r\n{$contentToAdd}", $content); } echo var_export($fileContentArray, true) . PHP_EOL;
HTML
Alles anzeigenarray ( 0 => '<!DOCTYPE html> <html> <head> <script> var i = 1; </script> <title>Page Title</title> </head> <body> <h1>This is a Heading</h1> <p>This is a paragraph.</p> </body> </html>', )
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?
-
Nach der eigtl Frage:
https://www.w3schools.com/sql/sql_insert_into_select.asp
Wenn per HTML Form:
- lade daten von tbl_1
- gib daten aus
- lass user daten auswählen
- [form wird abgesandt]
- lade daten wo id = ...
- schreibe daten (insert into tbl_2 ...)
Weiss nicht, wo das problem ist.
-
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()).