В 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
function GetLastValueOf(const AName: String; var VValue: String): Boolean; var I: Integer; begin Result := False; for I := CookieProp.Count-1 downto 0 do 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) then begin {Do not Localize} FPersistent := True; FExpires := StrToFloat(S); end else if GetLastValueOf('EXPIRES', S) then {Do not Localize} begin FPersistent := True; FExpires := StrToFloat(S); end else 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; if Length(S) > 0 then begin if not IsDomainMatch(AURI.Host, S) then begin Exit; end; FHostOnly := False; FDomain := S; end else 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
Комментариев нет:
Отправка комментария