1225 lines
38 KiB
Plaintext
1225 lines
38 KiB
Plaintext
|
|
{
|
|
$Project$
|
|
$Workfile$
|
|
$Revision$
|
|
$DateUTC$
|
|
$Id$
|
|
|
|
This file is part of the Indy (Internet Direct) project, and is offered
|
|
under the dual-licensing agreement described on the Indy website.
|
|
(http://www.indyproject.org/)
|
|
|
|
Copyright:
|
|
(c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved.
|
|
}
|
|
{
|
|
$Log$
|
|
}
|
|
{
|
|
Rev 1.9 2/16/2005 7:58:56 AM DSiders
|
|
Modified TIdRequestHeaderInfo to restore the Range property.
|
|
Modified TIdRequestHeaderInfo methods AssignTo, Clear, ProcessHeaders, and
|
|
SetHeaders to include Range property.
|
|
|
|
Rev 1.8 11/11/2004 12:55:38 AM DSiders
|
|
Modified TIdEntityHeaderInfo to fix problems with content-range header
|
|
handling.
|
|
Added ContentRangeInstanceLength property.
|
|
Added HasContentRange property (read-ony).
|
|
Added HasContentRangeInstance property (read-only).
|
|
Moved reading and writing methods to ProcessHeaders and SetHeaders in
|
|
TIdEntityHeaderInfo.
|
|
|
|
Rev 1.7 6/8/2004 10:35:46 AM BGooijen
|
|
fixed overflow
|
|
|
|
Rev 1.6 2004.02.03 5:43:46 PM czhower
|
|
Name changes
|
|
|
|
Rev 1.5 1/22/2004 7:10:08 AM JPMugaas
|
|
Tried to fix AnsiSameText depreciation.
|
|
|
|
Rev 1.4 13.1.2004 ã. 17:17:44 DBondzhev
|
|
moved few methods into protected section to remove some warnings
|
|
|
|
Rev 1.3 10/17/2003 12:09:28 AM DSiders
|
|
Added localization comments.
|
|
|
|
Rev 1.2 20/4/2003 3:46:34 PM SGrobety
|
|
Fix to previous fix... (Dumb me)
|
|
|
|
Rev 1.1 20/4/2003 3:33:58 PM SGrobety
|
|
Changed Content-type default in TIdEntityHeaderInfo back to empty string
|
|
and changed the default of the response object. Solved compatibility
|
|
issue with Netscape servers
|
|
|
|
Rev 1.0 11/13/2002 07:54:24 AM JPMugaas
|
|
}
|
|
|
|
unit IdHTTPHeaderInfo;
|
|
|
|
{
|
|
HTTP Header definition - RFC 2616
|
|
Author: Doychin Bondzhev (doychin@dsoft-bg.com)
|
|
}
|
|
|
|
interface
|
|
|
|
{$i IdCompilerDefines.inc}
|
|
|
|
uses
|
|
Classes,
|
|
IdAuthentication,
|
|
IdGlobal,
|
|
IdGlobalProtocols,
|
|
IdHeaderList;
|
|
|
|
type
|
|
TIdEntityHeaderInfo = class(TPersistent)
|
|
protected
|
|
{$IFDEF USE_OBJECT_ARC}[Weak]{$ENDIF} FOwner: TPersistent;
|
|
FCacheControl: String;
|
|
FRawHeaders: TIdHeaderList;
|
|
FCharSet: String;
|
|
FConnection: string;
|
|
FContentDisposition: string;
|
|
FContentEncoding: string;
|
|
FContentLanguage: string;
|
|
FContentLength: Int64;
|
|
FContentRangeEnd: Int64;
|
|
FContentRangeStart: Int64;
|
|
FContentRangeInstanceLength: Int64;
|
|
FContentRangeUnits: String;
|
|
FContentType: string;
|
|
FContentVersion: string;
|
|
FCustomHeaders: TIdHeaderList;
|
|
FDate: TDateTime;
|
|
FExpires: TDateTime;
|
|
FETag: string;
|
|
FLastModified: TDateTime;
|
|
FPragma: string;
|
|
FHasContentLength: Boolean;
|
|
FTransferEncoding: String;
|
|
//
|
|
procedure AssignTo(Destination: TPersistent); override;
|
|
procedure ProcessHeaders; virtual;
|
|
procedure SetHeaders; virtual;
|
|
function GetOwner: TPersistent; override;
|
|
function GetOwnerComponent: TComponent;
|
|
|
|
procedure SetContentLength(const AValue: Int64);
|
|
procedure SetContentType(const AValue: String);
|
|
procedure SetCustomHeaders(const AValue: TIdHeaderList);
|
|
function GetHasContentRange: Boolean;
|
|
function GetHasContentRangeInstance: Boolean;
|
|
public
|
|
procedure AfterConstruction; override;
|
|
procedure Clear; virtual;
|
|
constructor Create(AOwner: TPersistent); virtual;
|
|
destructor Destroy; override;
|
|
//
|
|
property OwnerComponent: TComponent read GetOwnerComponent;
|
|
property HasContentLength: Boolean read FHasContentLength;
|
|
property HasContentRange: Boolean read GetHasContentRange;
|
|
property HasContentRangeInstance: Boolean read GetHasContentRangeInstance;
|
|
property RawHeaders: TIdHeaderList read FRawHeaders;
|
|
published
|
|
property CacheControl: String read FCacheControl write FCacheControl;
|
|
property CharSet: String read FCharSet write FCharSet;
|
|
property Connection: string read FConnection write FConnection;
|
|
property ContentDisposition: string read FContentDisposition write FContentDisposition;
|
|
property ContentEncoding: string read FContentEncoding write FContentEncoding;
|
|
property ContentLanguage: string read FContentLanguage write FContentLanguage;
|
|
property ContentLength: Int64 read FContentLength write SetContentLength;
|
|
property ContentRangeEnd: Int64 read FContentRangeEnd write FContentRangeEnd;
|
|
property ContentRangeStart: Int64 read FContentRangeStart write FContentRangeStart;
|
|
property ContentRangeInstanceLength: Int64 read FContentRangeInstanceLength write FContentRangeInstanceLength;
|
|
property ContentRangeUnits: String read FContentRangeUnits write FContentRangeUnits;
|
|
property ContentType: string read FContentType write SetContentType;
|
|
property ContentVersion: string read FContentVersion write FContentVersion;
|
|
property CustomHeaders: TIdHeaderList read FCustomHeaders write SetCustomHeaders;
|
|
property Date: TDateTime read FDate write FDate;
|
|
property ETag: string read FETag write FETag;
|
|
property Expires: TDateTime read FExpires write FExpires;
|
|
property LastModified: TDateTime read FLastModified write FLastModified;
|
|
property Pragma: string read FPragma write FPragma;
|
|
property TransferEncoding: string read FTransferEncoding write FTransferEncoding;
|
|
end;
|
|
|
|
TIdProxyConnectionInfo = class(TPersistent)
|
|
protected
|
|
FAuthentication: TIdAuthentication;
|
|
FPassword: string;
|
|
FPort: Integer;
|
|
FServer: string;
|
|
FUsername: string;
|
|
FBasicByDefault: Boolean;
|
|
|
|
procedure AssignTo(Destination: TPersistent); override;
|
|
procedure SetProxyPort(const Value: Integer);
|
|
procedure SetProxyServer(const Value: string);
|
|
public
|
|
procedure AfterConstruction; override;
|
|
constructor Create;
|
|
procedure Clear;
|
|
destructor Destroy; override;
|
|
procedure SetHeaders(Headers: TIdHeaderList);
|
|
//
|
|
property Authentication: TIdAuthentication read FAuthentication write FAuthentication;
|
|
published
|
|
|
|
property BasicAuthentication: boolean read FBasicByDefault write FBasicByDefault;
|
|
property ProxyPassword: string read FPassword write FPassword;
|
|
property ProxyPort: Integer read FPort write SetProxyPort;
|
|
property ProxyServer: string read FServer write SetProxyServer;
|
|
property ProxyUsername: string read FUsername write FUserName;
|
|
end;
|
|
|
|
TIdEntityRange = class(TCollectionItem)
|
|
protected
|
|
FStartPos: Int64;
|
|
FEndPos: Int64;
|
|
FSuffixLength: Int64;
|
|
function GetText: String;
|
|
procedure SetText(const AValue: String);
|
|
public
|
|
constructor Create(Collection: TCollection); override;
|
|
published
|
|
property StartPos: Int64 read FStartPos write FStartPos;
|
|
property EndPos: Int64 read FEndPos write FEndPos;
|
|
property SuffixLength: Int64 read FSuffixLength write FSuffixLength;
|
|
property Text: String read GetText write SetText;
|
|
end;
|
|
|
|
TIdEntityRanges = class(TOwnedCollection)
|
|
protected
|
|
FUnits: String;
|
|
function GetRange(Index: Integer): TIdEntityRange;
|
|
procedure SetRange(Index: Integer; AValue: TIdEntityRange);
|
|
function GetText: String;
|
|
procedure SetText(const AValue: String);
|
|
procedure SetUnits(const AValue: String);
|
|
public
|
|
constructor Create(AOwner: TPersistent); reintroduce;
|
|
function Add: TIdEntityRange; reintroduce;
|
|
property Ranges[Index: Integer]: TIdEntityRange read GetRange write SetRange; default;
|
|
published
|
|
property Text: String read GetText write SetText;
|
|
property Units: String read FUnits write SetUnits;
|
|
end;
|
|
|
|
TIdRequestHeaderInfo = class(TIdEntityHeaderInfo)
|
|
protected
|
|
FAccept: String;
|
|
FAcceptCharSet: String;
|
|
FAcceptEncoding: String;
|
|
FAcceptLanguage: String;
|
|
FExpect: String;
|
|
FFrom: String;
|
|
FPassword: String;
|
|
FReferer: String;
|
|
FUserAgent: String;
|
|
FUserName: String;
|
|
FHost: String;
|
|
FProxyConnection: String;
|
|
FRanges: TIdEntityRanges;
|
|
FBasicByDefault: Boolean;
|
|
FAuthentication: TIdAuthentication;
|
|
FMethodOverride: String;
|
|
//
|
|
procedure AssignTo(Destination: TPersistent); override;
|
|
procedure ProcessHeaders; override;
|
|
procedure SetHeaders; override;
|
|
function GetRange: String;
|
|
procedure SetRange(const AValue: String);
|
|
procedure SetRanges(AValue: TIdEntityRanges);
|
|
public
|
|
//
|
|
constructor Create(AOwner: TPersistent); override;
|
|
destructor Destroy; override;
|
|
procedure Clear; override;
|
|
property Authentication: TIdAuthentication read FAuthentication write FAuthentication;
|
|
published
|
|
property Accept: String read FAccept write FAccept;
|
|
property AcceptCharSet: String read FAcceptCharSet write FAcceptCharSet;
|
|
property AcceptEncoding: String read FAcceptEncoding write FAcceptEncoding;
|
|
property AcceptLanguage: String read FAcceptLanguage write FAcceptLanguage;
|
|
property BasicAuthentication: boolean read FBasicByDefault write FBasicByDefault;
|
|
property Host: String read FHost write FHost;
|
|
property From: String read FFrom write FFrom;
|
|
property Password: String read FPassword write FPassword;
|
|
property Referer: String read FReferer write FReferer;
|
|
property UserAgent: String read FUserAgent write FUserAgent;
|
|
property Username: String read FUsername write FUsername;
|
|
property ProxyConnection: String read FProxyConnection write FProxyConnection;
|
|
property Range: String read GetRange write SetRange; //deprecated 'Use Ranges property';
|
|
property Ranges: TIdEntityRanges read FRanges write SetRanges;
|
|
property MethodOverride: String read FMethodOverride write FMethodOverride;
|
|
end;
|
|
|
|
TIdResponseHeaderInfo = class(TIdEntityHeaderInfo)
|
|
protected
|
|
FAcceptPatch: string;
|
|
FAcceptRanges: string;
|
|
FLocation: string;
|
|
FServer: string;
|
|
FProxyConnection: string;
|
|
FProxyAuthenticate: TIdHeaderList;
|
|
FWWWAuthenticate: TIdHeaderList;
|
|
//
|
|
procedure SetProxyAuthenticate(const Value: TIdHeaderList);
|
|
procedure SetWWWAuthenticate(const Value: TIdHeaderList);
|
|
procedure SetAcceptPatch(const Value: string);
|
|
procedure SetAcceptRanges(const Value: string);
|
|
procedure ProcessHeaders; override;
|
|
procedure SetHeaders; override;
|
|
public
|
|
|
|
procedure Clear; override;
|
|
constructor Create(AOwner: TPersistent); override;
|
|
destructor Destroy; override;
|
|
published
|
|
property AcceptPatch: string read FAcceptPatch write SetAcceptPatch;
|
|
property AcceptRanges: string read FAcceptRanges write SetAcceptRanges;
|
|
property Location: string read FLocation write FLocation;
|
|
property ProxyConnection: string read FProxyConnection write FProxyConnection;
|
|
property ProxyAuthenticate: TIdHeaderList read FProxyAuthenticate write SetProxyAuthenticate;
|
|
property Server: string read FServer write FServer;
|
|
property WWWAuthenticate: TIdHeaderList read FWWWAuthenticate write SetWWWAuthenticate;
|
|
end;
|
|
|
|
TIdMetaHTTPEquiv = class(TIdEntityHeaderInfo)
|
|
public
|
|
procedure ProcessMetaHTTPEquiv(AStream: TStream);
|
|
end;
|
|
|
|
var
|
|
GIdDefaultUserAgent: String = 'Mozilla/3.0 (compatible; Indy Library)'; {do not localize}
|
|
|
|
implementation
|
|
|
|
uses
|
|
SysUtils;
|
|
|
|
{ TIdEntityHeaderInfo }
|
|
|
|
constructor TIdEntityHeaderInfo.Create(AOwner: TPersistent);
|
|
begin
|
|
inherited Create;
|
|
FOwner := AOwner;
|
|
// HTTP does not fold headers based on line length
|
|
FRawHeaders := TIdHeaderList.Create(QuoteHTTP);
|
|
FRawHeaders.FoldLength := MaxInt;
|
|
FCustomHeaders := TIdHeaderList.Create(QuoteHTTP);
|
|
FCustomHeaders.FoldLength := MaxInt;
|
|
end;
|
|
|
|
procedure TIdEntityHeaderInfo.AfterConstruction;
|
|
begin
|
|
inherited AfterConstruction;
|
|
Clear;
|
|
end;
|
|
|
|
destructor TIdEntityHeaderInfo.Destroy;
|
|
begin
|
|
FreeAndNil(FRawHeaders);
|
|
FreeAndNil(FCustomHeaders);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TIdEntityHeaderInfo.AssignTo(Destination: TPersistent);
|
|
var
|
|
LDest: TIdEntityHeaderInfo;
|
|
begin
|
|
if Destination is TIdEntityHeaderInfo then
|
|
begin
|
|
LDest := TIdEntityHeaderInfo(Destination);
|
|
LDest.FRawHeaders.Assign(FRawHeaders);
|
|
LDest.FCustomHeaders.Assign(FCustomHeaders);
|
|
LDest.FCacheControl := FCacheControl;
|
|
LDest.FCharSet := FCharSet;
|
|
LDest.FContentDisposition := FContentDisposition;
|
|
LDest.FContentEncoding := FContentEncoding;
|
|
LDest.FContentLanguage := FContentLanguage;
|
|
LDest.FContentType := FContentType;
|
|
LDest.FContentVersion := FContentVersion;
|
|
LDest.FContentLength := FContentLength;
|
|
LDest.FContentRangeEnd:= FContentRangeEnd;
|
|
LDest.FContentRangeStart:= FContentRangeStart;
|
|
LDest.FContentRangeInstanceLength := FContentRangeInstanceLength;
|
|
LDest.FContentRangeUnits := FContentRangeUnits;
|
|
LDest.FDate := FDate;
|
|
LDest.FETag := FETag;
|
|
LDest.FExpires := FExpires;
|
|
LDest.FLastModified := FLastModified;
|
|
end else
|
|
begin
|
|
inherited AssignTo(Destination);
|
|
end;
|
|
end;
|
|
|
|
procedure TIdEntityHeaderInfo.Clear;
|
|
begin
|
|
FCacheControl := '';
|
|
FCharSet := '';
|
|
FConnection := '';
|
|
FContentVersion := '';
|
|
FContentDisposition := '';
|
|
FContentEncoding := '';
|
|
FContentLanguage := '';
|
|
|
|
{ S.G. 20/4/2003
|
|
|
|
Was FContentType := 'Text/HTML'
|
|
|
|
Shouldn't be set here but in response.
|
|
Requests, by default, have NO content-type.
|
|
This caused problems with some netscape servers
|
|
}
|
|
FContentType := '';
|
|
|
|
FContentLength := -1;
|
|
FContentRangeStart := -1;
|
|
FContentRangeEnd := -1;
|
|
FContentRangeInstanceLength := -1;
|
|
FContentRangeUnits := '';
|
|
FDate := 0;
|
|
FLastModified := 0;
|
|
FETag := '';
|
|
FExpires := 0;
|
|
FRawHeaders.Clear;
|
|
end;
|
|
|
|
procedure TIdEntityHeaderInfo.ProcessHeaders;
|
|
var
|
|
LSecs: Int64;
|
|
lValue: string;
|
|
lCRange: string;
|
|
lILength: string;
|
|
begin
|
|
FCacheControl := FRawHeaders.Values['Cache-control']; {do not localize}
|
|
FConnection := FRawHeaders.Values['Connection']; {do not localize}
|
|
FContentVersion := FRawHeaders.Values['Content-Version']; {do not localize}
|
|
FContentDisposition := FRawHeaders.Values['Content-Disposition']; {do not localize}
|
|
FContentEncoding := FRawHeaders.Values['Content-Encoding']; {do not localize}
|
|
FContentLanguage := FRawHeaders.Values['Content-Language']; {do not localize}
|
|
ContentType := FRawHeaders.Values['Content-Type']; {do not localize}
|
|
FContentLength := IndyStrToInt64(FRawHeaders.Values['Content-Length'], -1); {do not localize}
|
|
FHasContentLength := FContentLength >= 0;
|
|
|
|
FContentRangeStart := -1;
|
|
FContentRangeEnd := -1;
|
|
FContentRangeInstanceLength := -1;
|
|
FContentRangeUnits := '';
|
|
|
|
{
|
|
handle content-range headers, like:
|
|
|
|
content-range: bytes 1-65536/102400
|
|
content-range: bytes */102400
|
|
content-range: bytes 1-65536/*
|
|
}
|
|
lValue := FRawHeaders.Values['Content-Range']; {do not localize}
|
|
if lValue <> '' then
|
|
begin
|
|
// strip the bytes unit, and keep the range and instance info
|
|
FContentRangeUnits := Fetch(lValue);
|
|
lCRange := Fetch(lValue, '/');
|
|
lILength := Fetch(lValue);
|
|
|
|
FContentRangeStart := IndyStrToInt64(Fetch(lCRange, '-'), -1);
|
|
FContentRangeEnd := IndyStrToInt64(lCRange, -1);
|
|
FContentRangeInstanceLength := IndyStrToInt64(lILength, -1);
|
|
end;
|
|
|
|
// RLebeau 03/04/2009: RFC 2616 Section 14.18 says:
|
|
//
|
|
// "A received message that does not have a Date header field MUST be
|
|
// assigned one by the recipient if the message will be cached by that
|
|
// recipient or gatewayed via a protocol which requires a Date."
|
|
|
|
lValue := FRawHeaders.Values['Date']; {do not localize}
|
|
if lValue <> '' then
|
|
begin
|
|
FDate := GMTToLocalDateTime(lValue);
|
|
end else
|
|
begin
|
|
FDate := Now;
|
|
end;
|
|
|
|
FLastModified := GMTToLocalDateTime(FRawHeaders.Values['Last-Modified']); {do not localize}
|
|
|
|
// RLebeau 01/23/2006 - IIS fix
|
|
lValue := FRawHeaders.Values['Expires']; {do not localize}
|
|
if IsNumeric(lValue) then
|
|
begin
|
|
// This is happening when expires is an integer number in seconds
|
|
LSecs := IndyStrToInt64(lValue);
|
|
// RLebeau 01/23/2005 - IIS sometimes sends an 'Expires: -1' header
|
|
// should we be handling it as actually meaning "Now minus 1 second" instead?
|
|
if LSecs >= 0 then begin
|
|
FExpires := Now + (LSecs / SecsPerDay);
|
|
end else begin
|
|
FExpires := 0.0;
|
|
end;
|
|
end else
|
|
begin
|
|
// RLebeau 03/04/2009: RFC 2616 Section 14.21 says:
|
|
//
|
|
// "The format is an absolute date and time as defined by HTTP-date in
|
|
// section 3.3.1; it MUST be in RFC 1123 date format:
|
|
//
|
|
// Expires = "Expires" ":" HTTP-date
|
|
//
|
|
// HTTP/1.1 clients and caches MUST treat other invalid date formats,
|
|
// especially including the value "0", as in the past (i.e., "already
|
|
// expired")."
|
|
|
|
try
|
|
FExpires := GMTToLocalDateTime(lValue);
|
|
except
|
|
FExpires := Now - (1 / SecsPerDay);
|
|
end;
|
|
end;
|
|
|
|
FETag := FRawHeaders.Values['ETag']; {do not localize}
|
|
FPragma := FRawHeaders.Values['Pragma']; {do not localize}
|
|
FTransferEncoding := FRawHeaders.Values['Transfer-Encoding']; {do not localize}
|
|
end;
|
|
|
|
procedure TIdEntityHeaderInfo.SetHeaders;
|
|
begin
|
|
FRawHeaders.Clear;
|
|
if Length(FConnection) > 0 then
|
|
begin
|
|
FRawHeaders.Values['Connection'] := FConnection; {do not localize}
|
|
end;
|
|
if Length(FContentVersion) > 0 then
|
|
begin
|
|
FRawHeaders.Values['Content-Version'] := FContentVersion; {do not localize}
|
|
end;
|
|
if Length(FContentDisposition) > 0 then
|
|
begin
|
|
FRawHeaders.Values['Content-Disposition'] := FContentDisposition; {do not localize}
|
|
end;
|
|
if Length(FContentEncoding) > 0 then
|
|
begin
|
|
FRawHeaders.Values['Content-Encoding'] := FContentEncoding; {do not localize}
|
|
end;
|
|
if Length(FContentLanguage) > 0 then
|
|
begin
|
|
FRawHeaders.Values['Content-Language'] := FContentLanguage; {do not localize}
|
|
end;
|
|
if Length(FContentType) > 0 then
|
|
begin
|
|
FRawHeaders.Values['Content-Type'] := FContentType; {do not localize}
|
|
FRawHeaders.Params['Content-Type', 'charset'] := FCharSet; {do not localize}
|
|
end;
|
|
if FContentLength >= 0 then
|
|
begin
|
|
FRawHeaders.Values['Content-Length'] := IntToStr(FContentLength); {do not localize}
|
|
end;
|
|
|
|
{ removed setting Content-Range header for entities... deferred to response }
|
|
|
|
if Length(FCacheControl) > 0 then
|
|
begin
|
|
FRawHeaders.Values['Cache-control'] := FCacheControl; {do not localize}
|
|
end;
|
|
if FDate > 0 then
|
|
begin
|
|
FRawHeaders.Values['Date'] := LocalDateTimeToHttpStr(FDate); {do not localize}
|
|
end;
|
|
if Length(FETag) > 0 then
|
|
begin
|
|
FRawHeaders.Values['ETag'] := FETag; {do not localize}
|
|
end;
|
|
if FExpires > 0 then
|
|
begin
|
|
FRawHeaders.Values['Expires'] := LocalDateTimeToHttpStr(FExpires); {do not localize}
|
|
end;
|
|
if Length(FPragma) > 0 then
|
|
begin
|
|
FRawHeaders.Values['Pragma'] := FPragma; {do not localize}
|
|
end;
|
|
if Length(FTransferEncoding) > 0 then
|
|
begin
|
|
FRawHeaders.Values['Transfer-Encoding'] := FTransferEncoding; {do not localize}
|
|
end;
|
|
if FCustomHeaders.Count > 0 then
|
|
begin
|
|
// append custom headers
|
|
// TODO: use AddStrings() instead?
|
|
FRawHeaders.Text := FRawHeaders.Text + FCustomHeaders.Text;
|
|
end;
|
|
end;
|
|
|
|
procedure TIdEntityHeaderInfo.SetCustomHeaders(const AValue: TIdHeaderList);
|
|
begin
|
|
FCustomHeaders.Assign(AValue);
|
|
end;
|
|
|
|
procedure TIdEntityHeaderInfo.SetContentLength(const AValue: Int64);
|
|
begin
|
|
FContentLength := AValue;
|
|
FHasContentLength := FContentLength >= 0;
|
|
end;
|
|
|
|
procedure TIdEntityHeaderInfo.SetContentType(const AValue: String);
|
|
var
|
|
S, LCharSet: string;
|
|
LComp: TComponent;
|
|
begin
|
|
if AValue <> '' then begin
|
|
FContentType := RemoveHeaderEntry(AValue, 'charset', LCharSet, QuoteHTTP); {do not localize}
|
|
|
|
{RLebeau: the ContentType property is streamed after the CharSet property,
|
|
so do not overwrite it during streaming}
|
|
LComp := OwnerComponent;
|
|
if Assigned(LComp) and (csReading in LComp.ComponentState) then begin
|
|
Exit;
|
|
end;
|
|
|
|
// RLebeau: per RFC 2616 Section 3.7.1:
|
|
//
|
|
// The "charset" parameter is used with some media types to define the
|
|
// character set (section 3.4) of the data. When no explicit charset
|
|
// parameter is provided by the sender, media subtypes of the "text"
|
|
// type are defined to have a default charset value of "ISO-8859-1" when
|
|
// received via HTTP. Data in character sets other than "ISO-8859-1" or
|
|
// its subsets MUST be labeled with an appropriate charset value. See
|
|
// section 3.4.1 for compatibility problems.
|
|
|
|
// RLebeau: per RFC 3023 Sections 3.1, 3.3, 3.6, and 8.5:
|
|
//
|
|
// Conformant with [RFC2046], if a text/xml entity is received with
|
|
// the charset parameter omitted, MIME processors and XML processors
|
|
// MUST use the default charset value of "us-ascii"[ASCII]. In cases
|
|
// where the XML MIME entity is transmitted via HTTP, the default
|
|
// charset value is still "us-ascii". (Note: There is an
|
|
// inconsistency between this specification and HTTP/1.1, which uses
|
|
// ISO-8859-1[ISO8859] as the default for a historical reason. Since
|
|
// XML is a new format, a new default should be chosen for better
|
|
// I18N. US-ASCII was chosen, since it is the intersection of UTF-8
|
|
// and ISO-8859-1 and since it is already used by MIME.)
|
|
//
|
|
// ...
|
|
//
|
|
// The charset parameter of text/xml-external-parsed-entity is
|
|
// handled the same as that of text/xml as described in Section 3.1
|
|
//
|
|
// ...
|
|
//
|
|
// The following list applies to text/xml, text/xml-external-parsed-
|
|
// entity, and XML-based media types under the top-level type "text"
|
|
// that define the charset parameter according to this specification:
|
|
//
|
|
// - If the charset parameter is not specified, the default is "us-
|
|
// ascii". The default of "iso-8859-1" in HTTP is explicitly
|
|
// overridden.
|
|
//
|
|
// ...
|
|
//
|
|
// Omitting the charset parameter is NOT RECOMMENDED for text/xml. For
|
|
// example, even if the contents of the XML MIME entity are UTF-16 or
|
|
// UTF-8, or the XML MIME entity has an explicit encoding declaration,
|
|
// XML and MIME processors MUST assume the charset is "us-ascii".
|
|
|
|
if (LCharSet = '') and IsHeaderMediaType(FContentType, 'text') then begin {do not localize}
|
|
S := ExtractHeaderMediaSubType(FContentType);
|
|
if (PosInStrArray(S, ['xml', 'xml-external-parsed-entity'], False) >= 0) or TextEndsWith(S, '+xml') then begin {do not localize}
|
|
LCharSet := 'us-ascii'; {do not localize}
|
|
end else begin
|
|
LCharSet := 'ISO-8859-1'; {do not localize}
|
|
end;
|
|
end;
|
|
|
|
{RLebeau: override the current CharSet only if the header specifies a new value}
|
|
if LCharSet <> '' then begin
|
|
FCharSet := LCharSet;
|
|
end;
|
|
end else begin
|
|
FContentType := '';
|
|
FCharSet := '';
|
|
end;
|
|
end;
|
|
|
|
function TIdEntityHeaderInfo.GetHasContentRange: Boolean;
|
|
begin
|
|
Result := (FContentRangeEnd >= 0);
|
|
end;
|
|
|
|
function TIdEntityHeaderInfo.GetHasContentRangeInstance: Boolean;
|
|
begin
|
|
Result := (FContentRangeInstanceLength >= 0);
|
|
end;
|
|
|
|
function TIdEntityHeaderInfo.GetOwner: TPersistent;
|
|
begin
|
|
Result := FOwner;
|
|
end;
|
|
|
|
type
|
|
TPersistentAccess = class(TPersistent)
|
|
end;
|
|
|
|
function TIdEntityHeaderInfo.GetOwnerComponent: TComponent;
|
|
var
|
|
// under ARC, convert a weak reference to a strong reference before working with it
|
|
LOwner: TPersistent;
|
|
begin
|
|
Result := nil;
|
|
LOwner := GetOwner;
|
|
while LOwner <> nil do begin
|
|
if LOwner is TComponent then begin
|
|
Result := TComponent(LOwner);
|
|
Exit;
|
|
end;
|
|
LOwner := TPersistentAccess(LOwner).GetOwner;
|
|
end;
|
|
end;
|
|
|
|
{ TIdProxyConnectionInfo }
|
|
|
|
constructor TIdProxyConnectionInfo.Create;
|
|
begin
|
|
inherited Create;
|
|
end;
|
|
|
|
procedure TIdProxyConnectionInfo.AfterConstruction;
|
|
begin
|
|
inherited AfterConstruction;
|
|
Clear;
|
|
end;
|
|
|
|
destructor TIdProxyConnectionInfo.Destroy;
|
|
begin
|
|
FreeAndNil(FAuthentication);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TIdProxyConnectionInfo.AssignTo(Destination: TPersistent);
|
|
var
|
|
LDest: TIdProxyConnectionInfo;
|
|
begin
|
|
if Destination is TIdProxyConnectionInfo then
|
|
begin
|
|
LDest := TIdProxyConnectionInfo(Destination);
|
|
LDest.FPassword := FPassword;
|
|
LDest.FPort := FPort;
|
|
LDest.FServer := FServer;
|
|
LDest.FUsername := FUsername;
|
|
LDest.FBasicByDefault := FBasicByDefault;
|
|
end else
|
|
begin
|
|
inherited AssignTo(Destination);
|
|
end;
|
|
end;
|
|
|
|
procedure TIdProxyConnectionInfo.Clear;
|
|
begin
|
|
FServer := '';
|
|
FUsername := '';
|
|
FPassword := '';
|
|
FPort := 0;
|
|
end;
|
|
|
|
procedure TIdProxyConnectionInfo.SetHeaders(Headers: TIdHeaderList);
|
|
var
|
|
S: String;
|
|
begin
|
|
if Assigned(Authentication) then begin
|
|
S := Authentication.Authentication;
|
|
end
|
|
// Use Basic authentication by default
|
|
else if FBasicByDefault then begin
|
|
FAuthentication := TIdBasicAuthentication.Create;
|
|
// TODO: use FAuthentication Username/Password properties instead
|
|
FAuthentication.Params.Values['Username'] := FUsername; {do not localize}
|
|
FAuthentication.Params.Values['Password'] := FPassword; {do not localize}
|
|
S := FAuthentication.Authentication;
|
|
end else begin
|
|
S := '';
|
|
end;
|
|
if Length(S) > 0 then begin
|
|
Headers.Values['Proxy-Authorization'] := S; {do not localize}
|
|
end;
|
|
end;
|
|
|
|
procedure TIdProxyConnectionInfo.SetProxyPort(const Value: Integer);
|
|
begin
|
|
if Value <> FPort then
|
|
begin
|
|
FreeAndNil(FAuthentication);
|
|
end;
|
|
FPort := Value;
|
|
end;
|
|
|
|
procedure TIdProxyConnectionInfo.SetProxyServer(const Value: string);
|
|
begin
|
|
if not TextIsSame(Value, FServer) then
|
|
begin
|
|
FreeAndNil(FAuthentication);
|
|
end;
|
|
FServer := Value;
|
|
end;
|
|
|
|
{ TIdEntityRange }
|
|
|
|
constructor TIdEntityRange.Create(Collection: TCollection);
|
|
begin
|
|
inherited Create(Collection);
|
|
FStartPos := -1;
|
|
FEndPos := -1;
|
|
FSuffixLength := -1;
|
|
end;
|
|
|
|
function TIdEntityRange.GetText: String;
|
|
begin
|
|
if (FStartPos >= 0) or (FEndPos >= 0) then
|
|
begin
|
|
if FEndPos >= 0 then
|
|
begin
|
|
Result := IntToStr(FStartPos) + '-' + IntToStr(FEndPos); {do not localize}
|
|
end else begin
|
|
Result := IntToStr(FStartPos) + '-'; {do not localize}
|
|
end;
|
|
end
|
|
else if FSuffixLength >= 0 then begin
|
|
Result := '-' + IntToStr(FSuffixLength);
|
|
end
|
|
else begin
|
|
Result := '';
|
|
end;
|
|
end;
|
|
|
|
procedure TIdEntityRange.SetText(const AValue: String);
|
|
var
|
|
LValue, S: String;
|
|
begin
|
|
LValue := Trim(AValue);
|
|
if LValue <> '' then
|
|
begin
|
|
S := Fetch(LValue, '-'); {do not localize}
|
|
if S <> '' then begin
|
|
FStartPos := StrToInt64Def(S, -1);
|
|
FEndPos := StrToInt64Def(Fetch(LValue), -1);
|
|
FSuffixLength := -1;
|
|
end else begin
|
|
FStartPos := -1;
|
|
FEndPos := -1;
|
|
FSuffixLength := StrToInt64Def(Fetch(LValue), -1);
|
|
end;
|
|
end else begin
|
|
FStartPos := -1;
|
|
FEndPos := -1;
|
|
FSuffixLength := -1;
|
|
end;
|
|
end;
|
|
|
|
{ TIdEntityRanges }
|
|
|
|
constructor TIdEntityRanges.Create(AOwner: TPersistent);
|
|
begin
|
|
inherited Create(AOwner, TIdEntityRange);
|
|
FUnits := 'bytes'; {do not localize}
|
|
end;
|
|
|
|
function TIdEntityRanges.Add: TIdEntityRange;
|
|
begin
|
|
Result := TIdEntityRange(inherited Add);
|
|
end;
|
|
|
|
function TIdEntityRanges.GetRange(Index: Integer): TIdEntityRange;
|
|
begin
|
|
Result := TIdEntityRange(inherited GetItem(Index));
|
|
end;
|
|
|
|
procedure TIdEntityRanges.SetRange(Index: Integer; AValue: TIdEntityRange);
|
|
begin
|
|
inherited SetItem(Index, AValue);
|
|
end;
|
|
|
|
function TIdEntityRanges.GetText: String;
|
|
var
|
|
I: Integer;
|
|
S: String;
|
|
begin
|
|
Result := '';
|
|
for I := 0 to Count-1 do begin
|
|
S := Ranges[I].Text;
|
|
if S <> '' then begin
|
|
if Result <> '' then begin
|
|
Result := Result + ','; {do not localize}
|
|
end;
|
|
Result := Result + S;
|
|
end;
|
|
end;
|
|
if Result <> '' then begin
|
|
Result := FUnits + '=' + Result; {do not localize}
|
|
end;
|
|
end;
|
|
|
|
procedure TIdEntityRanges.SetText(const AValue: String);
|
|
var
|
|
LUnits, LTmp: String;
|
|
LRanges: TStringList;
|
|
I: Integer;
|
|
LRange: TIdEntityRange;
|
|
begin
|
|
LTmp := Trim(AValue);
|
|
BeginUpdate;
|
|
try
|
|
Clear;
|
|
if Pos('=', LTmp) > 0 then begin {do not localize}
|
|
LUnits := Fetch(LTmp, '='); {do not localize}
|
|
end;
|
|
SetUnits(LUnits);
|
|
LRanges := TStringList.Create;
|
|
try
|
|
SplitDelimitedString(LTmp, LRanges, True, ','); {do not localize}
|
|
for I := 0 to LRanges.Count-1 do begin
|
|
LTmp := Trim(LRanges[I]);
|
|
if LTmp <> '' then begin
|
|
LRange := Add;
|
|
try
|
|
LRange.Text := LTmp;
|
|
except
|
|
LRange.Free;
|
|
raise;
|
|
end;
|
|
end;
|
|
end;
|
|
finally
|
|
LRanges.Free;
|
|
end;
|
|
finally
|
|
EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure TIdEntityRanges.SetUnits(const AValue: String);
|
|
var
|
|
LUnits: String;
|
|
begin
|
|
LUnits := Trim(AValue);
|
|
if LUnits <> '' then begin
|
|
FUnits := LUnits;
|
|
end else begin
|
|
FUnits := 'bytes'; {do not localize}
|
|
end;
|
|
end;
|
|
|
|
{ TIdRequestHeaderInfo }
|
|
|
|
constructor TIdRequestHeaderInfo.Create(AOwner: TPersistent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
FRanges := TIdEntityRanges.Create(Self);
|
|
end;
|
|
|
|
destructor TIdRequestHeaderInfo.Destroy;
|
|
begin
|
|
FreeAndNil(FAuthentication);
|
|
FreeAndNil(FRanges);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TIdRequestHeaderInfo.ProcessHeaders;
|
|
begin
|
|
inherited ProcessHeaders;
|
|
|
|
FAccept := FRawHeaders.Values['Accept']; {do not localize}
|
|
FAcceptCharSet := FRawHeaders.Values['Accept-Charset']; {do not localize}
|
|
FAcceptEncoding := FRawHeaders.Values['Accept-Encoding']; {do not localize}
|
|
FAcceptLanguage := FRawHeaders.Values['Accept-Language']; {do not localize}
|
|
FHost := FRawHeaders.Values['Host']; {do not localize}
|
|
FFrom := FRawHeaders.Values['From']; {do not localize}
|
|
FReferer := FRawHeaders.Values['Referer']; {do not localize}
|
|
FUserAgent := FRawHeaders.Values['User-Agent']; {do not localize}
|
|
FRanges.Text := FRawHeaders.Values['Range']; {do not localize}
|
|
FMethodOverride := FRawHeaders.Values['X-HTTP-Method-Override']; {do not localize}
|
|
end;
|
|
|
|
procedure TIdRequestHeaderInfo.AssignTo(Destination: TPersistent);
|
|
var
|
|
LDest: TIdRequestHeaderInfo;
|
|
begin
|
|
if Destination is TIdRequestHeaderInfo then
|
|
begin
|
|
LDest := TIdRequestHeaderInfo(Destination);
|
|
LDest.FAccept := FAccept;
|
|
LDest.FAcceptCharSet := FAcceptCharset;
|
|
LDest.FAcceptEncoding := FAcceptEncoding;
|
|
LDest.FAcceptLanguage := FAcceptLanguage;
|
|
|
|
LDest.FFrom := FFrom;
|
|
LDest.FUsername := FUsername;
|
|
LDest.FPassword := FPassword;
|
|
LDest.FReferer := FReferer;
|
|
LDest.FUserAgent := FUserAgent;
|
|
LDest.FBasicByDefault := FBasicByDefault;
|
|
|
|
LDest.FRanges.Assign(FRanges);
|
|
LDest.FMethodOverride := FMethodOverride;
|
|
|
|
// TODO: omitted intentionally?
|
|
// LDest.FHost := FHost;
|
|
// LDest.FProxyConnection := FProxyConnection;
|
|
end;
|
|
|
|
inherited AssignTo(Destination);
|
|
end;
|
|
|
|
procedure TIdRequestHeaderInfo.Clear;
|
|
begin
|
|
FAccept := 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'; // 'text/html, */*'; {do not localize}
|
|
FAcceptCharSet := '';
|
|
FUserAgent := GIdDefaultUserAgent;
|
|
FBasicByDefault := false;
|
|
FRanges.Text := '';
|
|
FMethodOverride := '';
|
|
|
|
// TODO: omitted intentionally?
|
|
// FAcceptEncoding := '';
|
|
// FAcceptLanguage := '';
|
|
// FHost := '';
|
|
// FFrom := '';
|
|
// FPassword := '';
|
|
// FUsername := '';
|
|
// FReferer := '';
|
|
// FProxyConnection := '';
|
|
|
|
inherited Clear;
|
|
end;
|
|
|
|
function TIdRequestHeaderInfo.GetRange: String;
|
|
begin
|
|
Result := FRanges.Text;
|
|
end;
|
|
|
|
procedure TIdRequestHeaderInfo.SetRange(const AValue: String);
|
|
begin
|
|
FRanges.Text := AValue;
|
|
end;
|
|
|
|
procedure TIdRequestHeaderInfo.SetRanges(AValue: TIdEntityRanges);
|
|
begin
|
|
FRanges.Assign(AValue);
|
|
end;
|
|
|
|
procedure TIdRequestHeaderInfo.SetHeaders;
|
|
var
|
|
S: String;
|
|
begin
|
|
inherited SetHeaders;
|
|
|
|
if Length(FProxyConnection) > 0 then
|
|
begin
|
|
FRawHeaders.Values['Proxy-Connection'] := FProxyConnection; {do not localize}
|
|
end;
|
|
if Length(FHost) > 0 then
|
|
begin
|
|
FRawHeaders.Values['Host'] := FHost; {do not localize}
|
|
end;
|
|
if Length(FAccept) > 0 then
|
|
begin
|
|
FRawHeaders.Values['Accept'] := FAccept; {do not localize}
|
|
end;
|
|
if Length(FAcceptCharset) > 0 then
|
|
begin
|
|
FRawHeaders.Values['Accept-Charset'] := FAcceptCharSet; {do not localize}
|
|
end;
|
|
if Length(FAcceptEncoding) > 0 then
|
|
begin
|
|
FRawHeaders.Values['Accept-Encoding'] := FAcceptEncoding; {do not localize}
|
|
end;
|
|
if Length(FAcceptLanguage) > 0 then
|
|
begin
|
|
FRawHeaders.Values['Accept-Language'] := FAcceptLanguage; {do not localize}
|
|
end;
|
|
if Length(FFrom) > 0 then
|
|
begin
|
|
FRawHeaders.Values['From'] := FFrom; {do not localize}
|
|
end;
|
|
if Length(FReferer) > 0 then
|
|
begin
|
|
FRawHeaders.Values['Referer'] := FReferer; {do not localize}
|
|
end;
|
|
if Length(FUserAgent) > 0 then
|
|
begin
|
|
FRawHeaders.Values['User-Agent'] := FUserAgent; {do not localize}
|
|
end;
|
|
S := FRanges.Text;
|
|
if Length(S) > 0 then
|
|
begin
|
|
FRawHeaders.Values['Range'] := S; {do not localize}
|
|
end;
|
|
|
|
// use 'Last-Modified' entity header in the conditional request
|
|
if FLastModified > 0 then
|
|
begin
|
|
FRawHeaders.Values['If-Modified-Since'] := LocalDateTimeToHttpStr(FLastModified); {do not localize}
|
|
end;
|
|
|
|
if Assigned(Authentication) then
|
|
begin
|
|
S := Authentication.Authentication;
|
|
end
|
|
else if FBasicByDefault then begin
|
|
FAuthentication := TIdBasicAuthentication.Create;
|
|
// TODO: use FAuthentication Username/Password properties instead
|
|
FAuthentication.Params.Values['Username'] := FUserName; {do not localize}
|
|
FAuthentication.Params.Values['Password'] := FPassword; {do not localize}
|
|
S := FAuthentication.Authentication;
|
|
end else begin
|
|
S := '';
|
|
end;
|
|
if Length(S) > 0 then
|
|
begin
|
|
FRawHeaders.Values['Authorization'] := S; {do not localize}
|
|
end;
|
|
|
|
if Length(FMethodOverride) > 0 then
|
|
begin
|
|
FRawHeaders.Values['X-HTTP-Method-Override'] := FMethodOverride; {Do not Localize}
|
|
end;
|
|
end;
|
|
|
|
{ TIdResponseHeaderInfo }
|
|
|
|
constructor TIdResponseHeaderInfo.Create(AOwner: TPersistent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
// RLebeau 5/15/2012: don't set any default ContentType, make the user set it...
|
|
FContentType := '';
|
|
FCharSet := '';
|
|
FWWWAuthenticate := TIdHeaderList.Create(QuoteHTTP);
|
|
FProxyAuthenticate := TIdHeaderList.Create(QuoteHTTP);
|
|
FAcceptPatch := '';
|
|
FAcceptRanges := '';
|
|
end;
|
|
|
|
destructor TIdResponseHeaderInfo.Destroy;
|
|
begin
|
|
FreeAndNil(FWWWAuthenticate);
|
|
FreeAndNil(FProxyAuthenticate);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TIdResponseHeaderInfo.SetProxyAuthenticate(const Value: TIdHeaderList);
|
|
begin
|
|
FProxyAuthenticate.Assign(Value);
|
|
end;
|
|
|
|
procedure TIdResponseHeaderInfo.SetWWWAuthenticate(const Value: TIdHeaderList);
|
|
begin
|
|
FWWWAuthenticate.Assign(Value);
|
|
end;
|
|
|
|
procedure TIdResponseHeaderInfo.ProcessHeaders;
|
|
begin
|
|
inherited ProcessHeaders;
|
|
FLocation := FRawHeaders.Values['Location']; {do not localize}
|
|
FServer := FRawHeaders.Values['Server']; {do not localize}
|
|
FProxyConnection := FRawHeaders.Values['Proxy-Connection']; {do not localize}
|
|
|
|
FWWWAuthenticate.Clear;
|
|
FRawHeaders.Extract('WWW-Authenticate', FWWWAuthenticate); {do not localize}
|
|
|
|
FProxyAuthenticate.Clear;
|
|
FRawHeaders.Extract('Proxy-Authenticate', FProxyAuthenticate);{do not localize}
|
|
|
|
FAcceptPatch := FRawHeaders.Values['Accept-Patch']; {do not localize}
|
|
FAcceptRanges := FRawHeaders.Values['Accept-Ranges']; {do not localize}
|
|
end;
|
|
|
|
procedure TIdResponseHeaderInfo.SetHeaders;
|
|
var
|
|
sUnits: String;
|
|
sCR: String;
|
|
sCI: String;
|
|
begin
|
|
inherited SetHeaders;
|
|
|
|
{
|
|
setting the content-range header is allowed in server responses...
|
|
moved here TIdEntityHeaderInfo
|
|
}
|
|
if HasContentRange or HasContentRangeInstance then
|
|
begin
|
|
sUnits := iif(FContentRangeUnits <> '',
|
|
FContentRangeUnits, 'bytes'); {do not localize}
|
|
sCR := iif(HasContentRange,
|
|
IndyFormat('%d-%d', [FContentRangeStart, FContentRangeEnd]), '*'); {do not localize}
|
|
sCI := iif(HasContentRangeInstance,
|
|
IndyFormat('%d', [FContentRangeInstanceLength]), '*'); {do not localize}
|
|
|
|
RawHeaders.Values['Content-Range'] := sUnits + ' ' + sCR + '/' + sCI; {do not localize}
|
|
end;
|
|
if Length(FAcceptPatch) > 0 then
|
|
begin
|
|
RawHeaders.Values['Accept-Patch'] := FAcceptPatch; {do not localize}
|
|
end;
|
|
if Length(FAcceptRanges) > 0 then
|
|
begin
|
|
RawHeaders.Values['Accept-Ranges'] := FAcceptRanges; {do not localize}
|
|
end;
|
|
if FLastModified > 0 then
|
|
begin
|
|
RawHeaders.Values['Last-Modified'] := DateTimeGMTToHttpStr(FLastModified); {do not localize}
|
|
end;
|
|
end;
|
|
|
|
procedure TIdResponseHeaderInfo.Clear;
|
|
begin
|
|
inherited Clear;
|
|
|
|
// RLebeau 5/15/2012: don't set any default ContentType, make the user set it...
|
|
FContentType := '';
|
|
FCharSet := '';
|
|
|
|
FLocation := '';
|
|
FServer := '';
|
|
FAcceptPatch := '';
|
|
FAcceptRanges := '';
|
|
|
|
if Assigned(FProxyAuthenticate) then
|
|
begin
|
|
FProxyAuthenticate.Clear;
|
|
end;
|
|
|
|
if Assigned(FWWWAuthenticate) then
|
|
begin
|
|
FWWWAuthenticate.Clear;
|
|
end;
|
|
end;
|
|
|
|
procedure TIdResponseHeaderInfo.SetAcceptPatch(const Value: string);
|
|
begin
|
|
FAcceptPatch := Value;
|
|
end;
|
|
|
|
procedure TIdResponseHeaderInfo.SetAcceptRanges(const Value: string);
|
|
begin
|
|
FAcceptRanges := Value;
|
|
end;
|
|
|
|
{ TIdMetaHTTPEquiv }
|
|
|
|
procedure TIdMetaHTTPEquiv.ProcessMetaHTTPEquiv(AStream: TStream);
|
|
var
|
|
LCharSet: string;
|
|
begin
|
|
ParseMetaHTTPEquiv(AStream, RawHeaders, LCharSet);
|
|
if FRawHeaders.Count > 0 then begin
|
|
ProcessHeaders;
|
|
end;
|
|
if LCharSet <> '' then begin
|
|
FCharSet := LCharset;
|
|
end;
|
|
end;
|
|
|
|
end.
|