|
@@ -15,7 +15,7 @@
|
|
|
You should have received a Copy of the GNU Library General Public License
|
|
You should have received a Copy of the GNU Library General Public License
|
|
|
along with This library; if not, Write to the Free Software Foundation,
|
|
along with This library; if not, Write to the Free Software Foundation,
|
|
|
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
This license has been modified. See file LICENSE.ADDON for more information.
|
|
This license has been modified. See file LICENSE.ADDON for more information.
|
|
|
Should you find these sources without a LICENSE File, please contact
|
|
Should you find these sources without a LICENSE File, please contact
|
|
|
me at [email protected]
|
|
me at [email protected]
|
|
@@ -38,7 +38,7 @@ type
|
|
|
hpAccept, hpAcceptCharset, hpAcceptEncoding, hpAcceptLanguage, hpHost,
|
|
hpAccept, hpAcceptCharset, hpAcceptEncoding, hpAcceptLanguage, hpHost,
|
|
|
hpFrom, hpReferer, hpUserAgent, hpRange, hpTransferEncoding,
|
|
hpFrom, hpReferer, hpUserAgent, hpRange, hpTransferEncoding,
|
|
|
hpIfModifiedSince, hpIfUnmodifiedSince, hpCookie);
|
|
hpIfModifiedSince, hpIfUnmodifiedSince, hpCookie);
|
|
|
- TLHTTPStatus = (hsUnknown, hsOK, hsNoContent, hsMovedPermanently, hsFound, hsNotModified,
|
|
|
|
|
|
|
+ TLHTTPStatus = (hsUnknown, hsOK, hsNoContent, hsMovedPermanently, hsFound, hsNotModified,
|
|
|
hsBadRequest, hsForbidden, hsNotFound, hsPreconditionFailed, hsRequestTooLong,
|
|
hsBadRequest, hsForbidden, hsNotFound, hsPreconditionFailed, hsRequestTooLong,
|
|
|
hsInternalError, hsNotImplemented, hsNotAllowed);
|
|
hsInternalError, hsNotImplemented, hsNotAllowed);
|
|
|
TLHTTPTransferEncoding = (teIdentity, teChunked);
|
|
TLHTTPTransferEncoding = (teIdentity, teChunked);
|
|
@@ -46,19 +46,19 @@ type
|
|
|
ceUnsupportedEncoding);
|
|
ceUnsupportedEncoding);
|
|
|
|
|
|
|
|
const
|
|
const
|
|
|
- HTTPDisconnectStatuses = [hsBadRequest, hsRequestTooLong, hsForbidden,
|
|
|
|
|
|
|
+ HTTPDisconnectStatuses = [hsBadRequest, hsRequestTooLong, hsForbidden,
|
|
|
hsInternalError, hsNotAllowed];
|
|
hsInternalError, hsNotAllowed];
|
|
|
HTTPMethodStrings: array[TLHTTPMethod] of string =
|
|
HTTPMethodStrings: array[TLHTTPMethod] of string =
|
|
|
('HEAD', 'GET', 'POST', '');
|
|
('HEAD', 'GET', 'POST', '');
|
|
|
HTTPParameterStrings: array[TLHTTPParameter] of string =
|
|
HTTPParameterStrings: array[TLHTTPParameter] of string =
|
|
|
- ('CONNECTION', 'CONTENT-LENGTH', 'CONTENT-TYPE', 'ACCEPT',
|
|
|
|
|
|
|
+ ('CONNECTION', 'CONTENT-LENGTH', 'CONTENT-TYPE', 'ACCEPT',
|
|
|
'ACCEPT-CHARSET', 'ACCEPT-ENCODING', 'ACCEPT-LANGUAGE', 'HOST',
|
|
'ACCEPT-CHARSET', 'ACCEPT-ENCODING', 'ACCEPT-LANGUAGE', 'HOST',
|
|
|
'FROM', 'REFERER', 'USER-AGENT', 'RANGE', 'TRANSFER-ENCODING',
|
|
'FROM', 'REFERER', 'USER-AGENT', 'RANGE', 'TRANSFER-ENCODING',
|
|
|
'IF-MODIFIED-SINCE', 'IF-UNMODIFIED-SINCE', 'COOKIE');
|
|
'IF-MODIFIED-SINCE', 'IF-UNMODIFIED-SINCE', 'COOKIE');
|
|
|
HTTPStatusCodes: array[TLHTTPStatus] of dword =
|
|
HTTPStatusCodes: array[TLHTTPStatus] of dword =
|
|
|
(0, 200, 204, 301, 302, 304, 400, 403, 404, 412, 414, 500, 501, 504);
|
|
(0, 200, 204, 301, 302, 304, 400, 403, 404, 412, 414, 500, 501, 504);
|
|
|
- HTTPTexts: array[TLHTTPStatus] of string =
|
|
|
|
|
- ('', 'OK', 'No Content', 'Moved Permanently', 'Found', 'Not Modified', 'Bad Request', 'Forbidden',
|
|
|
|
|
|
|
+ HTTPTexts: array[TLHTTPStatus] of string =
|
|
|
|
|
+ ('', 'OK', 'No Content', 'Moved Permanently', 'Found', 'Not Modified', 'Bad Request', 'Forbidden',
|
|
|
'Not Found', 'Precondition Failed', 'Request Too Long', 'Internal Error',
|
|
'Not Found', 'Precondition Failed', 'Request Too Long', 'Internal Error',
|
|
|
'Method Not Implemented', 'Method Not Allowed');
|
|
'Method Not Implemented', 'Method Not Allowed');
|
|
|
HTTPDescriptions: array[TLHTTPStatus] of string = (
|
|
HTTPDescriptions: array[TLHTTPStatus] of string = (
|
|
@@ -120,7 +120,7 @@ type
|
|
|
TLHTTPSocket = class;
|
|
TLHTTPSocket = class;
|
|
|
TLHTTPConnection = class;
|
|
TLHTTPConnection = class;
|
|
|
TLHTTPClientSocket = class;
|
|
TLHTTPClientSocket = class;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
PRequestInfo = ^TRequestInfo;
|
|
PRequestInfo = ^TRequestInfo;
|
|
|
TRequestInfo = record
|
|
TRequestInfo = record
|
|
|
RequestType: TLHTTPMethod;
|
|
RequestType: TLHTTPMethod;
|
|
@@ -229,7 +229,7 @@ type
|
|
|
protected
|
|
protected
|
|
|
FFreeBuffer: boolean;
|
|
FFreeBuffer: boolean;
|
|
|
public
|
|
public
|
|
|
- constructor Create(ASocket: TLHTTPSocket; ABuffer: pointer;
|
|
|
|
|
|
|
+ constructor Create(ASocket: TLHTTPSocket; ABuffer: pointer;
|
|
|
ABufferOffset, ABufferSize: integer; AFreeBuffer: boolean);
|
|
ABufferOffset, ABufferSize: integer; AFreeBuffer: boolean);
|
|
|
destructor Destroy; override;
|
|
destructor Destroy; override;
|
|
|
end;
|
|
end;
|
|
@@ -245,7 +245,7 @@ type
|
|
|
constructor Create(ASocket: TLHTTPSocket; AStream: TStream; AFreeStream: boolean);
|
|
constructor Create(ASocket: TLHTTPSocket; AStream: TStream; AFreeStream: boolean);
|
|
|
destructor Destroy; override;
|
|
destructor Destroy; override;
|
|
|
end;
|
|
end;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
TMemoryStreamOutput = class(TOutputItem)
|
|
TMemoryStreamOutput = class(TOutputItem)
|
|
|
protected
|
|
protected
|
|
|
FFreeStream: boolean;
|
|
FFreeStream: boolean;
|
|
@@ -259,7 +259,7 @@ type
|
|
|
|
|
|
|
|
TChunkState = (csInitial, csData, csDataEnd, csTrailer, csFinished);
|
|
TChunkState = (csInitial, csData, csDataEnd, csTrailer, csFinished);
|
|
|
TLHTTPParameterArray = array[TLHTTPParameter] of PAnsiChar;
|
|
TLHTTPParameterArray = array[TLHTTPParameter] of PAnsiChar;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
TParseBufferMethod = function: boolean of object;
|
|
TParseBufferMethod = function: boolean of object;
|
|
|
TLInputEvent = function(ASocket: TLHTTPClientSocket; ABuffer: PAnsiChar; ASize: integer): integer of object;
|
|
TLInputEvent = function(ASocket: TLHTTPClientSocket; ABuffer: PAnsiChar; ASize: integer): integer of object;
|
|
|
TLCanWriteEvent = procedure(ASocket: TLHTTPClientSocket; var OutputEof: TWriteBlockStatus) of object;
|
|
TLCanWriteEvent = procedure(ASocket: TLHTTPClientSocket; var OutputEof: TWriteBlockStatus) of object;
|
|
@@ -328,14 +328,14 @@ type
|
|
|
procedure HandleReceive;
|
|
procedure HandleReceive;
|
|
|
function ParseBuffer: boolean;
|
|
function ParseBuffer: boolean;
|
|
|
procedure WriteBlock;
|
|
procedure WriteBlock;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
property Parameters: TLHTTPParameterArray read FParameters;
|
|
property Parameters: TLHTTPParameterArray read FParameters;
|
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
{ http server }
|
|
{ http server }
|
|
|
|
|
|
|
|
TSetupEncodingState = (seNone, seWaitHeaders, seStartHeaders);
|
|
TSetupEncodingState = (seNone, seWaitHeaders, seStartHeaders);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
TLHTTPServerSocket = class(TLHTTPSocket)
|
|
TLHTTPServerSocket = class(TLHTTPSocket)
|
|
|
protected
|
|
protected
|
|
|
FLogMessage: TStringBuffer;
|
|
FLogMessage: TStringBuffer;
|
|
@@ -367,7 +367,7 @@ type
|
|
|
procedure StartMemoryResponse(AOutputItem: TMemoryOutput; ACustomErrorMessage: boolean = false);
|
|
procedure StartMemoryResponse(AOutputItem: TMemoryOutput; ACustomErrorMessage: boolean = false);
|
|
|
procedure StartResponse(AOutputItem: TBufferOutput; ACustomErrorMessage: boolean = false);
|
|
procedure StartResponse(AOutputItem: TBufferOutput; ACustomErrorMessage: boolean = false);
|
|
|
end;
|
|
end;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
TURIHandler = class(TObject)
|
|
TURIHandler = class(TObject)
|
|
|
private
|
|
private
|
|
|
FNext: TURIHandler;
|
|
FNext: TURIHandler;
|
|
@@ -411,7 +411,7 @@ type
|
|
|
FResponse: PClientResponse;
|
|
FResponse: PClientResponse;
|
|
|
FHeaderOut: PHeaderOutInfo;
|
|
FHeaderOut: PHeaderOutInfo;
|
|
|
FError: TLHTTPClientError;
|
|
FError: TLHTTPClientError;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
procedure AddContentLength(ALength: integer); override;
|
|
procedure AddContentLength(ALength: integer); override;
|
|
|
function GetResponseReason: string;
|
|
function GetResponseReason: string;
|
|
|
function GetResponseStatus: TLHTTPStatus;
|
|
function GetResponseStatus: TLHTTPStatus;
|
|
@@ -446,7 +446,7 @@ type
|
|
|
FOnDoneInput: TLHTTPClientEvent;
|
|
FOnDoneInput: TLHTTPClientEvent;
|
|
|
FOnInput: TLInputEvent;
|
|
FOnInput: TLInputEvent;
|
|
|
FOnProcessHeaders: TLHTTPClientEvent;
|
|
FOnProcessHeaders: TLHTTPClientEvent;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
procedure ConnectEvent(aSocket: TLHandle); override;
|
|
procedure ConnectEvent(aSocket: TLHandle); override;
|
|
|
procedure DoDoneInput(ASocket: TLHTTPClientSocket);
|
|
procedure DoDoneInput(ASocket: TLHTTPClientSocket);
|
|
|
function DoHandleInput(ASocket: TLHTTPClientSocket; ABuffer: PAnsiChar; ASize: integer): integer;
|
|
function DoHandleInput(ASocket: TLHTTPClientSocket; ABuffer: PAnsiChar; ASize: integer): integer;
|
|
@@ -506,9 +506,9 @@ function HTTPVersionCheck(AStr, AStrEnd: PAnsiChar; out AVersion: dword): boolea
|
|
|
var
|
|
var
|
|
|
lMajorVersion, lMinorVersion: byte;
|
|
lMajorVersion, lMinorVersion: byte;
|
|
|
begin
|
|
begin
|
|
|
- Result := ((AStrEnd-AStr) = 8)
|
|
|
|
|
|
|
+ Result := ((AStrEnd-AStr) = 8)
|
|
|
and CompareMem(AStr, PAnsiChar('HTTP/'), 5)
|
|
and CompareMem(AStr, PAnsiChar('HTTP/'), 5)
|
|
|
- and TrySingleDigit(AStr[5], lMajorVersion)
|
|
|
|
|
|
|
+ and TrySingleDigit(AStr[5], lMajorVersion)
|
|
|
and (AStr[6] = '.')
|
|
and (AStr[6] = '.')
|
|
|
and TrySingleDigit(AStr[7], lMinorVersion);
|
|
and TrySingleDigit(AStr[7], lMinorVersion);
|
|
|
AVersion := lMajorVersion * 10 + lMinorVersion;
|
|
AVersion := lMajorVersion * 10 + lMinorVersion;
|
|
@@ -589,7 +589,7 @@ destructor TOutputItem.Destroy;
|
|
|
begin
|
|
begin
|
|
|
if FSocket.FCurrentInput = Self then
|
|
if FSocket.FCurrentInput = Self then
|
|
|
FSocket.FCurrentInput := nil;
|
|
FSocket.FCurrentInput := nil;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
if FPrevDelayFree = nil then
|
|
if FPrevDelayFree = nil then
|
|
|
FSocket.FDelayFreeItems := FNextDelayFree
|
|
FSocket.FDelayFreeItems := FNextDelayFree
|
|
|
else
|
|
else
|
|
@@ -681,7 +681,7 @@ begin
|
|
|
FSocket.PrependOutput(TStreamOutput.Create(FSocket, AStream, AFree), Self);
|
|
FSocket.PrependOutput(TStreamOutput.Create(FSocket, AStream, AFree), Self);
|
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
-procedure TBufferOutput.Add(AStream: TStream; AQueue: boolean = false;
|
|
|
|
|
|
|
+procedure TBufferOutput.Add(AStream: TStream; AQueue: boolean = false;
|
|
|
AFree: boolean = true);
|
|
AFree: boolean = true);
|
|
|
var
|
|
var
|
|
|
size, copySize: integer;
|
|
size, copySize: integer;
|
|
@@ -778,7 +778,7 @@ begin
|
|
|
FBuffer[FBufferSize+4] := #10;
|
|
FBuffer[FBufferSize+4] := #10;
|
|
|
inc(FBufferSize, 5);
|
|
inc(FBufferSize, 5);
|
|
|
end;
|
|
end;
|
|
|
- end else
|
|
|
|
|
|
|
+ end else
|
|
|
Result := EofToWriteStatus[FEof];
|
|
Result := EofToWriteStatus[FEof];
|
|
|
if FOutputPending then
|
|
if FOutputPending then
|
|
|
begin
|
|
begin
|
|
@@ -790,7 +790,7 @@ begin
|
|
|
end;
|
|
end;
|
|
|
end;
|
|
end;
|
|
|
end;
|
|
end;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
function TBufferOutput.WriteBuffer: TWriteBlockStatus;
|
|
function TBufferOutput.WriteBuffer: TWriteBlockStatus;
|
|
|
begin
|
|
begin
|
|
|
if not FOutputPending then
|
|
if not FOutputPending then
|
|
@@ -859,7 +859,7 @@ begin
|
|
|
FFinishBuffer := @FinishChunk;
|
|
FFinishBuffer := @FinishChunk;
|
|
|
PrepareChunk;
|
|
PrepareChunk;
|
|
|
end;
|
|
end;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
procedure TBufferOutput.SelectBuffered;
|
|
procedure TBufferOutput.SelectBuffered;
|
|
|
begin
|
|
begin
|
|
|
FPrepareBuffer := @PrepareBuffer;
|
|
FPrepareBuffer := @PrepareBuffer;
|
|
@@ -867,7 +867,7 @@ begin
|
|
|
FFinishBuffer := @FinishBuffer;
|
|
FFinishBuffer := @FinishBuffer;
|
|
|
PrepareBuffer;
|
|
PrepareBuffer;
|
|
|
end;
|
|
end;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
procedure TBufferOutput.SelectPlain;
|
|
procedure TBufferOutput.SelectPlain;
|
|
|
begin
|
|
begin
|
|
|
FPrepareBuffer := @PrepareBuffer;
|
|
FPrepareBuffer := @PrepareBuffer;
|
|
@@ -878,7 +878,7 @@ end;
|
|
|
|
|
|
|
|
{ TMemoryOutput }
|
|
{ TMemoryOutput }
|
|
|
|
|
|
|
|
-constructor TMemoryOutput.Create(ASocket: TLHTTPSocket; ABuffer: pointer;
|
|
|
|
|
|
|
+constructor TMemoryOutput.Create(ASocket: TLHTTPSocket; ABuffer: pointer;
|
|
|
ABufferOffset, ABufferSize: integer; AFreeBuffer: boolean);
|
|
ABufferOffset, ABufferSize: integer; AFreeBuffer: boolean);
|
|
|
begin
|
|
begin
|
|
|
inherited Create(ASocket);
|
|
inherited Create(ASocket);
|
|
@@ -925,7 +925,7 @@ end;
|
|
|
|
|
|
|
|
{ TMemoryStreamOutput }
|
|
{ TMemoryStreamOutput }
|
|
|
|
|
|
|
|
-constructor TMemoryStreamOutput.Create(ASocket: TLHTTPSocket; AStream: TMemoryStream;
|
|
|
|
|
|
|
+constructor TMemoryStreamOutput.Create(ASocket: TLHTTPSocket; AStream: TMemoryStream;
|
|
|
AFreeStream: boolean);
|
|
AFreeStream: boolean);
|
|
|
begin
|
|
begin
|
|
|
inherited Create(ASocket);
|
|
inherited Create(ASocket);
|
|
@@ -1087,7 +1087,7 @@ procedure TLHTTPSocket.HandleReceive;
|
|
|
var
|
|
var
|
|
|
lRead: integer;
|
|
lRead: integer;
|
|
|
begin
|
|
begin
|
|
|
- if FRequestInputDone then
|
|
|
|
|
|
|
+ if FRequestInputDone then
|
|
|
begin
|
|
begin
|
|
|
IgnoreRead := true;
|
|
IgnoreRead := true;
|
|
|
exit;
|
|
exit;
|
|
@@ -1196,19 +1196,19 @@ begin
|
|
|
if FChunkState = csFinished then
|
|
if FChunkState = csFinished then
|
|
|
exit(false);
|
|
exit(false);
|
|
|
if FChunkState = csData then
|
|
if FChunkState = csData then
|
|
|
- if ParseEntityPlain then
|
|
|
|
|
|
|
+ if ParseEntityPlain then
|
|
|
exit(true)
|
|
exit(true)
|
|
|
else
|
|
else
|
|
|
FChunkState := csDataEnd;
|
|
FChunkState := csDataEnd;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
lLineEnd := StrScan(FBufferPos, #10);
|
|
lLineEnd := StrScan(FBufferPos, #10);
|
|
|
if lLineEnd = nil then
|
|
if lLineEnd = nil then
|
|
|
exit(true);
|
|
exit(true);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
lNextLine := lLineEnd+1;
|
|
lNextLine := lLineEnd+1;
|
|
|
if (lLineEnd > FBufferPos) and ((lLineEnd-1)^ = #13) then
|
|
if (lLineEnd > FBufferPos) and ((lLineEnd-1)^ = #13) then
|
|
|
dec(lLineEnd);
|
|
dec(lLineEnd);
|
|
|
- case FChunkState of
|
|
|
|
|
|
|
+ case FChunkState of
|
|
|
csInitial:
|
|
csInitial:
|
|
|
begin
|
|
begin
|
|
|
lLineEnd^ := #0;
|
|
lLineEnd^ := #0;
|
|
@@ -1257,7 +1257,7 @@ begin
|
|
|
WriteError(hsRequestTooLong);
|
|
WriteError(hsRequestTooLong);
|
|
|
exit(true);
|
|
exit(true);
|
|
|
end;
|
|
end;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
pNextLine := pLineEnd+1;
|
|
pNextLine := pLineEnd+1;
|
|
|
if (pLineEnd > FBufferPos) and ((pLineEnd-1)^ = #13) then
|
|
if (pLineEnd > FBufferPos) and ((pLineEnd-1)^ = #13) then
|
|
|
dec(pLineEnd);
|
|
dec(pLineEnd);
|
|
@@ -1307,7 +1307,7 @@ begin
|
|
|
end else
|
|
end else
|
|
|
ParseParameterLine(pLineEnd);
|
|
ParseParameterLine(pLineEnd);
|
|
|
end;
|
|
end;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
function TLHTTPSocket.ParseBuffer: boolean;
|
|
function TLHTTPSocket.ParseBuffer: boolean;
|
|
|
var
|
|
var
|
|
|
lParseFunc: TParseBufferMethod;
|
|
lParseFunc: TParseBufferMethod;
|
|
@@ -1321,7 +1321,7 @@ begin
|
|
|
if FCurrentInput <> nil then
|
|
if FCurrentInput <> nil then
|
|
|
FCurrentInput.DoneInput;
|
|
FCurrentInput.DoneInput;
|
|
|
end;
|
|
end;
|
|
|
- { if parse func changed mid-run, then we should continue calling the new
|
|
|
|
|
|
|
+ { if parse func changed mid-run, then we should continue calling the new
|
|
|
one: header + data }
|
|
one: header + data }
|
|
|
until (lParseFunc = FParseBuffer) or not Result;
|
|
until (lParseFunc = FParseBuffer) or not Result;
|
|
|
end;
|
|
end;
|
|
@@ -1354,7 +1354,7 @@ begin
|
|
|
exit;
|
|
exit;
|
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
- { only if keep-alive, then user must specify either of above headers to
|
|
|
|
|
|
|
+ { only if keep-alive, then user must specify either of above headers to
|
|
|
indicate next header's start }
|
|
indicate next header's start }
|
|
|
lParam := FParameters[hpConnection];
|
|
lParam := FParameters[hpConnection];
|
|
|
FRequestInputDone := (lParam <> nil) and (StrIComp(lParam, 'keep-alive') = 0);
|
|
FRequestInputDone := (lParam <> nil) and (StrIComp(lParam, 'keep-alive') = 0);
|
|
@@ -1414,13 +1414,13 @@ begin
|
|
|
if FBufferPos = FBufferEnd then
|
|
if FBufferPos = FBufferEnd then
|
|
|
PackRequestBuffer;
|
|
PackRequestBuffer;
|
|
|
|
|
|
|
|
- if ParseBuffer and IgnoreRead then
|
|
|
|
|
|
|
+ if ParseBuffer and IgnoreRead then
|
|
|
begin
|
|
begin
|
|
|
{ end of input buffer reached, try reading more }
|
|
{ end of input buffer reached, try reading more }
|
|
|
HandleReceive;
|
|
HandleReceive;
|
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
- if FCurrentOutput = nil then
|
|
|
|
|
|
|
+ if FCurrentOutput = nil then
|
|
|
break;
|
|
break;
|
|
|
end;
|
|
end;
|
|
|
|
|
|
|
@@ -1495,7 +1495,7 @@ procedure TLHTTPServerSocket.LogMessage;
|
|
|
|
|
|
|
|
|
|
|
|
|
begin
|
|
begin
|
|
|
- { log a message about this request,
|
|
|
|
|
|
|
+ { log a message about this request,
|
|
|
'<StatusCode> <Length> "<Referer>" "<User-Agent>"' }
|
|
'<StatusCode> <Length> "<Referer>" "<User-Agent>"' }
|
|
|
AppendString(FLogMessage, IntToStr(HTTPStatusCodes[FResponseInfo.Status]));
|
|
AppendString(FLogMessage, IntToStr(HTTPStatusCodes[FResponseInfo.Status]));
|
|
|
AppendChar(FLogMessage, ' ');
|
|
AppendChar(FLogMessage, ' ');
|
|
@@ -1542,7 +1542,7 @@ begin
|
|
|
end;
|
|
end;
|
|
|
inherited;
|
|
inherited;
|
|
|
end;
|
|
end;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
procedure TLHTTPServerSocket.RelocateVariables;
|
|
procedure TLHTTPServerSocket.RelocateVariables;
|
|
|
begin
|
|
begin
|
|
|
RelocateVariable(FRequestInfo.Method);
|
|
RelocateVariable(FRequestInfo.Method);
|
|
@@ -1603,7 +1603,7 @@ begin
|
|
|
end;
|
|
end;
|
|
|
FRequestInfo.VersionStr := lPos;
|
|
FRequestInfo.VersionStr := lPos;
|
|
|
FHeaderOut.Version := FRequestInfo.Version;
|
|
FHeaderOut.Version := FRequestInfo.Version;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
{ trim spaces at end of URI }
|
|
{ trim spaces at end of URI }
|
|
|
dec(lPos);
|
|
dec(lPos);
|
|
|
repeat
|
|
repeat
|
|
@@ -1641,7 +1641,7 @@ begin
|
|
|
begin
|
|
begin
|
|
|
{ absolute URI }
|
|
{ absolute URI }
|
|
|
lPos := FRequestInfo.Argument+7;
|
|
lPos := FRequestInfo.Argument+7;
|
|
|
- while (lPos^ = '/') do
|
|
|
|
|
|
|
+ while (lPos^ = '/') do
|
|
|
Inc(lPos);
|
|
Inc(lPos);
|
|
|
FParameters[hpHost] := lPos;
|
|
FParameters[hpHost] := lPos;
|
|
|
lPos := StrScan(lPos, '/');
|
|
lPos := StrScan(lPos, '/');
|
|
@@ -1669,7 +1669,7 @@ begin
|
|
|
WriteError(hsBadRequest);
|
|
WriteError(hsBadRequest);
|
|
|
exit;
|
|
exit;
|
|
|
end;
|
|
end;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
lPos := StrScan(FRequestInfo.Argument, '?');
|
|
lPos := StrScan(FRequestInfo.Argument, '?');
|
|
|
if lPos <> nil then
|
|
if lPos <> nil then
|
|
|
begin
|
|
begin
|
|
@@ -1687,7 +1687,7 @@ begin
|
|
|
if StrIComp(lConnParam, 'close') = 0 then
|
|
if StrIComp(lConnParam, 'close') = 0 then
|
|
|
FKeepAlive := false;
|
|
FKeepAlive := false;
|
|
|
end;
|
|
end;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
HTTPDecode(FRequestInfo.Argument);
|
|
HTTPDecode(FRequestInfo.Argument);
|
|
|
if not CheckPermission(FRequestInfo.Argument) then
|
|
if not CheckPermission(FRequestInfo.Argument) then
|
|
|
begin
|
|
begin
|
|
@@ -1698,9 +1698,9 @@ begin
|
|
|
WriteError(hsNotImplemented);
|
|
WriteError(hsNotImplemented);
|
|
|
exit;
|
|
exit;
|
|
|
end;
|
|
end;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
FCurrentInput := HandleURI;
|
|
FCurrentInput := HandleURI;
|
|
|
- { if we have a valid outputitem, wait until it is ready
|
|
|
|
|
|
|
+ { if we have a valid outputitem, wait until it is ready
|
|
|
to produce its response }
|
|
to produce its response }
|
|
|
if FCurrentInput = nil then
|
|
if FCurrentInput = nil then
|
|
|
begin
|
|
begin
|
|
@@ -1720,7 +1720,7 @@ begin
|
|
|
{ check modification date }
|
|
{ check modification date }
|
|
|
if FResponseInfo.Status < hsBadRequest then
|
|
if FResponseInfo.Status < hsBadRequest then
|
|
|
begin
|
|
begin
|
|
|
- if (FParameters[hpIfModifiedSince] <> nil)
|
|
|
|
|
|
|
+ if (FParameters[hpIfModifiedSince] <> nil)
|
|
|
and (FResponseInfo.LastModified <> 0.0) then
|
|
and (FResponseInfo.LastModified <> 0.0) then
|
|
|
begin
|
|
begin
|
|
|
if TryHTTPDateStrToDateTime(FParameters[hpIfModifiedSince], lDateTime) then
|
|
if TryHTTPDateStrToDateTime(FParameters[hpIfModifiedSince], lDateTime) then
|
|
@@ -1736,7 +1736,7 @@ begin
|
|
|
begin
|
|
begin
|
|
|
if TryHTTPDateStrToDateTime(FParameters[hpIfUnmodifiedSince], lDateTime) then
|
|
if TryHTTPDateStrToDateTime(FParameters[hpIfUnmodifiedSince], lDateTime) then
|
|
|
begin
|
|
begin
|
|
|
- if (FResponseInfo.LastModified = 0.0)
|
|
|
|
|
|
|
+ if (FResponseInfo.LastModified = 0.0)
|
|
|
or (lDateTime < FResponseInfo.LastModified) then
|
|
or (lDateTime < FResponseInfo.LastModified) then
|
|
|
FResponseInfo.Status := hsPreconditionFailed;
|
|
FResponseInfo.Status := hsPreconditionFailed;
|
|
|
end;
|
|
end;
|
|
@@ -1749,7 +1749,7 @@ begin
|
|
|
ACustomErrorMessage := false;
|
|
ACustomErrorMessage := false;
|
|
|
FHeaderOut.ContentLength := 0;
|
|
FHeaderOut.ContentLength := 0;
|
|
|
end;
|
|
end;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
Result := (FResponseInfo.Status = hsOK) or ACustomErrorMessage;
|
|
Result := (FResponseInfo.Status = hsOK) or ACustomErrorMessage;
|
|
|
if not Result then
|
|
if not Result then
|
|
|
begin
|
|
begin
|
|
@@ -1822,7 +1822,7 @@ var
|
|
|
tempStr: string;
|
|
tempStr: string;
|
|
|
begin
|
|
begin
|
|
|
lMessage := InitStringBuffer(504);
|
|
lMessage := InitStringBuffer(504);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
AppendString(lMessage, 'HTTP/1.1 ');
|
|
AppendString(lMessage, 'HTTP/1.1 ');
|
|
|
Str(HTTPStatusCodes[FResponseInfo.Status], lTemp);
|
|
Str(HTTPStatusCodes[FResponseInfo.Status], lTemp);
|
|
|
AppendString(lMessage, lTemp);
|
|
AppendString(lMessage, lTemp);
|
|
@@ -1927,7 +1927,7 @@ begin
|
|
|
else
|
|
else
|
|
|
TZSign := '-';
|
|
TZSign := '-';
|
|
|
TZSecsAbs := Abs(TZSeconds);
|
|
TZSecsAbs := Abs(TZSeconds);
|
|
|
- FLogMessageTZString := Format(' %s%.2d%.2d] "',
|
|
|
|
|
|
|
+ FLogMessageTZString := Format(' %s%.2d%.2d] "',
|
|
|
[TZSign, TZSecsAbs div 3600, (TZSecsAbs div 60) mod 60]);
|
|
[TZSign, TZSecsAbs div 3600, (TZSecsAbs div 60) mod 60]);
|
|
|
end;
|
|
end;
|
|
|
|
|
|
|
@@ -1983,7 +1983,7 @@ type
|
|
|
TClientOutput = class(TOutputItem)
|
|
TClientOutput = class(TOutputItem)
|
|
|
protected
|
|
protected
|
|
|
FPersistent: boolean;
|
|
FPersistent: boolean;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
procedure DoneInput; override;
|
|
procedure DoneInput; override;
|
|
|
public
|
|
public
|
|
|
constructor Create(ASocket: TLHTTPClientSocket);
|
|
constructor Create(ASocket: TLHTTPClientSocket);
|
|
@@ -2002,13 +2002,13 @@ end;
|
|
|
|
|
|
|
|
destructor TClientOutput.Destroy;
|
|
destructor TClientOutput.Destroy;
|
|
|
begin
|
|
begin
|
|
|
- if FPersistent then exit;
|
|
|
|
|
|
|
+ if FPersistent then exit;
|
|
|
inherited;
|
|
inherited;
|
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
procedure TClientOutput.FreeInstance;
|
|
procedure TClientOutput.FreeInstance;
|
|
|
begin
|
|
begin
|
|
|
- if FPersistent then exit;
|
|
|
|
|
|
|
+ if FPersistent then exit;
|
|
|
inherited;
|
|
inherited;
|
|
|
end;
|
|
end;
|
|
|
|
|
|
|
@@ -2121,7 +2121,7 @@ begin
|
|
|
AddToOutput(TMemoryOutput.Create(Self, lMessage.Memory, 0,
|
|
AddToOutput(TMemoryOutput.Create(Self, lMessage.Memory, 0,
|
|
|
lMessage.Pos-lMessage.Memory, true));
|
|
lMessage.Pos-lMessage.Memory, true));
|
|
|
AddToOutput(FCurrentInput);
|
|
AddToOutput(FCurrentInput);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
WriteBlock;
|
|
WriteBlock;
|
|
|
end;
|
|
end;
|
|
|
|
|
|