В Delphi XE2 отыскался баг в TIdCookie.ParseServerCookie. Смотрим код:
Ошибка происходит если строка S после вызова GetLastValueOf('EXPIRES', S) содержит что-нибудь (Length(S) > 0), а GetLastValueOf('DOMAIN', S) возвращает False.
Такое случается, если на вход TIdCookie.ParseServerCookie поступает строка ACookieText типа такой:
CookieName=CookieValue;Path=/;Expires=Wed, 20-Aug-2017 02:20:00 GMT;
Интересно, что ошибки бы не случилось, если бы параметр VValue у функции GetLastValueOf был объявлен как out, а не как var.
Fix. Для исправления этого бага я сделал класс TVCookieManager, который служит заменой для TIdCookieManager. Взять можно тут: https://github.com/coolsoftware/VCookieManager.
Использовать так:
===
Перепечатка материалов блога разрешается с обязательной ссылкой на blog.coolsoftware.ru
functionGetLastValueOf(const AName:String;var VValue:String):Boolean;
var
I:Integer;
begin
Result:=False;
for I := CookieProp.Count-1downto0do
begin
if TextIsSame(CookieProp.Names[I], AName) then
begin
{$IFDEF HAS_TStrings_ValueFromIndex}
VValue := CookieProp.ValueFromIndex[I];
{$ELSE}
VValue :=Copy(CookieProp[I],Pos('=', CookieProp[I])+1, MaxInt);{Do not Localize}
{$ENDIF}
Result:=True;
Exit;
end;
end;
end;
...
if GetLastValueOf('MAX-AGE', S) thenbegin{Do not Localize}
FPersistent :=True;
FExpires :=StrToFloat(S);
end
elseif GetLastValueOf('EXPIRES', S) then{Do not Localize}
begin
FPersistent :=True;
FExpires :=StrToFloat(S);
endelse
begin
FPersistent :=False;
FExpires :=EncodeDate(9999,12,31) +EncodeTime(23,59,59,999);
end;
if GetLastValueOf('DOMAIN', S)then{Do not Localize}
begin
{
If the user agent is configured to reject "public suffixes" and
the domain-attribute is a public suffix:
If the domain-attribute is identical to the canonicalized
request-host:
Let the domain-attribute be the empty string.
Otherwise:
Ignore the cookie entirely and abort these steps.
NOTE: A "public suffix" is a domain that is controlled by a
public registry, such as "com", "co.uk", and "pvt.k12.wy.us".
This step is essential for preventing attacker.com from
disrupting the integrity of example.com by setting a cookie
with a Domain attribute of "com". Unfortunately, the set of
public suffixes (also known as "registry controlled domains")
changes over time. If feasible, user agents SHOULD use an
up-to-date public suffix list, such as the one maintained by
the Mozilla project at <http://publicsuffix.org/>.
}
end;
ifLength(S) >0then
begin
ifnot IsDomainMatch(AURI.Host, S) thenbegin
Exit;
end;
FHostOnly :=False;
FDomain := S;
endelse
begin
FHostOnly :=True;
FDomain := CanonicalizeHostName(AURI.Host);
end;
Ошибка происходит если строка S после вызова GetLastValueOf('EXPIRES', S) содержит что-нибудь (Length(S) > 0), а GetLastValueOf('DOMAIN', S) возвращает False.
Такое случается, если на вход TIdCookie.ParseServerCookie поступает строка ACookieText типа такой:
CookieName=CookieValue;Path=/;Expires=Wed, 20-Aug-2017 02:20:00 GMT;
Интересно, что ошибки бы не случилось, если бы параметр VValue у функции GetLastValueOf был объявлен как out, а не как var.
Fix. Для исправления этого бага я сделал класс TVCookieManager, который служит заменой для TIdCookieManager. Взять можно тут: https://github.com/coolsoftware/VCookieManager.
Использовать так:
var
FixedCookieManager: TVCookieManager;
IdHTTP: TIdHTTP;
...
FixedCookieManager := TVCookieManager.Create;
IdHTTP := TIdHTTP.Create;
IdHTTP.CookieManager := FixedCookieManager;
===
Перепечатка материалов блога разрешается с обязательной ссылкой на blog.coolsoftware.ru