My code is littered with things like this
Write (thePhpFile, ' echo "<option value=\"' +
theControl.Name +
'_selection\">" . $' +
theControl.Name +
'_values[$_POST["' +
theControl.Name +
'_selection"]];');
which genrates the following PHP code
echo "<option value=\"ComboBox1_selection\">" .
$ComboBox1_values[$_POST["ComboBox1_selection"]];?>
Surely there's a better way to handle this? Maybe a Delphi function which I can pass the desired PHP string and have it double up quotes where necessary? Or am I deluding myself?
The basic algorithm would seem to be
// assume all PHP strings are double quoted, even when it's inefficient
find the first double quote, if any
find the last double quote, if any
for every double quote in between
change it to \""
Does that sound right? Maybe I should code it myself?
Hmmm, not so easy ... in the snippet above, we wouldn't want to escape $_POST["ComboBox1_selection"]
- better just to hand code the mess shown at the top?
Any ideas? I'm off now to google "generating php from delphi" - which is probably what I should have done weeks ago :-/
You're not just generating PHP. You're generating PHP that in turn generates HTML. Your program will need to be aware of both languages' string-encoding rules. It will probably be easier to write two separate functions for that:
function QuoteStringForPHP(s: string): string;
function QuoteHTMLAttributeValue(s: string): string;
Given your example, you'd use them like this:
ControlName := theControl.Name;
ValueName := ControlName + '_values';
SelectionName := ControlName + '_selection';
Write(thePhpFile, ' echo ' +
QuoteStringForPHP(
'<option value=' +
QuoteHTMLAttributeValue(SelectionName) +
'>'
) +
'.' +
'$' + ValueName + '[$_POST[' +
QuoteStringForPHP(SelectionName) +
']];'
);
Writing them is straightforward:
// Input: Any sequence of characters
// Output: A single-quoted PHP string literal
function QuoteStringForPHP(s: string): string;
begin
// Commented apostrophes are only to fix Stack Overflow's code highlighting
s := StringReplace(s, '\' {'}, '\\', [rfReplaceAll]);
s := StringReplace(s, '''', '\''' {'}, [rfReplaceAll]);
Result := '''' + s + '''';
end;
// Input: Any sequence of valid HTML text characters
// Precondition: s has not already had any HTML encoding applied to
// it; i.e., no character references
// Output: A single-quoted HTML attribute value
function QuoteHTMLAttributeValue(s: string): string;
begin
s := StringReplace(s, '&', '&', [rfReplaceAll]);
s := StringReplace(s, '''', ''', [rfReplaceAll]);
Result := '''' + s + '''';
end;
I chose to use apostrophes rather than quotation marks since that makes PHP escaping easier. If you use quotation marks for your PHP strings, then you need to worry about variable interpolation. With apostrophes, that problem goes away.
By making QuoteStringForPHP
responsible for quoting and escaping, you make escaping easy. There's no more guesswork about which characters need escaping because they all do. The ones that don't need escaping are only added after the escaping work is complete.
I've read you question several times, but I can't understand what your problem is. I would leave the code as it is.
But it seems that you don't want to use this tiny, but annoying escape characters in your code? As you described, the escaping algorithm is very error prone. It tries to solve a syntactic problem without semantic informations. But how do you provide the parsing algorithm with this information? Right, use escape characters.
But it seems that you don't want to use this tiny, but annoying escape characters in your code? As you described, the escaping algorithm is very error prone. It tries to solve a syntactic problem without semantic informations. But how do you provide the parsing algorithm with this information? Right, use escape characters.
But it seems that you don't want to use this tiny, but annoying escape characters in your code? As you described, the escaping algorithm is very error prone. It tries to solve a syntactic problem without semantic informations. But how do you provide the parsing algorithm with this information? Right, use escape characters. ...
;-)
Well, I can't know your abilities, so I don't know if you can do it yourself. It is not entirely trivial (since character positions change due to inserting), but I'd say it is a problem for a first programming class. (watch those invariants!)
function escapephp(s: string):string;
var first,n,cur,lastcur : integer;
begin
result:=s;
first:=pos('"',result);
if first>0 then // first found?
begin
n:=0;
cur:=first;
while cur<>0 do
begin
lastcur:=cur; // keep last found
cur:=posex('"',result,lastcur+1); // search next
if (lastcur<>first) and (cur<>0) then // next is not last and not first?
begin
insert('\"',result,lastcur); // then insert
inc(cur,2); // we inserted 2 chars so need to correct with 2
end;
end;
end;
end;
The example could do with a bit more thorough testing, I only quickly tested it on your string