-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 - --- ./postgresql-8.0.4/src/interfaces/libpq/fe-connect.c.orig 2005-07-13 17:26:06.000000000 +0200 +++ ./postgresql-8.0.4/src/interfaces/libpq/fe-connect.c 2005-11-09 10:34:25.263540736 +0100 @@ -532,8 +532,241 @@ return connOptions; } - -/* ---------------- - - * PQsetdbLogin +/* + * - PQsetdbLogin OPTIONS EXTENSION PATCH - + * + * + * To make it possible to set options like sslmode with ECPG + * as ECPG uses PQsetdbLogin with its limitations + * Use : essentially to override default settings with + * PQsetdbLogin() for parameters like sslmode or + * connect_timeout, while at the same time preventing + * the setting via URL of the parameters normally + * supplied to PQsetdbLogin outside URL as : host, login, + * pwd ... + * + * URL ex. tcp:postgresql://:5432/[?[][<&sslmode=require|&requiressl=1>[&connect_timeout=[& ...]]]] + * + * Ex. tcp:postgresql://:5432/dbname?&sslmode=require + * + * Previously only options for the backend as "Backend-Debug-Options" could be passed. + * In this version everything between the '?' character and the first ampersand character + * is considered as the former if no ampersand is present, the behaviour + * is that of the former. + * + * For anti-idiosyncratic convenience : if the first parameter is + * one of { sslmode, requiressl, connect_timeout } the leading ampersand might + * be omitted and that parameter and the following won't be considered + * to be intended for the backend as (command-line-options). + * So for instance tcp:postgresql://:5432/dbname?sslmode=require + * will be considered as tcp:postgresql://:5432/dbname?&sslmode=require + * + * conninfo_parseURL : Parses a substring from a previously strdup-licated options string passed + * + * Most of the parsing code is adapted from conninfo_parse(). + * + * Send your comments to + * + * Waldemar Olenycz 2005-11-04 2005-11-09 + * + */ + +/* (The following prototype is to keep gcc happy + * should be moved into an include file ?) + */ + +char * +conninfo_parseURL(char *, PQExpBuffer ); + +/* + * - PQsetdbLogin OPTIONS EXTENSION PATCH - (continued) + * + * conninfo_parseURL + * + * Parses a substring from a previously strdup-licated options string passed + * to PQsetdbLogin by an ECPG connection request and tests the options + * allowed (ex. dbname, login, pwd etc. are not allowed here as they + * are passed as parameters to PQsetdbLogin) and replaces the '&' characters by ' '. + * + * Return values : the modified string or NULL if not okay. + * + * Most of the parsing code is adapted from conninfo_parse(). + * + */ + +char * +conninfo_parseURL(char *pgparms, PQExpBuffer errorMessage) +{ + char *cp; + char buf[512]; + int i; + cp = pgparms; + + while (*cp) + { + /* Skip blanks before the parameter name */ + if (isspace((unsigned char) *cp)) + { + cp++; + continue; + } + + /* Get the parameter name */ + + for (i = 0; *cp && i < sizeof(buf) - 1; i++) + { + if (*cp == '=') + break; + if (isspace((unsigned char) *cp)) + { + cp++; + buf[i]='\0'; + while (*cp) + { + if (!isspace((unsigned char) *cp)) + { + break; + } + cp++; + } + break; + } + else + buf[i]=*cp++; + } + + + /* Check that there is a following '=' */ + if (*cp != '=') + { + printfPQExpBuffer(errorMessage, + libpq_gettext("missing \"=\" after \"%s\" in URL connection info string\n"), + buf); + return NULL; + } + cp++; + + buf[i]='\0'; + + if(strcmp(buf,"sslmode") && +#ifdef USE_SSL + +/* +* "requiressl" is deprecated, its purpose having been taken over by +* "sslmode". It remains for backwards compatibility. +*/ + strcmp(buf,"requiressl") && +#endif + + strcmp(buf,"connect_timeout")) + { + if(strcmp(buf,"requiressl")) + printfPQExpBuffer(errorMessage, + libpq_gettext("invalid connection parameter name in URL \"%s\"\n"), + buf); + else + printfPQExpBuffer(errorMessage, + libpq_gettext("USE_SSL not compiled-in and requiressl used in URL\n")); + return NULL; + } + + /* Skip blanks after the '=' */ + while (*cp) + { + if (!isspace((unsigned char) *cp)) + { + break; + } + *cp++=' '; + } + + /* Get the parameter value */ + + if (*cp != '\'') + { + for (i = 0; *cp && i < sizeof(buf) - 1; i++) + { + if (isspace((unsigned char) *cp)) + { + *cp++ = ' '; + break; + } + if (*cp == '\\') + { + cp++; + if (*cp != '\0') + buf[i]=*cp++; + } + else if(*cp=='&') + break; + else if(*cp=='=') + { + printfPQExpBuffer(errorMessage, + libpq_gettext("invalid character '=' in parameter (connection info URL string)\n")); + return NULL; + } + else + buf[i]=*cp++; + } + if(!i) + { printfPQExpBuffer(errorMessage, + libpq_gettext("No value present for parameter in URL string\n")); + return NULL; + } + } + else + { cp++; + for (;;) + { + if (*cp == '\0') + { printfPQExpBuffer(errorMessage, + libpq_gettext("unterminated quoted string in connection info URL string\n")); + return NULL; + } + if (*cp == '\\') + { + cp++; + if (*cp != '\0') + cp++; + continue; + } + if (*cp == '\'') + { + cp++; + break; + } + cp++; + } + } + /* Skip blanks after parameter value */ + while (*cp) + { + if (!isspace((unsigned char) *cp)) + { + break; + } + cp++; + } + if(*cp == '&') + *cp++=' '; + else if(*cp != '\0') + { printfPQExpBuffer(errorMessage, + libpq_gettext("In URL string : ampersand '&' delimiter required between parameter/value expressions\n")); + return NULL; + } + } + return pgparms; +} + +/* + * - PQsetdbLogin OPTIONS EXTENSION PATCH - (continued) + * + * PQsetdbLogin : Modified to work with conninfo_parseURL() see above comments + * + * + * + * ---------------- + * PQsetdbLogin (with OPTIONS EXTENSION PATCH) * * establishes a connection to a postgres backend through the postmaster * at the specified host and port. @@ -550,6 +783,8 @@ const char *pwd) { PGconn *conn; + char *p_pgoptions=NULL; + char *p_parms=NULL; /* * Allocate memory for the conn structure @@ -562,9 +797,75 @@ * Parse an empty conninfo string in order to set up the same defaults * that PQconnectdb() would use. */ - - if (!connectOptions1(conn, "")) + if (pgoptions == NULL || *pgoptions == '\0') + { + if (!connectOptions1(conn, "")) return conn; + } + else + { int i,j=0; + char *cp; + + if((p_pgoptions=strdup(pgoptions)) == NULL) + { + printfPQExpBuffer(&conn->errorMessage, libpq_gettext("out of memory\n")); + return NULL; + } + + cp = p_pgoptions; + /* + * Parse the first ampersand of the URL string + */ + + for (i=0; *cp ; i++,cp++) + if(*cp=='&') + { + i++; + break; + } + + if(i) + { for ( ; j < i && isspace((unsigned char) p_pgoptions[j]) ; j++) + ; + + if(i-j >= 7 && (!strncmp(p_pgoptions+j,"sslmode",7) || +#ifdef USE_SSL + !strncmp(p_pgoptions+j,"requiressl",10) || +#endif + !strncmp(p_pgoptions+j,"connect_timeout",15))) + { /* + * Assume no command-line-options for back-ground present + * (leading ampersand omitted : ok) + */ + i=j; + } + else /* + * command-line-options for back-ground present + * in first part of p_pgoptions string + */ + + *cp='\0'; + } + + p_parms = conninfo_parseURL(p_pgoptions+i,&conn->errorMessage); + + /* + * Eventually Force URL string parameters in defaults for this connection + */ + + if (!connectOptions1(conn,(p_parms != NULL ? p_parms : ""))) + { + free(p_pgoptions); + return conn; + } + + if(i==j) + { free(p_pgoptions); + p_pgoptions=NULL; + } + } + /* * Absorb specified options into conn structure, overriding defaults */ @@ -582,12 +883,19 @@ conn->pgport = strdup(pgport); } - - if (pgoptions && pgoptions[0] != '\0') + /* + * Modified for compatibility with conninfo_parseURL + * - begin - + */ + if (p_pgoptions && p_pgoptions[0] != '\0') { if (conn->pgoptions) free(conn->pgoptions); - - conn->pgoptions = strdup(pgoptions); + conn->pgoptions = strdup(p_pgoptions); + /* and cleanup */ + free(p_pgoptions); } + /* - end - */ if (pgtty && pgtty[0] != '\0') { -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.0.6 (GNU/Linux) Comment: Pour information voir http://www.gnupg.org iD8DBQFDcdc0cZZkWM0x2hERAt6YAJ9e52YDCYv7kOFHFfA4uz69sBlDrACgiEvo RjMszGSpb1LCwcinYbPW51k= =RdXI -----END PGP SIGNATURE-----