TL;DR:
Verwijder addslashes($data)
. Het is hier overbodig.
Dubbele ontsnapping .. twee keer
$data=fread($p,filesize($fi));
$data=addslashes($data);
$dat= pg_escape_bytea($data);
U leest de gegevens in, ontsnapt eraan alsof het een letterlijke tekenreeks is en converteert het vervolgens naar bytea octaal of hex-escapes. Het zou nooit zo kunnen werken, zelfs als pg_escape_bytea
gezond was, wat het niet is.
PHP's pg_escape_bytea
lijkt te dubbele escape de uitvoer zodat deze letterlijk in een tekenreeks kan worden ingevoegd. Dit is ongelooflijk lelijk, maar er lijkt geen alternatief te zijn dat deze dubbele escape niet doet, dus het lijkt erop dat je geen geparametriseerde instructies voor bytea in PHP kunt gebruiken. Je moet dit nog steeds doen voor al het andere.
In dit geval verwijdert u gewoon de addslashes
regel voor de ingelezen gegevens uit het bestand is voldoende.
Testcase die aantoont dat pg_escape_bytea
dubbele ontsnappingen (en gebruikt ook altijd de oude, inefficiënte octale ontsnappingen):
<?php
# oh-the-horror.php
print pg_escape_bytea("Blah binary\x00\x01\x02\x03\x04 blah");
?>
Uitvoeren:
php oh-the-horror.php
Resultaat:
Blah binary\\000\\001\\002\\003\\004 blah
Zie je de dubbele backslashes? Dat komt omdat het ervan uitgaat dat je het als een tekenreeks in SQL gaat interpoleren, wat extreem geheugeninefficiënt, lelijk en een zeer slechte gewoonte is. Je lijkt echter geen alternatief te krijgen.
Dit betekent onder meer dat:
pg_unescape_bytea(pg_escape_bytea("\x01\x02\x03"));
... geeft het verkeerde resultaat , sinds pg_unescape_bytea
is eigenlijk niet het omgekeerde van pg_escape_bytea
. Het maakt het ook onmogelijk om de uitvoer van pg_escape_bytea
. te voeren in pg_query_params
als parameter moet je het in interpoleren.
Decodering
Als je een moderne PostgreSQL gebruikt, zet deze waarschijnlijk bytea_output
naar hex
standaard. Dat betekent dat als ik mijn gegevens schrijf naar een bytea
veld en haal het dan terug, het ziet er ongeveer zo uit:
craig=> CREATE TABLE byteademo(x bytea);
CREATE TABLE
craig=> INSERT INTO byteademo(x) VALUES ('Blah binary\\000\\001\\002\\003\\004 blah');
INSERT 0 1
craig=> SELECT * FROM byteademo ;
x
----------------------------------------------------------------------------
\x426c61682062696e6172795c3030305c3030315c3030325c3030335c30303420626c6168
(1 row)
"Eh, wat", zou je misschien zeggen? Het is prima, het is gewoon PostgreSQL's iets compactere hex-representatie van bytea
. pg_unescape_bytea
zal het prima afhandelen en dezelfde onbewerkte bytes produceren als uitvoer ... als je een moderne PHP en libpq
hebt . Op oudere versies krijg je rotzooi en moet je bytea_output
. instellen om te escape
voor pg_unescape_bytea
om ermee om te gaan.
Wat u in plaats daarvan moet doen
Gebruik BOB.
Het heeft gezonde (ish) ondersteuning voor bytea
.
$sth = $pdo->prepare('INSERT INTO mytable(somecol, byteacol) VALUES (:somecol, :byteacol)');
$sth->bindParam(':somecol', 'bork bork bork');
$sth->bindParam(':byteacol', $thebytes, PDO::PARAM_LOB);
$sth->execute();
Zie:
- PHP:grote objecten, met een voorbeeld van precies wat je wilt;
- PDOStatement::bindParam
- hoe een geserialiseerd object met naamruimte in de database op te slaan met pdo php
- Bind BYTEA aan PGSQL PDO opgestelde verklaring in PHP5
Misschien wilt u ook kijken naar de lob-ondersteuning (groot object) van PostgreSQL, die een streaming-, doorzoekbare interface biedt die nog steeds volledig transactioneel is.
Nu, op naar mijn zeepkist
Als PHP een echt onderscheid zou maken tussen de typen "byte string" en "text string", zou je pg_escape_bytea
niet eens nodig hebben aangezien het databasestuurprogramma het voor u zou kunnen doen. Al deze lelijkheid zou niet nodig zijn. Helaas zijn er geen aparte typen strings en bytes in PHP.
Gebruik alstublieft zoveel mogelijk PDO met geparametriseerde statements.
Waar dat niet kan, gebruik in ieder geval pg_query_params
en geparametriseerde statements. PHP's addslashes
is geen alternatief, het is inefficiënt, lelijk en begrijpt geen database-specifieke ontsnappingsregels. Je moet nog steeds handmatig ontsnappen aan bytea
als je PDO om icky historische redenen niet gebruikt, maar al het andere moet via geparametriseerde instructies gaan.
Voor hulp bij pg_query_params
:
- Bobby-tabellen, PHP-sectie.
- De PHP-handleiding op
pg_query_params