@@ -1107,7 +1107,71 @@ ReceiveAndUnpackTarFile(PGconn *conn, PGresult *res, int rownum)
11071107}
11081108
11091109/*
1110- * Escape single quotes used in connection parameters
1110+ * Escape a parameter value so that it can be used as part of a libpq
1111+ * connection string, e.g. in:
1112+ *
1113+ * application_name=<value>
1114+ *
1115+ * The returned string is malloc'd. Return NULL on out-of-memory.
1116+ */
1117+ static char *
1118+ escapeConnectionParameter (const char * src )
1119+ {
1120+ bool need_quotes = false;
1121+ bool need_escaping = false;
1122+ const char * p ;
1123+ char * dstbuf ;
1124+ char * dst ;
1125+
1126+ /*
1127+ * First check if quoting is needed. Any quote (') or backslash (\)
1128+ * characters need to be escaped. Parameters are separated by whitespace,
1129+ * so any string containing whitespace characters need to be quoted. An
1130+ * empty string is represented by ''.
1131+ */
1132+ if (strchr (src ,'\'' )!= NULL || strchr (src ,'\\' )!= NULL )
1133+ need_escaping = true;
1134+
1135+ for (p = src ;* p ;p ++ )
1136+ {
1137+ if (isspace (* p ))
1138+ {
1139+ need_quotes = true;
1140+ break ;
1141+ }
1142+ }
1143+
1144+ if (* src == '\0' )
1145+ return pg_strdup ("''" );
1146+
1147+ if (!need_quotes && !need_escaping )
1148+ return pg_strdup (src );/* no quoting or escaping needed */
1149+
1150+ /*
1151+ * Allocate a buffer large enough for the worst case that all the source
1152+ * characters need to be escaped, plus quotes.
1153+ */
1154+ dstbuf = pg_malloc (strlen (src )* 2 + 2 + 1 );
1155+
1156+ dst = dstbuf ;
1157+ if (need_quotes )
1158+ * (dst ++ )= '\'' ;
1159+ for (;* src ;src ++ )
1160+ {
1161+ if (* src == '\'' || * src == '\\' )
1162+ * (dst ++ )= '\\' ;
1163+ * (dst ++ )= * src ;
1164+ }
1165+ if (need_quotes )
1166+ * (dst ++ )= '\'' ;
1167+ * dst = '\0' ;
1168+
1169+ return dstbuf ;
1170+ }
1171+
1172+ /*
1173+ * Escape a string so that it can be used as a value in a key-value pair
1174+ * a configuration file.
11111175 */
11121176static char *
11131177escape_quotes (const char * src )
@@ -1130,6 +1194,8 @@ GenerateRecoveryConf(PGconn *conn)
11301194{
11311195PQconninfoOption * connOptions ;
11321196PQconninfoOption * option ;
1197+ PQExpBufferData conninfo_buf ;
1198+ char * escaped ;
11331199
11341200recoveryconfcontents = createPQExpBuffer ();
11351201if (!recoveryconfcontents )
@@ -1146,12 +1212,10 @@ GenerateRecoveryConf(PGconn *conn)
11461212}
11471213
11481214appendPQExpBufferStr (recoveryconfcontents ,"standby_mode = 'on'\n" );
1149- appendPQExpBufferStr (recoveryconfcontents ,"primary_conninfo = '" );
11501215
1216+ initPQExpBuffer (& conninfo_buf );
11511217for (option = connOptions ;option && option -> keyword ;option ++ )
11521218{
1153- char * escaped ;
1154-
11551219/*
11561220 * Do not emit this setting if: - the setting is "replication",
11571221 * "dbname" or "fallback_application_name", since these would be
@@ -1165,24 +1229,37 @@ GenerateRecoveryConf(PGconn *conn)
11651229(option -> val != NULL && option -> val [0 ]== '\0' ))
11661230continue ;
11671231
1232+ /* Separate key-value pairs with spaces */
1233+ if (conninfo_buf .len != 0 )
1234+ appendPQExpBufferStr (& conninfo_buf ," " );
1235+
11681236/*
1169- * Write "keyword=' value' " pieces, the value string is escapedif
1170- *necessary and doubled single quotes around the value string .
1237+ * Write "keyword=value" pieces, the value string is escapedand/or
1238+ *quoted if necessary .
11711239 */
1172- escaped = escape_quotes (option -> val );
1173-
1174- appendPQExpBuffer (recoveryconfcontents ,"%s=''%s'' " ,option -> keyword ,escaped );
1175-
1240+ escaped = escapeConnectionParameter (option -> val );
1241+ appendPQExpBuffer (& conninfo_buf ,"%s=%s" ,option -> keyword ,escaped );
11761242free (escaped );
11771243}
11781244
1179- appendPQExpBufferStr (recoveryconfcontents ,"'\n" );
1180- if (PQExpBufferBroken (recoveryconfcontents ))
1245+ /*
1246+ * Escape the connection string, so that it can be put in the config file.
1247+ * Note that this is different from the escaping of individual connection
1248+ * options above!
1249+ */
1250+ escaped = escape_quotes (conninfo_buf .data );
1251+ appendPQExpBuffer (recoveryconfcontents ,"primary_conninfo = '%s'\n" ,escaped );
1252+ free (escaped );
1253+
1254+ if (PQExpBufferBroken (recoveryconfcontents )||
1255+ PQExpBufferDataBroken (conninfo_buf ))
11811256{
11821257fprintf (stderr ,_ ("%s: out of memory\n" ),progname );
11831258disconnect_and_exit (1 );
11841259}
11851260
1261+ termPQExpBuffer (& conninfo_buf );
1262+
11861263PQconninfoFree (connOptions );
11871264}
11881265