TL; DR :
Supprimer addslashes($data)
. C'est redondant ici.
Double échappement .. deux fois
$data=fread($p,filesize($fi));
$data=addslashes($data);
$dat= pg_escape_bytea($data);
Vous lisez les données, les échappez comme s'il s'agissait d'un littéral de chaîne, puis les convertissez en octets d'échappement octal ou hexadécimal. Cela ne pourrait jamais fonctionner de cette façon même si pg_escape_bytea
était sain d'esprit, ce qui n'est pas le cas.
pg_escape_bytea
de PHP semble double-échappement la sortie afin qu'elle puisse être insérée dans un littéral de chaîne. C'est incroyablement moche, mais il ne semble pas y avoir d'alternative qui ne fasse pas ce double échappement, donc vous ne semblez pas pouvoir utiliser des instructions paramétrées pour bytea en PHP. Vous devriez toujours le faire pour tout le reste.
Dans ce cas, en supprimant simplement les addslashes
ligne pour les données lues à partir du fichier est suffisante.
Cas de test montrant que pg_escape_bytea
doubles échappements (et utilise toujours les anciens échappements octaux inefficaces) :
<?php
# oh-the-horror.php
print pg_escape_bytea("Blah binary\x00\x01\x02\x03\x04 blah");
?>
Exécuter :
php oh-the-horror.php
Résultat :
Blah binary\\000\\001\\002\\003\\004 blah
Vous voyez les doubles barres obliques inverses ? C'est parce qu'il suppose que vous allez l'interpoler dans SQL sous forme de chaîne, ce qui est extrêmement inefficace en termes de mémoire, laid et une très mauvaise habitude. Cependant, vous ne semblez pas avoir d'alternative.
Cela signifie entre autres que :
pg_unescape_bytea(pg_escape_bytea("\x01\x02\x03"));
... produit le résultat erroné , depuis pg_unescape_bytea
n'est pas en fait l'inverse de pg_escape_bytea
. Cela rend également impossible d'alimenter la sortie de pg_escape_bytea
dans pg_query_params
en tant que paramètre, vous devez l'interpoler.
Décodage
Si vous utilisez un PostgreSQL moderne, il définit probablement bytea_output
en hex
par défaut. Cela signifie que si j'écris mes données dans un bytea
puis récupérez-le, il ressemblera à ceci :
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)
« Euh, quoi », pourriez-vous dire ? C'est bien, c'est juste la représentation hexadécimale légèrement plus compacte de bytea
de PostgreSQL . pg_unescape_bytea
le gérera bien et produira les mêmes octets bruts que la sortie ... si vous avez un PHP moderne et libpq
. Sur les anciennes versions, vous obtiendrez des ordures et devrez définir bytea_output
pour escape
pour pg_unescape_bytea
pour le gérer.
Ce que vous devriez faire à la place
Utilisez AOP.
Il a un support sain (plutôt) pour 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();
Voir :
- PHP :Large Objects, qui contient un exemple de ce que vous voulez exactement ;
- PDOStatement::bindParam
- comment stocker un objet sérialisé avec un espace de noms dans la base de données à l'aide de pdo php
- Lier BYTEA à l'instruction préparée PGSQL PDO en PHP5
Vous pouvez également consulter la prise en charge des lob (objets volumineux) de PostgreSQL, qui fournit une interface de recherche en continu qui reste entièrement transactionnelle.
Maintenant, passons à ma boîte à savon
Si PHP avait une réelle distinction entre les types "chaîne d'octets" et "chaîne de texte", vous n'auriez même pas besoin de pg_escape_bytea
car le pilote de base de données pourrait le faire pour vous. Aucune de ces laideurs ne serait nécessaire. Malheureusement, il n'y a pas de types de chaînes et d'octets distincts en PHP.
Veuillez utiliser PDO avec des instructions paramétrées autant que possible.
Là où vous ne pouvez pas, utilisez au moins pg_query_params
et des instructions paramétrées. Les addslashes
de PHP n'est pas une alternative, il est inefficace, moche et ne comprend pas les règles d'échappement spécifiques à la base de données. Vous devez toujours échapper manuellement bytea
si vous n'utilisez pas PDO pour des raisons historiques délicates, mais tout le reste doit passer par des instructions paramétrées.
Pour obtenir des conseils sur pg_query_params
:
- Tableaux Bobby, section PHP.
- Le manuel PHP sur
pg_query_params