2015-12-16 7 views
8

Sto provando a connettermi con una chiave client SSL utilizzando DBI e DBD::Pg.Come utilizzare gli spazi nei parametri per DBI-> connettere?

use strict; 
use warnings 'all'; 
use DBI; 

my $dsn = "dbi:Pg:db=mydb;sslmode=require;host=localhost;" 
    ."sslcert=C:\\path with\\spaces.crt;" 
    ."sslkey=C:\\path with\\spaces.key"; 

my $dbh = DBI->connect($dsn, 'username', ''); 

ottengo il seguente errore:

Can't connect to database: missing "=" after "with\spaces.crt" in connection info string! 

Ho provato con virgolette singole o doppie attorno ai valori senza alcun risultato, e non riesco a trovare nulla nella documentazione.

Aggiornamento

Con virgolette singole come segue:

my $dsn = "dbi:Pg:db=mydb;sslmode=require;host=localhost;" 
    ."sslcert='C:\\path with\\spaces.crt';" 
    ."sslkey='C:\\path with\\spaces.key'"; 

ottengo il seguente errore:

failed: FATAL: connection requires a valid client certificate 

So che questo funziona di configurazione, come funziona in Python.

Si scopre che questo funziona:

my $dsn = "dbi:Pg:db=mydb;sslmode=require;host=localhost;" 
    ."sslcert='C:\\\\path with\\\\spaces.crt';" 
    ."sslkey='C:\\\\path with\\\\spaces.key'"; 

Perché ho bisogno di rovesciare doppio sfuggiti?

+0

@ikegami Uso rigoroso e avvisi, e infatti i valori provengono da un file di configurazione. Ho appena dimenticato di usare le doppie barre per l'esempio SO. Modificherò, grazie. – RazerM

+1

Puoi modificare la tua domanda per mostrare il tuo tentativo con virgolette singole e il messaggio di errore esatto che hai ricevuto? C'è il codice in [dbdimp.c] (https://metacpan.org/source/TURNSTEP/DBD-Pg-3.5.3/dbdimp.c#L122) nella distribuzione DBD :: Pg che sembra debba gestire un singolo attributi correttamente citati, ma non ho modo di testare adesso. – ThisSuitIsBlackNot

+0

@ThisSuitIsBlackNot: vuoi dire "sslcert = 'C: \\ percorso con \\ spaces.crt';" 'ecc.? Come sospetto che OP significhi ''sslcert = C: \ percorso con \ spaces.crt;'' – Borodin

risposta

3

per includere un attributo che contiene gli spazi nel DSN, circondare il valore con apici:

my $dsn = q{dbi:Pg:db=mydb;sslmode=require;host=localhost;} 
     . q{sslcert='C:\\\path with\\\spaces.crt';} 
     . q{sslkey='C:\\\path with\\\spaces.key'}; 

Si noti che il punto e virgola utilizzato per gli attributi di collegamento separati deve essere al di fuori le virgolette singole. Si noti inoltre che le barre rovesciate e le virgolette singole all'interno degli attributi devono essere sottoposte a escape con barre retroverse (è necessario utilizzare tre barre rovesciate precedenti poiché Perl converte \\ in \ in stringhe con quotatura singola).

Se il DSN è racchiuso tra virgolette, è necessario utilizzare quattro barre inverse, dal momento che il Perl interpola sequenze di escape come \n in stringhe tra doppi apici:

my $dsn = qq{dbi:Pg:db=mydb;sslmode=require;host=localhost;} 
     . qq{sslcert='C:\\\\path with\\\\spaces.crt';} 
     . qq{sslkey='C:\\\\path with\\\\spaces.key'}; 

Per quanto riguarda la documentazione, I don' Si veda questo menzionato in DBD :: Pg, ma si può vedere che è supportato guardando la fonte.Il codice che gestisce il DSN è in dbdimp.c nella distribuzione DBD :: Pg:

/* DBD::Pg syntax: 'dbname=dbname;host=host;port=port', 'User', 'Pass' */ 
    /* libpq syntax: 'dbname=dbname host=host port=port user=uid password=pwd' */ 

... 

    /* Change all semi-colons in dbname to a space, unless single-quoted */ 
    dest = conn_str; 
    while (*dbname != '\0') { 
      if (';' == *dbname && !inquote) 
        *dest++ = ' '; 
      else { 
        if ('\'' == *dbname) 
          inquote = !inquote; 
        *dest++ = *dbname; 
      } 
      dbname++; 
    } 
    *dest = '\0'; 

Questo trasforma una stringa di connessione in stile DBI ad un libpq-style connection string (libpq è l'API Postgres C, che DBD :: Pg utilizza dietro le scene). Poiché il DSN generato viene passato direttamente a libpq, è necessario seguire le regole per la citazione e l'escaping descritte nello libpq documentation.

Una patch di documentazione per DBD :: Pg sarebbe certamente in ordine.

1

Il problema è lo spazio. Non è chiaro se sia possibile fornire un percorso con uno spazio al suo interno. Se lo è, sarebbe probabilmente la sintassi specifica del driver. Potrebbe essere necessario scavare in DBI e/o DBD :: Pg per determinare la sintassi se è supportata. Alcuni hanno fatto questo e citato nei commenti che si potrebbe essere in grado di utilizzare il seguente:

my $dsn = join(';', 
    "dbi:Pg:db=mydb", 
    "sslmode=require", 
    "sslcert='$ssl_cert_qfn'", 
    "sslkey='$ssl_key_qfn'", 
); 

o si potrebbe affrontare il problema da un'altra angolazione. Windows ha un sistema di compatibilità con le versioni precedenti per consentire applicazioni che supportano solo percorsi in stile DOS. Da notare che DOS non ha permesso spazi nei percorsi. Utilizzando un percorso in stile DOS, è possibile evitare il problema.

use Win32 qw(); 

my $dsn = join(';', 
    "dbi:Pg:db=mydb", 
    "sslmode=require", 
    "sslcert=".Win32::GetShortPathName($ssl_cert_qfn), 
    "sslkey=".Win32::GetShortPathName($ssl_key_qfn), 
); 

Un'altra soluzione è quella di utilizzare un file di configurazione come descritto nella DBD::Pg's documentation.

Problemi correlati