TL;DR:
Elimina addslashes($data)
. Qui è ridondante.
Doppio escape .. due volte
$data=fread($p,filesize($fi));
$data=addslashes($data);
$dat= pg_escape_bytea($data);
Leggi i dati, esegui l'escape come se fosse una stringa letterale, quindi lo converti in bytea ottale o esadecimale. Non potrebbe mai funzionare in questo modo anche se pg_escape_bytea
era sano di mente, ma non lo è.
pg_escape_bytea
di PHP sembra doppio escape l'output in modo che possa essere inserito in una stringa letterale. Questo è incredibilmente brutto, ma non sembra esserci un'alternativa che non esegua questo doppio escape, quindi non sembra che tu possa usare istruzioni parametrizzate per bytea in PHP. Dovresti comunque farlo per tutto il resto.
In questo caso, è sufficiente rimuovere le addslashes
è sufficiente la riga per i dati letti dal file.
Caso di test che mostra che pg_escape_bytea
double-escapes (e usa sempre anche i vecchi e inefficienti escape ottali):
<?php
# oh-the-horror.php
print pg_escape_bytea("Blah binary\x00\x01\x02\x03\x04 blah");
?>
Corri:
php oh-the-horror.php
Risultato:
Blah binary\\000\\001\\002\\003\\004 blah
Vedi le barre rovesciate raddoppiate? Questo perché presuppone che lo interpolerai in SQL come una stringa, il che è estremamente inefficiente in termini di memoria, brutto e una pessima abitudine. Tuttavia, non sembra che tu abbia alternative.
Tra l'altro questo significa che:
pg_unescape_bytea(pg_escape_bytea("\x01\x02\x03"));
... produce il risultato errato , poiché pg_unescape_bytea
in realtà non è il contrario di pg_escape_bytea
. Inoltre, rende impossibile alimentare l'output di pg_escape_bytea
in pg_query_params
come parametro, devi interpolarlo.
Decodifica
Se stai usando un PostgreSQL moderno, probabilmente imposta bytea_output
in hex
per impostazione predefinita. Ciò significa che se scrivo i miei dati su un bytea
campo quindi recuperalo, sarà simile a questo:
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)
"Uhm, cosa", potresti dire? Va bene, è solo la rappresentazione esadecimale leggermente più compatta di bytea
di PostgreSQL . pg_unescape_bytea
lo gestirà bene e produrrà gli stessi byte grezzi dell'output ... se hai un PHP moderno e libpq
. Nelle versioni precedenti otterrai spazzatura e dovrai impostare bytea_output
per escape
per pg_unescape_bytea
per gestirlo.
Cosa dovresti fare invece
Usa DOP.
Ha un supporto sano (ish) per 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();
Vedi:
- PHP:Large Objects, che contiene un esempio di esattamente ciò che desideri;
- PDOStement::bindParam
- come memorizzare un oggetto serializzato con spazio dei nomi nel database usando pdo php
- Collega BYTEA a PGSQL PDO Prepared Statement in PHP5
Potresti anche voler esaminare il supporto lob (oggetto di grandi dimensioni) di PostgreSQL, che fornisce un'interfaccia in streaming ricercabile che è ancora completamente transazionale.
Ora, alla mia scatola di sapone
Se PHP avesse una vera distinzione tra i tipi "stringa di byte" e "stringa di testo", non avresti nemmeno bisogno di pg_escape_bytea
poiché il driver del database potrebbe farlo per te. Nessuna di queste bruttezze sarebbe necessaria. Sfortunatamente, in PHP non ci sono tipi di stringhe e byte separati.
Si prega di utilizzare il più possibile PDO con istruzioni parametrizzate.
Dove non puoi, usa almeno pg_query_params
e dichiarazioni parametrizzate. addslashes
di PHP non è un'alternativa, è inefficiente, brutto e non comprende le regole di escape specifiche del database. Devi ancora uscire manualmente da bytea
se non stai usando PDO per sfiziosi motivi storici, ma tutto il resto dovrebbe passare attraverso istruzioni parametrizzate.
Per indicazioni su pg_query_params
:
- Tabelle Bobby, sezione PHP.
- Il manuale PHP su
pg_query_params