Reputation: 263
How do I set the HTTPOnly flag? the TCookie does not have any method or property to specify the HTTPOnly flag.
Upvotes: 1
Views: 2229
Reputation: 1216
Please note that original TCookie.GetHeaderValue() method in HTTPApp.pas may generate an incorrect header when expires > -1 and the system/application time separator is other than the colon sign ":". TCookie.GetHeaderValue() method uses the constant sDateFormat for formatting "Expires" field. Turns out that sDateFormat constant is wrongly defined as:
const
sDateFormat = '"%s", dd "%s" yyyy hh:nn:ss';
If the user changes the application TimeSeparator variable to something other than the colon sign ":", then the expires time will be formated using another character, and not ":" as specified in RFC 1123 (format “Wdy, DD Mon YYYY HH:MM:SS GMT”). Google Chrome 25+ rejects cookies with time separator other than the colon sign, causing complete failure of web applications using it. So the correct GetHeaderValue() method should be:
function TCookieGenerator.GetHeaderValue: string;
const
_DateFormat = '"%s", dd "%s" yyyy hh":"nn":"ss'; // this is the correct constant. HTTPApp.pas wrongly declares it as sDateFormat = '"%s", dd "%s" yyyy hh:nn:ss';
begin
Result := Format('%s=%s; ', [HTTPEncode(FName), HTTPEncode(FValue)]);
if Domain <> '' then
Result := Result + Format('domain=%s; ', [Domain]); { do not localize }
if Path <> '' then
Result := Result + Format('path=%s; ', [Path]); { do not localize }
if Expires > -1 then
Result := Result +
Format(FormatDateTime('"expires="' + _DateFormat + ' "GMT; "', Expires), { do not localize }
[DayOfWeekStr(Expires), MonthStr(Expires)]);
if Secure then Result := Result + 'secure; '; { do not localize }
if HttpOnly then Result := Result + 'HttpOnly'; { do not localize }
if Copy(Result, Length(Result) - 1, MaxInt) = '; ' then
SetLength(Result, Length(Result) - 2);
end;
I've submited QC #113139 about this.
Upvotes: 0
Reputation: 12581
If you talking about TCookie in HttpApp.pas then there is no built in property to support HttpOnly.
You can look at httpApp.pas at the TCookie.GetHeaderValue: string;
implementation to verify.
However a Cookie is just something set in the Header and TWebResponse has a CustomHeaders
property. Where you could Call Response.CustomHeaders.Add(MyCookieValue);
The following class is a modified version of TCookie to support HttpOnly that you can use to generate the cookie correctly.
unit CookieGen;
interface
uses
Sysutils,Classes,HttpApp;
type
TCookieGenerator = class(TObject)
private
FName: string;
FValue: string;
FPath: string;
FDomain: string;
FExpires: TDateTime;
FSecure: Boolean;
FHttpOnly: Boolean;
protected
function GetHeaderValue: string;
public
property Name: string read FName write FName;
property Value: string read FValue write FValue;
property Domain: string read FDomain write FDomain;
property Path: string read FPath write FPath;
property Expires: TDateTime read FExpires write FExpires;
property Secure: Boolean read FSecure write FSecure;
property HttpOnly : Boolean read FHttpOnly write FHttpOnly;
property HeaderValue: string read GetHeaderValue;
end;
implementation
{ TCookieGenerator }
function TCookieGenerator.GetHeaderValue: string;
begin
Result := Format('%s=%s; ', [HTTPEncode(FName), HTTPEncode(FValue)]);
if Domain <> '' then
Result := Result + Format('domain=%s; ', [Domain]); { do not localize }
if Path <> '' then
Result := Result + Format('path=%s; ', [Path]); { do not localize }
if Expires > -1 then
Result := Result +
Format(FormatDateTime('"expires="' + sDateFormat + ' "GMT; "', Expires), { do not localize }
[DayOfWeekStr(Expires), MonthStr(Expires)]);
if Secure then Result := Result + 'secure; '; { do not localize }
if HttpOnly then Result := Result + 'HttpOnly'; { do not localize }
if Copy(Result, Length(Result) - 1, MaxInt) = '; ' then
SetLength(Result, Length(Result) - 2);
end;
end.
Upvotes: 5