6 SysUtils, Classes, ComCtrls, Controls, Forms, IdHTTP,
7 {HTTPApp,} YofUtils, IdGlobal, IdException, IdComponent, IniFiles, {DateUtils,}
8 GikoSystem, BoardGroup, MonaUtils;
11 TDownloadItem = class;
12 TGikoDownloadType = (gdtBoard, gdtThread);
13 TGikoDownloadState = (gdsWait, gdsWork, gdsComplete, gdsDiffComplete, gdsNotModify, gdsAbort, gdsError);
14 TGikoCgiStatus = (gcsOK, gcsINCR, gcsERR);
15 TGikoDLProgress = (gdpStd, gdpAll, gdpDatOchi, gdpOfflaw);
17 TGikoWorkEvent = procedure(Sender: TObject; AWorkMode: TWorkMode; const AWorkCount: Integer; ID: Integer) of object;
18 TGikoWorkBeginEvent = procedure(Sender: TObject; AWorkMode: TWorkMode; const AWorkCountMax: Integer; ID: Integer) of object;
19 TGikoWorkEndEvent = procedure(Sender: TObject; AWorkMode: TWorkMode; ID: Integer) of object;
20 TDownloadEndEvent = procedure(Sender: TObject; Item: TDownloadItem) of object;
21 TDownloadMsgEvent = procedure(Sender: TObject; Item: TDownloadItem; Msg: string; Icon: TGikoMessageIcon) of object;
24 FStatus: TGikoCgiStatus;
30 TDownloadThread = class(TThread)
37 FIcon: TGikoMessageIcon;
39 FOnWork: TGikoWorkEvent;
40 FOnWorkBegin: TGikoWorkBeginEvent;
41 FOnWorkEnd: TGikoWorkEndEvent;
42 FOnDownloadEnd: TDownloadEndEvent;
43 FOnDownloadMsg: TDownloadMsgEvent;
45 procedure FireDownloadEnd;
46 procedure FireDownloadMsg;
47 procedure GetSessionID;
48 procedure WorkBegin(Sender: TObject; AWorkMode: TWorkMode; const AWorkCountMax: Integer);
49 procedure WorkEnd(Sender: TObject; AWorkMode: TWorkMode);
50 procedure Work(Sender: TObject; AWorkMode: TWorkMode; const AWorkCount: Integer);
51 function ParseCgiStatus(Content: string): TCgiStatus;
52 function CgiDownload(ItemType: TGikoDownloadType; URL: string; Modified: TDateTime): Boolean;
53 function DatDownload(ItemType: TGikoDownloadType; URL: string; Modified: TDateTime; RangeStart: Integer; AdjustLen: Integer): Boolean;
54 function DeleteStatusLine(Content: string): string;
56 procedure Execute; override;
58 property Item: TDownloadItem read FItem write FItem;
59 property Number: Integer read FNumber write FNumber;
60 constructor Create(CreateSuspended: Boolean);
61 destructor Destroy; override;
63 property OnWork: TGikoWorkEvent read FOnWork write FOnWork;
64 property OnWorkBegin: TGikoWorkBeginEvent read FOnWorkBegin write FOnWorkBegin;
65 property OnWorkEnd: TGikoWorkEndEvent read FOnWorkEnd write FOnWorkEnd;
66 property OnDownloadEnd: TDownloadEndEvent read FOnDownloadEnd write FOnDownloadEnd;
67 property OnDownloadMsg: TDownloadMsgEvent read FOnDownloadMsg write FOnDownloadMsg;
70 TDownloadItem = class(TObject)
72 FDownType: TGikoDownloadType;
74 FThreadItem: TThreadItem;
76 FContentLength: Integer;
77 FLastModified: TDateTime;
79 FResponseCode: Smallint;
80 FState: TGikoDownloadState;
83 procedure SaveListFile;
84 procedure SaveItemFile;
86 property DownType: TGikoDownloadType read FDownType write FDownType;
87 property Board: TBoard read FBoard write FBoard;
88 property ThreadItem: TThreadItem read FThreadItem write FThreadItem;
90 property ContentLength: Integer read FContentLength write FContentLength;
91 property LastModified: TDateTime read FLastModified write FLastModified;
92 property Content: string read FContent write FContent;
93 property ResponseCode: Smallint read FResponseCode write FResponseCode;
94 property State: TGikoDownloadState read FState write FState;
95 property ErrText: string read FErrText write FErrText;
100 constructor TDownloadThread.Create(CreateSuspended: Boolean);
102 inherited Create(CreateSuspended);
103 FIndy := TIdHttp.Create(nil);
105 FIndy.OnWorkBegin := WorkBegin;
106 FIndy.OnWorkEnd := WorkEnd;
107 FIndy.OnWork := Work;
110 destructor TDownloadThread.Destroy;
116 function RFC1123_Date(aDate : TDateTime) : String;
118 StrWeekDay : String = 'MonTueWedThuFriSatSun';
119 StrMonth : String = 'JanFebMarAprMayJunJulAugSepOctNovDec';
121 Year, Month, Day : Word;
122 Hour, Min, Sec, MSec : Word;
125 DecodeDate(aDate, Year, Month, Day);
126 DecodeTime(aDate, Hour, Min, Sec, MSec);
127 DayOfWeek := ((Trunc(aDate) - 2) mod 7);
128 Result := Copy(StrWeekDay, 1 + DayOfWeek * 3, 3) + ', ' +
129 Format('%2.2d %s %4.4d %2.2d:%2.2d:%2.2d',
130 [Day, Copy(StrMonth, 1 + 3 * (Month - 1), 3),
131 Year, Hour, Min, Sec]);
134 procedure TDownloadThread.Execute;
136 ResStream: TMemoryStream;
139 CgiStatus: TCgiStatus;
145 DownloadResult: Boolean;
149 while not Terminated do begin
151 FIndy.Request.CustomHeaders.Clear;
152 FIndy.Response.Clear;
154 FIndy.Request.UserAgent := GikoSys.GetUserAgent;
155 FIndy.RecvBufferSize := Gikosys.Setting.RecvBufferSize;
156 FIndy.ProxyParams.BasicAuthentication := False;
158 Writeln('------------------------------------------------------------');
160 //FIndy.AllowCookies := False;
161 if GikoSys.Setting.ReadProxy then begin
162 if GikoSys.Setting.ProxyProtocol then
163 FIndy.ProtocolVersion := pv1_1
165 FIndy.ProtocolVersion := pv1_0;
166 FIndy.ProxyParams.ProxyServer := GikoSys.Setting.ReadProxyAddress;
167 FIndy.ProxyParams.ProxyPort := GikoSys.Setting.ReadProxyPort;
168 FIndy.ProxyParams.ProxyUsername := GikoSys.Setting.ReadProxyUserID;
169 FIndy.ProxyParams.ProxyPassword := GikoSys.Setting.ReadProxyPassword;
170 if GikoSys.Setting.ReadProxyUserID <> '' then
171 FIndy.ProxyParams.BasicAuthentication := True;
173 Writeln('
\83v
\83\8d\83L
\83V
\90Ý
\92è
\82 \82è');
174 Writeln('
\83z
\83X
\83g: ' + GikoSys.Setting.ReadProxyAddress);
175 Writeln('
\83|
\81[
\83g: ' + IntToStr(GikoSys.Setting.ReadProxyPort));
178 if GikoSys.Setting.Protocol then
179 FIndy.ProtocolVersion := pv1_1
181 FIndy.ProtocolVersion := pv1_0;
182 FIndy.ProxyParams.ProxyServer := '';
183 FIndy.ProxyParams.ProxyPort := 80;
184 FIndy.ProxyParams.ProxyUsername := '';
185 FIndy.ProxyParams.ProxyPassword := '';
187 Writeln('
\83v
\83\8d\83L
\83V
\90Ý
\92è
\82È
\82µ');
191 FIndy.Request.ContentRangeStart := 0;
192 FIndy.Request.LastModified := ZERO_DATE;
193 ResStream := TMemoryStream.Create;
196 //********************
197 //DAT or Subject
\8eæ
\93¾
198 //********************
199 Item.ResponseCode := 0;
203 if Item.DownType = gdtBoard then begin
205 Writeln('Subject
\8eæ
\93¾');
206 Writeln('URL: ' + Item.Board.GetReadCgiURL);
207 Writeln('Modified: ' + FloatToStr(Item.Board.LastModified));
209 URL := Item.Board.GetReadCgiURL;
210 Modified := Item.Board.LastModified;
211 end else if Item.DownType = gdtThread then begin
213 Writeln('DAT
\8eæ
\93¾');
214 Writeln('URL: ' + Item.ThreadItem.GetDatURL);
215 Writeln('Modified: ' + FloatToStr(Item.ThreadItem.LastModified));
217 URL := Item.ThreadItem.GetDatURL;
218 Modified := Item.ThreadItem.LastModified;
219 if Item.ThreadItem.Size > 0 then begin
221 Writeln('RangeStart: ' + IntToStr(Item.ThreadItem.Size));
223 //
\82 \82Ú
\81[
\82ñ
\83`
\83F
\83b
\83N
\82Ì
\82½
\82ß
\82P
\83o
\83C
\83g
\91O
\82©
\82ç
\8eæ
\93¾
224 RangeStart := Item.ThreadItem.Size;
229 DownloadResult := DatDownload(Item.DownType, URL, Modified, RangeStart, AdjustLen);
231 Writeln('ResponseCode: ' + IntToStr(FIndy.ResponseCode));
233 if Item.DownType = gdtThread then begin
234 if Item.ResponseCode = 416 then begin
236 DownloadResult := True;
237 end else if DownloadResult and (AdjustLen = -1) and (Item.Content[1] <> #10) then
241 if Trim(FIndy.Response.RawHeaders.Values['Date']) <> '' then begin
242 if Item.DownType = gdtBoard then
243 Item.Board.LastGetTime := MonaUtils.DateStrToDateTime(FIndy.Response.RawHeaders.Values['Date'])
245 Item.ThreadItem.ParentBoard.LastGetTime := MonaUtils.DateStrToDateTime(FIndy.Response.RawHeaders.Values['Date']);
248 if DownloadResult then begin
250 Writeln('Date:' + FIndy.Response.RawHeaders.Values['Date']);
254 Writeln('
\82 \82Ú
\81[
\82ñ
\8c\9f\8fo');
256 ATitle := Item.ThreadItem.Title;
258 ATitle := '
\81i
\96¼
\8fÌ
\95s
\96¾
\81j';
259 //
\8d·
\95ª
\8eæ
\93¾
\82©
\82Â
\82P
\83o
\83C
\83g
\96Ú
\82ªLF
\82Å
\82È
\82¢
\8fê
\8d\87\82Í
\81u
\82 \82Ú
\81[
\82ñ
\81v
\82³
\82ê
\82Ä
\82¢
\82é
\82©
\82à
\82µ
\82ê
\82ñ
\82Ì
\82Å
\8dÄ
\8eæ
\93¾
262 FMsg := '
\81\9a\81u
\82 \82Ú
\81[
\82ñ
\81v
\82ð
\8c\9f\8fo
\82µ
\82½
\82Ì
\82Å
\8dÄ
\8eæ
\93¾
\82ð
\8ds
\82¢
\82Ü
\82· - [' + ATitle + ']';
264 if FileExists(ChangeFileExt(Item.FThreadItem.GetThreadFileName,'.NG')) = true then
265 DeleteFile(ChangeFileExt(Item.FThreadItem.GetThreadFileName,'.NG'));
266 if Assigned(OnDownloadMsg) then
267 Synchronize(FireDownloadMsg);
268 if not DatDownload(Item.DownType, URL, ZERO_DATE, RangeStart, AdjustLen) then
269 Item.State := gdsError;
271 Writeln('
\82 \82Ú
\81[
\82ñ
\8dÄ
\8eæ
\93¾
\8cã');
272 Writeln('ResponseCode: ' + IntToStr(Item.ResponseCode));
274 end else if (Item.DownType = gdtThread) and (AdjustLen = -1) and (Item.Content[1] = #10) then begin
275 //
\8d·
\95ª
\8eæ
\93¾
\82©
\82Â
\82P
\83o
\83C
\83g
\96Ú
\82ªLF
\82Ì
\8fê
\8d\87\81i
\90³
\8fí
\8eæ
\93¾
\81j
\82Í
\93ª
\82ÌLF
\82ð
\8dí
\8f\9c
276 Item.Content := Copy(Item.Content, 2, Length(Item.Content));
279 Item.State := gdsError;
280 if (Item.DownType = gdtBoard) and (Item.ResponseCode = 302) then begin
281 FMsg := '
\81\9a\81\9a\94Â
\82ª
\88Ú
\93]
\82µ
\82½
\82©
\82à
\82µ
\82ê
\82È
\82¢
\82Ì
\82Å
\94Â
\8dX
\90V
\82ð
\8ds
\82Á
\82Ä
\82
\82¾
\82³
\82¢
\81\9a\81\9a';
283 if Assigned(OnDownloadMsg) then
284 Synchronize(FireDownloadMsg);
288 //********************
290 //********************
291 if (Item.DownType = gdtThread) and (Item.ResponseCode = 302) then begin
293 Writeln('dat.gz
\8eæ
\93¾');
295 ATitle := Item.ThreadItem.Title;
297 ATitle := '
\81i
\96¼
\8fÌ
\95s
\96¾
\81j';
298 FMsg := '
\81\9adat
\82ª
\91¶
\8dÝ
\82µ
\82È
\82¢
\82½
\82ß
\89ß
\8b\8e\83\8d\83O(dat.gz)
\82ð
\92T
\82µ
\82Ü
\82· - [' + ATitle + ']';
300 if Assigned(OnDownloadMsg) then
301 Synchronize(FireDownloadMsg);
302 URL := Item.ThreadItem.GetDatgzURL;
303 Modified := Item.ThreadItem.LastModified;
306 if not DatDownload(Item.DownType, URL, Modified, RangeStart, AdjustLen) then
307 Item.State := gdsError;
309 Writeln('ResponseCode: ' + IntToStr(Item.ResponseCode));
313 //********************
315 //********************
317 if (Item.DownType = gdtThread) and (Item.ResponseCode = 302) then begin
318 ATitle := Item.ThreadItem.Title;
320 ATitle := '
\81i
\96¼
\8fÌ
\95s
\96¾
\81j';
321 FMsg := '
\81\9a\89ß
\8b\8e\83\8d\83O(1)
\82ª
\91¶
\8dÝ
\82µ
\82È
\82¢
\82½
\82ß
\89ß
\8b\8e\83\8d\83O(2)
\82©
\82ç
\92T
\82µ
\82Ü
\82· - [' + ATitle + ']';
323 if Assigned(OnDownloadMsg) then
324 Synchronize(FireDownloadMsg);
325 URL := Item.ThreadItem.GetOldDatgzURL;
326 Modified := Item.ThreadItem.LastModified;
329 if not DatDownload(Item.DownType, URL, Modified, RangeStart, AdjustLen) then
330 Item.State := gdsError;
334 //********************
335 //offlaw.cgi
\82Å
\8eæ
\93¾
336 //********************
338 Synchronize(GetSessionID);
339 if (Item.DownType = gdtThread) and (Item.ResponseCode = 302) and (FSessionID <> '') then begin
341 Writeln('offlaw.cgi
\82Å
\8eæ
\93¾');
343 ATitle := Item.ThreadItem.Title;
345 ATitle := '
\81i
\96¼
\8fÌ
\95s
\96¾
\81j';
346 FMsg := '
\81\9adat.gz
\82ª
\91¶
\8dÝ
\82µ
\82È
\82¢
\82½
\82ßofflaw.cgi
\82ð
\97\98\97p
\82µ
\82Ü
\82· - [' + ATitle + ']';
348 if Assigned(OnDownloadMsg) then
349 Synchronize(FireDownloadMsg);
350 URL := Item.ThreadItem.GetOfflawCgiURL(FSessionID);
351 Modified := Item.ThreadItem.LastModified;
354 if not DatDownload(Item.DownType, URL, Modified, RangeStart, AdjustLen) then begin
356 Writeln('ResponseCode: ' + IntToStr(Item.ResponseCode));
358 Item.State := gdsError;
360 if (Item.DownType = gdtThread) and (Item.ResponseCode = 302) then begin
361 FMsg := '
\94Â
\82ª
\88Ú
\93]
\82µ
\82½
\82©
\82à
\82µ
\82ê
\82È
\82¢
\82Ì
\82Å
\94Â
\8dX
\90V
\82ð
\8ds
\82Á
\82Ä
\82
\82¾
\82³
\82¢
\81B';
363 if Assigned(OnDownloadMsg) then
364 Synchronize(FireDownloadMsg);
368 CgiStatus := ParseCgiStatus(Item.Content);
370 Writeln('ResponseCode: ' + IntToStr(Item.ResponseCode));
372 case CgiStatus.FStatus of
375 Writeln('CGIStatus: OK');
377 Item.ResponseCode := 200;
378 Item.Content := DeleteStatusLine(Item.Content);
379 Item.ContentLength := CgiStatus.FSize;
382 //
\8d¡
\82Í
\82 \82è
\82¦
\82È
\82¢
384 Writeln('CGIStatus: 206');
386 Item.ResponseCode := 206;
387 Item.Content := DeleteStatusLine(Item.Content);
388 Item.ContentLength := CgiStatus.FSize;
392 Writeln('CGIStatus: 404(ERROR)');
394 Item.ResponseCode := 404;
395 Item.State := gdsError;
396 Item.ErrText := CgiStatus.FErrText;
399 if (Item.ResponseCode = 404) and (AnsiPos('
\89ß
\8b\8e\83\8d\83O
\91q
\8cÉ
\82Å
\94
\8c©', Item.ErrText) <> 0) then begin
401 Writeln('
\89ß
\8b\8e\83\8d\83O
\8eæ
\93¾');
403 ATitle := Item.ThreadItem.Title;
405 ATitle := '
\81i
\96¼
\8fÌ
\95s
\96¾
\81j';
406 FMsg := '
\81\9a\89ß
\8b\8e\83\8d\83O
\91q
\8cÉ
\82Å
\94
\8c© - [' + ATitle + ']';
408 if Assigned(OnDownloadMsg) then
409 Synchronize(FireDownloadMsg);
410 Idx := Pos(' ', Item.ErrText);
411 if Idx <> 0 then begin
412 URL := Copy(Item.ErrText, Idx + 1, Length(Item.ErrText));
413 if Pos('../', URL) = 1 then
414 URL := Copy(URL, 4, Length(URL));
415 URL := GikoSys.UrlToServer(Item.ThreadItem.ParentBoard.URL) + URL;
416 Modified := Item.ThreadItem.LastModified;
419 if not DatDownload(Item.DownType, URL, Modified, RangeStart, AdjustLen) then
420 Item.State := gdsError;
422 Writeln('ResponseCode: ' + IntToStr(Item.ResponseCode));
428 if (Item.DownType = gdtThread) and (Item.ResponseCode = 302) and (FSessionID = '') then begin
430 Writeln('
\83\8d\83O
\83C
\83\93\82³
\82ê
\82Ä
\82È
\82¢
\82Ì
\82Å
\89ß
\8b\8e\83\8d\83O
\8eæ
\93¾
\95s
\89Â');
432 ATitle := Item.ThreadItem.Title;
434 ATitle := '
\81i
\96¼
\8fÌ
\95s
\96¾
\81j';
435 FMsg := '
\81\9a\83\8d\83O
\83C
\83\93\82³
\82ê
\82Ä
\82¢
\82È
\82¢
\82½
\82ß
\92T
\82·
\82±
\82Æ
\82ª
\8fo
\97\88\82Ü
\82¹
\82ñ - [' + ATitle + ']';
437 if Assigned(OnDownloadMsg) then
438 Synchronize(FireDownloadMsg);
443 if (Item.DownType = gdtThread) and (Item.ResponseCode = 302) then begin
444 ATitle := Item.ThreadItem.Title;
446 ATitle := '
\81i
\96¼
\8fÌ
\95s
\96¾
\81j';
447 FMsg := '
\81\9a\89ß
\8b\8e\83\8d\83O(1)
\82ª
\91¶
\8dÝ
\82µ
\82È
\82¢
\82½
\82ßgoogle
\83L
\83\83\83b
\83V
\83\85\82©
\82ç
\92T
\82µ
\82Ü
\82· - [' + ATitle + ']';
449 if Assigned(OnDownloadMsg) then
450 Synchronize(FireDownloadMsg);
451 URL := 'http://www.google.co.jp/search?q=cache:' + Item.ThreadItem.URL;
452 URL := StringReplace( URL, 'l50', '', [rfReplaceAll] );
453 Modified := Item.ThreadItem.LastModified;
455 if not CgiDownload(Item.DownType, URL, Modified) then
456 Item.State := gdsError;
457 URL := FIndy.Response.Location;
458 Until Item.ResponseCode <> 301;
459 if Item.ResponseCode = 200 then begin
460 foundPos := Pos( '<dt>', Item.Content ) + Length( '<dt>' );
461 Item.Content := Copy( Item.Content, foundPos, Length( Item.Content ) );
462 foundPos := Pos( '</dl>', Item.Content );
464 Item.Content := Copy( Item.Content, 1, foundPos - 1 );
465 Item.Content := StringReplace( Item.Content, '<dt>', '<>' + #13#10, [rfReplaceAll] );
466 Item.Content := StringReplace( Item.Content, '<a href="mailto:', '', [rfReplaceAll] );
467 Item.Content := StringReplace( Item.Content, '"><b>', '<>', [rfReplaceAll] );
468 Item.Content := StringReplace( Item.Content, '<b>', '<>', [rfReplaceAll] );
469 Item.Content := StringReplace( Item.Content, '</b></a>', '<>', [rfReplaceAll] );
470 Item.Content := StringReplace( Item.Content, '</b>', '<>', [rfReplaceAll] );
471 Item.Content := StringReplace( Item.Content, '<dd>', '<>', [rfReplaceAll] );
476 case Item.ResponseCode of
477 200: Item.State := gdsComplete;
478 206: Item.State := gdsDiffComplete;
479 304: Item.State := gdsNotModify;
481 Item.State := gdsError;
484 //
\96³
\82¢
\82Æ
\8ev
\82¤
\82¯
\82Ç
\81B
\81B
\81B
485 if (Item.ResponseCode in [200, 206]) and (Item.Content = '') then
486 Item.State := gdsError;
487 Item.LastModified := FIndy.Response.LastModified;
488 //
\8d·
\95ª
\8eæ
\93¾
\82Å
\82P
\83o
\83C
\83g
\91O
\82©
\82ç
\82Æ
\82Á
\82Ä
\82«
\82½
\82Æ
\82«
\82Í
\83}
\83C
\83i
\83X
\82·
\82é
489 Item.ContentLength := FIndy.Response.ContentLength + AdjustLen;
492 FIndy.Get(URL, ResStream);
493 Item.Content := GikoSys.GzipDecompress(ResStream, FIndy.Response.ContentEncoding);
494 if (Item.DownType = gdtThread) and (AdjustLen = -1) and (Item.Content[1] <> #10) then begin
495 //
\8d·
\95ª
\8eæ
\93¾
\82©
\82Â
\82P
\83o
\83C
\83g
\96Ú
\82ªLF
\82Å
\82È
\82¢
\8fê
\8d\87\82Í
\81u
\82 \82Ú
\81[
\82ñ
\81v
\82³
\82ê
\82Ä
\82¢
\82é
\82©
\82à
\82µ
\82ê
\82ñ
\82Ì
\82Å
\8dÄ
\8eæ
\93¾
496 //
\82±
\82±
\82Å
\83\81\83b
\83Z
\81[
\83W
\95\
\8e¦
\83C
\83x
\83\93\83g
498 FMsg := '
\81u
\82 \82Ú
\81[
\82ñ
\81v
\82ð
\8c\9f\8fo
\82µ
\82½
\82Ì
\82Å
\8dÄ
\8eæ
\93¾
\82ð
\8ds
\82¢
\82Ü
\82·';
499 if Assigned(OnDownloadMsg) then
500 Synchronize(FireDownloadMsg);
501 FIndy.Request.ContentRangeStart := 0;
502 FIndy.Request.ContentRangeEnd := 0;
505 FIndy.Get(URL, ResStream);
506 Item.Content := GikoSys.GzipDecompress(ResStream, FIndy.Response.ContentEncoding);
507 end else if (Item.DownType = gdtThread) and (AdjustLen = -1) and (Item.Content[1] = #10) then begin
508 //
\8d·
\95ª
\8eæ
\93¾
\82©
\82Â
\82P
\83o
\83C
\83g
\96Ú
\82ªLF
\82Ì
\8fê
\8d\87\81i
\90³
\8fí
\8eæ
\93¾
\81j
\82Í
\93ª
\82ÌLF
\82ð
\8dí
\8f\9c
509 Item.Content := Copy(Item.Content, 2, Length(Item.Content));
512 Item.State := gdsError;
514 Item.ResponseCode := FIndy.ResponseCode;
519 FIndy.Get(URL, ResStream);
520 Item.Content := GikoSys.GzipDecompress(ResStream, FIndy.Response.ContentEncoding);
522 Item.State := gdsError;
525 CgiStatus := ParseCgiStatus(Item.Content);
526 if CgiStatus.FStatus = gcsOK then begin
527 if CgiStatus.FSize = 0 then
528 Item.State := gdsNotModify
529 else if Item.DownType = gdtBoard then
530 Item.State := gdsComplete
532 Item.State := gdsDiffComplete;
533 end else if CgiStatus.FStatus = gcsINCR then begin
534 Item.State := gdsComplete;
535 end else if CgiStatus.FStatus = gcsERR then begin
536 Item.State := gdsError;
537 Item.ErrText := CgiStatus.FErrText;
539 Item.ContentLength := CgiStatus.FSize;
542 Item.State := gdsError;
544 //Item.ResponseCode := FIndy.ResponseCode;
546 Item.State := gdsAbort;
548 if Assigned(OnDownloadEnd) then
549 Synchronize(FireDownloadEnd);
552 if Terminated then Break;
557 function TDownloadThread.CgiDownload(ItemType: TGikoDownloadType; URL: string; Modified: TDateTime): Boolean;
559 ResponseCode: Integer;
560 ResStream: TMemoryStream;
563 FIndy.Request.ContentRangeStart := 0;
564 FIndy.Request.ContentRangeEnd := 0;
566 FIndy.Request.CustomHeaders.Clear;
567 if (Modified <> 0) and (Modified <> ZERO_DATE) then begin
568 FIndy.Request.LastModified := modified - OffsetFromUTC;
570 FIndy.Request.AcceptEncoding := '';
571 FIndy.Request.Accept := 'text/html';
572 ResStream := TMemoryStream.Create;
577 Writeln('URL: ' + URL);
579 FIndy.Get(URL, ResStream);
580 Item.Content := GikoSys.GzipDecompress(ResStream, FIndy.Response.ContentEncoding);
581 Item.LastModified := FIndy.Response.LastModified;
582 //
\8d·
\95ª
\8eæ
\93¾
\82Å
\82P
\83o
\83C
\83g
\91O
\82©
\82ç
\82Æ
\82Á
\82Ä
\82«
\82½
\82Æ
\82«
\82Í
\83}
\83C
\83i
\83X
\82·
\82é
583 Item.ContentLength := Length(Item.Content);
584 //
\96³
\82¢
\82Æ
\8ev
\82¤
\82¯
\82Ç
\81B
\81B
\81B
585 if Item.Content = '' then
590 Writeln('
\8eæ
\93¾
\82Å
\97á
\8aO
\82È
\82µ');
592 ResponseCode := FIndy.ResponseCode;
594 on E: EIdSocketError do begin
596 Item.LastModified := ZERO_DATE;
597 Item.ContentLength := 0;
598 Item.ErrText := E.Message;
601 Screen.Cursor := crDefault;
603 on E: EIdConnectException do begin
605 Item.LastModified := ZERO_DATE;
606 Item.ContentLength := 0;
607 Item.ErrText := E.Message;
610 Screen.Cursor := crDefault;
612 on E: Exception do begin
614 Writeln('
\8eæ
\93¾
\82Å
\97á
\8aO
\82 \82è');
615 Writeln('E.Message: ' + E.Message);
618 Item.LastModified := ZERO_DATE;
619 Item.ContentLength := 0;
620 Item.ErrText := E.Message;
621 ResponseCode := FIndy.ResponseCode;
623 Screen.Cursor := crDefault;
627 if (Item.ContentLength = 0) and (ResponseCode = 206) then
628 Item.ResponseCode := 304
630 Item.ResponseCode := ResponseCode;
635 function TDownloadThread.DatDownload(ItemType: TGikoDownloadType; URL: string; Modified: TDateTime; RangeStart: Integer; AdjustLen: Integer): Boolean;
637 ResponseCode: Integer;
638 ResStream: TMemoryStream;
641 if (ItemType = gdtThread) and (RangeStart > 0) then begin
642 // if (ItemType = gdtThread) and (Item.ThreadItem.Size > 0) then begin
643 // FIndy.Request.ContentRangeStart := Item.ThreadItem.Size + AdjustLen;
644 FIndy.Request.ContentRangeStart := RangeStart + AdjustLen;
645 FIndy.Request.ContentRangeEnd := 0;
647 FIndy.Request.ContentRangeStart := 0;
648 FIndy.Request.ContentRangeEnd := 0;
651 FIndy.Request.CustomHeaders.Clear;
652 FIndy.Request.CacheControl := 'no-cache';
653 FIndy.Request.CustomHeaders.Add('Pragma: no-cache');
654 if (Modified <> 0) and (Modified <> ZERO_DATE) then begin
655 FIndy.Request.LastModified := modified - OffsetFromUTC;
656 //FIndy.Request.CustomHeaders.Add('If-Modified-Since: ' + RFC1123_Date(modified - OffsetFromUTC) + ' GMT');
658 // FIndy.Request.AcceptEncoding := 'gzip';
659 if RangeStart = 0 then
660 FIndy.Request.AcceptEncoding := 'gzip'
662 FIndy.Request.AcceptEncoding := '';
663 ResStream := TMemoryStream.Create;
668 Writeln('URL: ' + URL);
670 FIndy.Get(URL, ResStream);
671 Item.Content := GikoSys.GzipDecompress(ResStream, FIndy.Response.ContentEncoding);
672 Item.LastModified := FIndy.Response.LastModified;
673 //
\8d·
\95ª
\8eæ
\93¾
\82Å
\82P
\83o
\83C
\83g
\91O
\82©
\82ç
\82Æ
\82Á
\82Ä
\82«
\82½
\82Æ
\82«
\82Í
\83}
\83C
\83i
\83X
\82·
\82é
674 // Item.ContentLength := FIndy.Response.ContentLength + AdjustLen;
675 Item.ContentLength := Length(Item.Content) + AdjustLen;
676 //
\96³
\82¢
\82Æ
\8ev
\82¤
\82¯
\82Ç
\81B
\81B
\81B
677 // if (FIndy.ResponseCode in [200, 206]) and (Item.Content = '') then
679 if Item.Content = '' then
684 Writeln('
\8eæ
\93¾
\82Å
\97á
\8aO
\82È
\82µ');
686 ResponseCode := FIndy.ResponseCode;
688 on E: EIdSocketError do begin
690 Item.LastModified := ZERO_DATE;
691 Item.ContentLength := 0;
692 Item.ErrText := E.Message;
695 Screen.Cursor := crDefault;
697 on E: EIdConnectException do begin
699 Item.LastModified := ZERO_DATE;
700 Item.ContentLength := 0;
701 Item.ErrText := E.Message;
704 Screen.Cursor := crDefault;
706 on E: Exception do begin
708 Writeln('
\8eæ
\93¾
\82Å
\97á
\8aO
\82 \82è');
709 Writeln('E.Message: ' + E.Message);
712 Item.LastModified := ZERO_DATE;
713 Item.ContentLength := 0;
714 Item.ErrText := E.Message;
715 ResponseCode := FIndy.ResponseCode;
717 Screen.Cursor := crDefault;
721 if (Item.ContentLength = 0) and (ResponseCode = 206) then
722 Item.ResponseCode := 304
724 Item.ResponseCode := ResponseCode;
729 procedure TDownloadThread.FireDownloadEnd;
731 OnDownloadEnd(self, Item);
734 procedure TDownloadThread.FireDownloadMsg;
736 OnDownloadMsg(Self, Item, FMsg, FIcon);
739 procedure TDownloadThread.GetSessionID;
741 FSessionID := GikoSys.Dolib.SessionID;
744 procedure TDownloadThread.Abort;
747 FIndy.DisconnectSocket;
750 procedure TDownloadThread.WorkBegin(Sender: TObject; AWorkMode: TWorkMode; const AWorkCountMax: Integer);
752 if Assigned(OnWorkBegin) then
753 OnWorkBegin(Sender, AWorkMode, AWorkCountMax, FNumber);
756 procedure TDownloadThread.WorkEnd(Sender: TObject; AWorkMode: TWorkMode);
758 if Assigned(OnWorkEnd) then
759 OnWorkEnd(Sender, AWorkMode, FNumber);
762 procedure TDownloadThread.Work(Sender: TObject; AWorkMode: TWorkMode; const AWorkCount: Integer);
764 if Assigned(OnWork) then
765 OnWork(Sender, AWorkMode, AWorkCount, FNumber);
768 function TDownloadThread.ParseCgiStatus(Content: string): TCgiStatus;
777 // [+OK]
\82Ì
\8fê
\8d\87\82Í
\8d·
\95ª
778 // [-INCR] (Incorrect)
\82Ì
\8fê
\8d\87\82Í
\82·
\82×
\82Ä
\82Ì
\83f
\81[
\83^
779 // [-ERR (
\83e
\83L
\83X
\83g)]
\82Ì
\8fê
\8d\87\82Í
\82È
\82ñ
\82©
\83G
\83\89\81[
780 //
\97á
\81F+OK 23094/512K
782 // -ERR
\82»
\82ñ
\82È
\94Â
\82È
\82¢
\82Å
\82·
783 Idx := AnsiPos(#10, Content);
784 StatusLine := Copy(Content, 0, Idx);
786 Idx := AnsiPos(' ', Content);
787 Status := Copy(StatusLine, 0, Idx - 1);
788 Line := Copy(StatusLine, Idx + 1, Length(StatusLine));
790 // Idx := AnsiPos('/', Line);
791 if Trim(Status) = '-ERR' then
794 Size := Copy(Line, 0, Idx - 1);
796 if Trim(Status) = '+OK' then
797 Result.FStatus := gcsOK
798 else if Trim(Status) = '-INCR' then
799 Result.FStatus := gcsINCR
800 else if Trim(Status) = '-ERR' then begin
801 Result.FStatus := gcsERR;
802 Result.FErrText := Msg;
809 Result.FStatus := gcsERR;
810 Result.FErrText := '
\83G
\83\89\81[
\82È
\82ñ
\82¾
\82¯
\82Ç
\81A
\82æ
\82
\95ª
\82©
\82ç
\82È
\82¢
\83G
\83\89\81[';
815 if GikoSys.IsNumeric(Size) then
816 Result.FSize := StrToInt(Size)
819 Result.FStatus := gcsERR;
820 Result.FErrText := '
\83X
\83e
\81[
\83^
\83X
\89ð
\90Í
\8e¸
\94s[' + StatusLine + ']';
824 //
\8eè
\94²
\82«
\82È
\8f\88\97\9d\82Å1
\8ds
\96Ú
\82ð
\8fÁ
\82·
825 function TDownloadThread.DeleteStatusLine(Content: string): string;
829 SList := TStringList.Create;
831 SList.Text := Content;
832 if SList.Count > 1 then
834 Result := SList.Text;
840 procedure TDownloadItem.SaveListFile;
844 NewItem: TThreadItem;
846 // SaveCount: Integer;
851 NewList := TList.Create;
852 Body := TStringList.Create;
854 //
\83_
\83E
\83\93\83\8d\81[
\83h
\93ú
\8e\9e\90Ý
\92è
\81i
\83\8d\81[
\83J
\83\8b\93ú
\8e\9e\81j
855 Board.RoundDate := Now;
856 //
\83T
\81[
\83o
\8fã
\83t
\83@
\83C
\83\8b\82Ì
\8dX
\90V
\8e\9e\8d\8f\90Ý
\92è
857 Board.LastModified := LastModified;
859 //
\90V
\82µ
\82¢
\83\8a\83X
\83g
\82ð
\8dì
\90¬
\82·
\82é
860 //
\90V
\82µ
\82¢
\83\8a\83X
\83g
\82É
\8cÃ
\82¢
\83\8a\83X
\83g
\82Ì
\83\8d\83O
\82ª
\82 \82é
\82È
\82ç
\82»
\82ê
\82ð
\90V
\82µ
\82¢
\83\8a\83X
\83g
\82É
\92Ç
\89Á
861 //
\8cÃ
\82¢
\83\8d\83O
\82ª
\82È
\82¯
\82ê
\82Î
\81A
\90V
\82½
\82É
\83X
\83\8c\83I
\83u
\83W
\83F
\83N
\83g
\82ð
\8dì
\90¬
862 Body.Text := Content;
864 for i := 0 to Body.Count - 1 do begin
865 //if i = 0 then Continue; //
\82P
\8ds
\96Ú
\82Í
\83X
\83e
\81[
\83^
\83X
\8ds
\82Ì
\82½
\82ß
\8f\88\97\9d\82È
\82µ
867 Rec := GikoSys.DivideSubject(Body[i]);
868 Rec.FFileName := Trim(Rec.FFileName);
869 if (Rec.FTitle = '') and (Rec.FCount = 0) then Continue;
871 index := Board.GetIndex(Rec.FFileName);
872 if index = -1 then begin
873 //
\90V
\82µ
\82¢
\83X
\83\8c\83b
\83h
874 NewItem := TThreadItem.Create;
875 NewItem.FileName := Rec.FFileName;
876 NewItem.Title := Rec.FTitle;
877 // NewItem.Count := Rec.FCount;
878 NewItem.AllResCount := Rec.FCount;
879 NewItem.ParentBoard := Board;
880 NewItem.No := NumCount;
881 NewItem.RoundDate := ZERO_DATE;
882 NewItem.LastModified := ZERO_DATE;
883 NewItem.AgeSage := gasNew;
884 NewList.Add(NewItem);
886 //Board.Items[index].Count := Count;
887 //Board.Items[index].Count := Rec.FCount;
888 if Board.Items[index].No > NumCount then
889 Board.Items[index].AgeSage := gasAge
890 else if Board.Items[index].AllResCount < Rec.FCount then
891 Board.Items[index].AgeSage := gasSage
893 Board.Items[index].AgeSage := gasNone;
896 Board.Items[index].No := NumCount;
897 Board.Items[index].AllResCount := Rec.FCount;
898 // if not Board.Items[index].IsLogFile then
899 // Board.Items[index].Count := Rec.FCount;
900 NewList.Add(Board.Items[index]);
901 Board.DeleteList(index);
905 //
\90V
\82µ
\82¢
\83\8a\83X
\83g
\82É
\96³
\82©
\82Á
\82½
\83A
\83C
\83e
\83\80\82ð
\90V
\82µ
\82¢
\83\8a\83X
\83g
\82É
\92Ç
\89Á
906 for i := 0 to Board.Count - 1 do begin
907 if Board.Items[i].IsLogFile then begin
909 Board.Items[i].No := NumCount;
910 Board.Items[i].AllResCount := Board.Items[i].Count;
911 Board.Items[i].NewResCount := 0;
912 Board.Items[i].AgeSage := gasNone;
913 NewList.Add(Board.Items[i]);
917 //
\8cÃ
\82¢
\83\8a\83X
\83g
\82ð
\8fÁ
\82·
\81i
\83\8a\83X
\83g
\82Ì
\82Ý
\81B
\83X
\83\8c\83I
\83u
\83W
\83F
\83N
\83g
\8e©
\91Ì
\82Í
\8fÁ
\82³
\82È
\82¢
\81j
918 for i := Board.Count - 1 downto 0 do
921 //
\90V
\82µ
\82¢
\83\8a\83X
\83g
\82ð
\83{
\81[
\83h
\83I
\83u
\83W
\83F
\83N
\83g
\82É
\92Ç
\89Á
922 for i := 0 to NewList.Count - 1 do
923 Board.Add(TThreadItem(NewList[i]));
925 //
\83\8a\83X
\83g(subject.txt)
\82ð
\95Û
\91¶
926 // GikoSys.ForceDirectoriesEx(GikoSys.GetLogDir + Board.BBSID);
927 // Body.SaveToFile(GikoSys.GetSubjectFileName(Board.BBSID));
928 GikoSys.ForceDirectoriesEx(ExtractFilePath(Board.GetSubjectFileName));
929 Body.SaveToFile(Board.GetSubjectFileName);
936 {procedure TDownloadItem.SaveListFile;
940 NewItem: TThreadItem;
942 // SaveCount: Integer;
947 NewList := TList.Create;
948 Body := TStringList.Create;
950 //
\8f\84\89ñ
\93ú
\8e\9e\90Ý
\92è
951 Board.RoundDate := Now;
952 //
\83T
\81[
\83o
\8fã
\83t
\83@
\83C
\83\8b\82Ì
\8dX
\90V
\8e\9e\8d\8f\90Ý
\92è
953 Board.LastModified := LastModified;
955 //
\83\8a\83X
\83g
\95Û
\91¶
\8c\8f\90\94\8eæ
\93¾
956 //SaveCount := MaxInt;
958 //
\8cÃ
\82¢
\83\8a\83X
\83g
\82©
\82ç
\83\8d\83O
\96³
\82µ
\83A
\83C
\83e
\83\80\82ð
\8dí
\8f\9c
959 for i := Board.Count - 1 downto 0 do
960 if not Board.Items[i].IsLogFile then
963 //
\90V
\82µ
\82¢
\83\8a\83X
\83g
\82ð
\8dì
\90¬
\82·
\82é
964 //
\90V
\82µ
\82¢
\83\8a\83X
\83g
\82É
\8cÃ
\82¢
\83\8a\83X
\83g
\82Ì
\83\8d\83O
\82ª
\82 \82é
\82È
\82ç
\82»
\82ê
\82ð
\90V
\82µ
\82¢
\83\8a\83X
\83g
\82É
\92Ç
\89Á
965 //
\8cÃ
\82¢
\83\8d\83O
\82ª
\82È
\82¯
\82ê
\82Î
\81A
\90V
\82½
\82É
\83X
\83\8c\83I
\83u
\83W
\83F
\83N
\83g
\82ð
\8dì
\90¬
966 Body.Text := Content;
967 // Loop := Min(Body.Count, SaveCount);
969 // for i := 0 to Loop - 1 do begin
970 for i := 0 to Body.Count - 1 do begin
971 if i = 0 then Continue; //
\82P
\8ds
\96Ú
\82Í
\83X
\83e
\81[
\83^
\83X
\8ds
\82Ì
\82½
\82ß
\8f\88\97\9d\82È
\82µ
973 Rec := GikoSys.DivideSubject(Body[i]);
974 if (Rec.FTitle = '') and (Rec.FCount = 0) then Continue;
976 index := Board.GetIndex(Rec.FFileName);
977 if index = -1 then begin
978 NewItem := TThreadItem.Create;
979 NewItem.FileName := Rec.FFileName;
980 NewItem.Title := Rec.FTitle;
981 NewItem.Count := Rec.FCount;
982 NewItem.ParentBoard := Board;
983 NewItem.No := NumCount;
984 NewItem.RoundDate := ZERO_DATE;
985 NewItem.LastModified := ZERO_DATE;
986 NewList.Add(NewItem);
988 //Board.Items[index].Count := Count;
989 Board.Items[index].No := NumCount;
990 NewList.Add(Board.Items[index]);
991 Board.DeleteList(index);
995 //
\90V
\82µ
\82¢
\83\8a\83X
\83g
\82É
\96³
\82©
\82Á
\82½
\8cÃ
\82¢
\83\8d\83O
\97L
\82è
\83A
\83C
\83e
\83\80\82ð
\90V
\82µ
\82¢
\83\8a\83X
\83g
\82É
\92Ç
\89Á
996 for i := 0 to Board.Count - 1 do begin
998 Board.Items[i].No := NumCount;
999 NewList.Add(Board.Items[i]);
1002 //
\8cÃ
\82¢
\83\8a\83X
\83g
\82ð
\8fÁ
\82·
\81i
\83\8a\83X
\83g
\82Ì
\82Ý
\81B
\83X
\83\8c\83I
\83u
\83W
\83F
\83N
\83g
\8e©
\91Ì
\82Í
\8fÁ
\82³
\82È
\82¢
\81j
1003 for i := Board.Count - 1 downto 0 do
1004 Board.DeleteList(i);
1006 //
\90V
\82µ
\82¢
\83\8a\83X
\83g
\82ð
\83{
\81[
\83h
\83I
\83u
\83W
\83F
\83N
\83g
\82É
\92Ç
\89Á
1007 for i := 0 to NewList.Count - 1 do
1008 Board.Add(TThreadItem(NewList[i]));
1010 //
\83\8a\83X
\83g(subject.txt)
\82ð
\95Û
\91¶
1011 // GikoSys.ForceDirectoriesEx(GikoSys.GetLogDir + Board.BBSID);
1012 // Body.SaveToFile(GikoSys.GetSubjectFileName(Board.BBSID));
1013 GikoSys.ForceDirectoriesEx(ExtractFilePath(Board.GetSubjectFileName));
1014 Body.SaveToFile(Board.GetSubjectFileName);
1021 procedure TDownloadItem.SaveItemFile;
1031 if Trim(Content) = '' then
1033 FileName := ThreadItem.GetThreadFileName;
1034 GikoSys.ForceDirectoriesEx(ExtractFilePath(FileName));
1037 Body := TStringList.Create;
1039 // if FileExists(FileName) and (ResponseCode = 206) then begin
1040 if FileExists(FileName) and (State = gdsDiffComplete) then begin
1041 // Body.Text := Content;
1042 // if Body.Count > 0 then
1044 // Content := Body.Text;
1045 Body.LoadFromFile(FileName);
1046 OldCnt := Body.Count;
1047 Body.Text := Body.Text + Content;
1048 Body.SaveToFile(FileName);
1049 NewRes := Body.Count - OldCnt;
1052 Body.Text := Content;
1053 // if Body.Count > 0 then
1055 Body.SaveToFile(FileName);
1057 if ThreadItem.Title = '' then begin
1058 Res := GikoSys.DivideStrLine(Body[0]);
1059 ThreadItem.Title := Res.FTitle;
1061 ThreadItem.Size := 0;
1062 //ThreadItem.Count := 0;
1063 ThreadItem.AllResCount := 0;
1064 ThreadItem.NewResCount := 0;
1066 NewRes := Body.Count;
1073 ThreadItem.RoundDate := Now;
1074 ThreadItem.Size := ThreadItem.Size + ContentLength;
1075 ThreadItem.LastModified := LastModified;
1076 ThreadItem.Count := Cnt;
1077 ThreadItem.AllResCount := Cnt;
1078 ThreadItem.NewResCount := NewRes;
1079 ThreadItem.IsLogFile := True;
1080 ThreadItem.NewReceive := OldCnt + 1;
1081 ThreadItem.UnRead := True;
1082 ThreadItem.ParentBoard.UnRead := ThreadItem.ParentBoard.UnRead + 1;
1083 // if ThreadItem.RoundNo = 6 then
1084 // ThreadItem.RoundNo := 0;
1086 //
\88Ù
\8fí
\8fI
\97¹
\8e\9e\82Í
\83C
\83\93\83f
\83b
\83N
\83X
\82ª
\8dX
\90V
\82³
\82ê
\82È
\82¢
\82½
\82ß
\81A
\83e
\83\93\83|
\83\89\83\8a\82ð
\8dì
\90¬
\82·
\82é
\81B
1087 //
\90³
\8fí
\8fI
\97¹
\8e\9e\82É
\82Í
\8dí
\8f\9c
1088 //
\88Ù
\8fí
\8fI
\97¹
\8e\9e\82Í
\81A
\8e\9f\89ñ
\8bN
\93®
\8e\9e\82É
\83e
\83\93\83|
\83\89\83\8a\82ð
\8c©
\82Ä
\8dX
\90V
1089 ini := TMemIniFile.Create(ChangeFileExt(FileName, '.tmp'));
1091 ini.WriteDateTime('Setting', 'RoundDate', ThreadItem.RoundDate);
1092 ini.WriteDateTime('Setting', 'LastModified', ThreadItem.LastModified);
1093 ini.WriteInteger('Setting', 'Size', ThreadItem.Size);
1094 ini.WriteInteger('Setting', 'Count', ThreadItem.Count);
1095 ini.WriteInteger('Setting', 'AllResCount', ThreadItem.AllResCount);
1096 ini.WriteInteger('Setting', 'NewResCount', ThreadItem.NewResCount);
1097 ini.WriteInteger('Setting', 'NewReceive', ThreadItem.NewReceive);
1098 // ini.WriteInteger('Setting', 'RoundNo', ThreadItem.RoundNo);
1099 ini.WriteBool('Setting', 'Round', ThreadItem.Round);
1100 ini.WriteBool('Setting', 'UnRead', ThreadItem.UnRead);