-
Notifications
You must be signed in to change notification settings - Fork 5
/
URLThread.pas
159 lines (134 loc) · 4.49 KB
/
URLThread.pas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
unit URLThread;
interface
uses
DataThread,IdHTTP,IdSSLOpenSSL,Classes;
type
PHttp = ^TIdHttp;
TURLThread = class(TDataThread)
private
httpCopy: PHttp; // so we can cancel the request.
protected
public
constructor Create(AInterval : longint);
destructor Destroy; override;
function GetUrl(Url: String; maxfreq: Cardinal = 0; PostParameters: TStringList = nil): String; virtual;
end;
implementation
uses
DateUtils,SysUtils,UConfig,UUtils;
constructor TURLThread.Create(AInterval : longint);
begin
httpCopy := nil;
inherited;
end;
destructor TURLThread.Destroy;
begin
fDataLock.Enter();
if assigned(httpCopy) then
httpCopy^.Disconnect;
fDataLock.Leave();
inherited;
end;
// Download URL and return file location.
// Just return cached file if newer than maxfreq minutes.
function TURLThread.GetUrl(Url: String; maxfreq: Cardinal = 0; PostParameters: TStringList = nil): String;
var
HTTP: TIdHTTP;
Id_HandlerSocket : TIdSSLIOHandlerSocketOpenSSL;
sl: TStringList;
Filename: String;
lasttime: TDateTime;
toonew: Boolean;
sRest: String;
iRest: Integer;
i: Integer;
begin
// Generate a filename for the cached Rss stream.
Filename := copy(LowerCase(Url),1,30);
sRest := copy(LowerCase(Url),30,length(Url)-30);
Filename := StringReplace(Filename, 'http://', '_', [rfReplaceAll]);
Filename := StringReplace(Filename, 'https://', '_', [rfReplaceAll]);
Filename := StringReplace(Filename, '\', '_', [rfReplaceAll]);
Filename := StringReplace(Filename, ':', '_', [rfReplaceAll]);
Filename := StringReplace(Filename, '/', '_', [rfReplaceAll]);
Filename := StringReplace(Filename, '"', '_', [rfReplaceAll]);
Filename := StringReplace(Filename, '|', '_', [rfReplaceAll]);
Filename := StringReplace(Filename, '<', '_', [rfReplaceAll]);
Filename := StringReplace(Filename, '>', '_', [rfReplaceAll]);
Filename := StringReplace(Filename, '&', '_', [rfReplaceAll]);
Filename := StringReplace(Filename, '?', '_', [rfReplaceAll]);
Filename := StringReplace(Filename, '=', '_', [rfReplaceAll]);
Filename := StringReplace(Filename, '.', '_', [rfReplaceAll]);
Filename := StringReplace(Filename, '%', '_', [rfReplaceAll]);
iRest := 0;
for i := 1 to length(sRest) do
begin
iRest := iRest + (Ord(sRest[i]) xor i);
end;
Filename := Filename + IntToHex(iRest, 0);
Filename := extractfilepath(paramstr(0)) + 'cache\\' + Filename + '.cache';
try
toonew := false;
sl := TStringList.create;
HTTP := TIdHTTP.Create(nil);
HTTP.Request.UserAgent := 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:12.0) Gecko/20100101 Firefox/12.0';
Id_HandlerSocket := TIdSSLIOHandlerSocketOpenSSL.Create( HTTP );
Id_HandlerSocket.SSLOptions.Mode := sslmClient;
Id_HandlerSocket.SSLOptions.Method := sslvSSLv23;
HTTP.IOHandler := Id_HandlerSocket;
try
// Only fetch new data if it's newer than the cache files' date.
// and if it's older than maxfreq hours.
if FileExists(Filename) then
begin
lasttime := FileDateToDateTime(FileAge(Filename));
if (MinutesBetween(Now, lasttime) < maxfreq) then toonew := true;
HTTP.Request.LastModified := lasttime;
end;
if (not toonew) then
begin
HTTP.HandleRedirects := True;
if (config.httpProxy <> '') and (config.httpProxyPort <> 0) then
begin
HTTP.ProxyParams.ProxyServer := config.httpProxy;
HTTP.ProxyParams.ProxyPort := config.httpProxyPort;
end;
HTTP.ReadTimeout := 5000; // 5 seconds
if (Terminated) then raise EExiting.Create('');
fDataLock.Enter();
httpCopy := @HTTP;
fDataLock.Leave();
if assigned(PostParameters) then
sl.Text := HTTP.Post(Url, PostParameters)
else
sl.Text := HTTP.Get(Url);
// the get call can block for a long time so check if smartie is exiting
if (Terminated) then raise EExiting.Create('');
sl.savetofile(Filename);
end;
finally
fDataLock.Enter();
httpCopy := nil;
fDataLock.Leave();
freeandnil(sl);
freeandnil(HTTP);
end;
except
on E: EIdHTTPProtocolException do
begin
if (Terminated) then
raise EExiting.Create('');
if (E.ErrorCode <> 304) then // 304=Not Modified.
raise;
end;
else
begin
if (Terminated) then
raise EExiting.Create('');
raise;
end;
end;
// Even if we fail to download - give the filename so they can use the old data.
Result := filename;
end;
end.