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;
148 while not Terminated do begin
150 FIndy.Request.CustomHeaders.Clear;
151 FIndy.Response.Clear;
153 FIndy.Request.UserAgent := GikoSys.GetUserAgent;
154 FIndy.RecvBufferSize := Gikosys.Setting.RecvBufferSize;
155 FIndy.ProxyParams.BasicAuthentication := False;
157 Writeln('------------------------------------------------------------');
159 //FIndy.AllowCookies := False;
160 if GikoSys.Setting.ReadProxy then begin
161 if GikoSys.Setting.ProxyProtocol then
162 FIndy.ProtocolVersion := pv1_1
164 FIndy.ProtocolVersion := pv1_0;
165 FIndy.ProxyParams.ProxyServer := GikoSys.Setting.ReadProxyAddress;
166 FIndy.ProxyParams.ProxyPort := GikoSys.Setting.ReadProxyPort;
167 FIndy.ProxyParams.ProxyUsername := GikoSys.Setting.ReadProxyUserID;
168 FIndy.ProxyParams.ProxyPassword := GikoSys.Setting.ReadProxyPassword;
169 if GikoSys.Setting.ReadProxyUserID <> '' then
170 FIndy.ProxyParams.BasicAuthentication := True;
172 Writeln('
\83v
\83\8d\83L
\83V
\90Ý
\92è
\82 \82è');
173 Writeln('
\83z
\83X
\83g: ' + GikoSys.Setting.ReadProxyAddress);
174 Writeln('
\83|
\81[
\83g: ' + IntToStr(GikoSys.Setting.ReadProxyPort));
177 if GikoSys.Setting.Protocol then
178 FIndy.ProtocolVersion := pv1_1
180 FIndy.ProtocolVersion := pv1_0;
181 FIndy.ProxyParams.ProxyServer := '';
182 FIndy.ProxyParams.ProxyPort := 80;
183 FIndy.ProxyParams.ProxyUsername := '';
184 FIndy.ProxyParams.ProxyPassword := '';
186 Writeln('
\83v
\83\8d\83L
\83V
\90Ý
\92è
\82È
\82µ');
190 FIndy.Request.ContentRangeStart := 0;
191 FIndy.Request.LastModified := ZERO_DATE;
192 ResStream := TMemoryStream.Create;
195 //********************
196 //DAT or Subject
\8eæ
\93¾
197 //********************
198 Item.ResponseCode := 0;
202 if Item.DownType = gdtBoard then begin
204 Writeln('Subject
\8eæ
\93¾');
205 Writeln('URL: ' + Item.Board.GetReadCgiURL);
206 Writeln('Modified: ' + FloatToStr(Item.Board.LastModified));
208 URL := Item.Board.GetReadCgiURL;
209 Modified := Item.Board.LastModified;
210 end else if Item.DownType = gdtThread then begin
212 Writeln('DAT
\8eæ
\93¾');
213 Writeln('URL: ' + Item.ThreadItem.GetDatURL);
214 Writeln('Modified: ' + FloatToStr(Item.ThreadItem.LastModified));
216 URL := Item.ThreadItem.GetDatURL;
217 Modified := Item.ThreadItem.LastModified;
218 if Item.ThreadItem.Size > 0 then begin
220 Writeln('RangeStart: ' + IntToStr(Item.ThreadItem.Size));
222 //
\82 \82Ú
\81[
\82ñ
\83`
\83F
\83b
\83N
\82Ì
\82½
\82ß
\82P
\83o
\83C
\83g
\91O
\82©
\82ç
\8eæ
\93¾
223 RangeStart := Item.ThreadItem.Size;
228 DownloadResult := DatDownload(Item.DownType, URL, Modified, RangeStart, AdjustLen);
230 Writeln('ResponseCode: ' + IntToStr(FIndy.ResponseCode));
232 if Item.DownType = gdtThread then begin
233 if Item.ResponseCode = 416 then begin
235 DownloadResult := True;
236 end else if DownloadResult and (AdjustLen = -1) and (Item.Content[1] <> #10) then
240 if Trim(FIndy.Response.RawHeaders.Values['Date']) <> '' then begin
241 if Item.DownType = gdtBoard then
242 Item.Board.LastGetTime := MonaUtils.DateStrToDateTime(FIndy.Response.RawHeaders.Values['Date'])
244 Item.ThreadItem.ParentBoard.LastGetTime := MonaUtils.DateStrToDateTime(FIndy.Response.RawHeaders.Values['Date']);
247 if DownloadResult then begin
249 Writeln('Date:' + FIndy.Response.RawHeaders.Values['Date']);
253 Writeln('
\82 \82Ú
\81[
\82ñ
\8c\9f\8fo');
255 ATitle := Item.ThreadItem.Title;
257 ATitle := '
\81i
\96¼
\8fÌ
\95s
\96¾
\81j';
258 //
\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¾
261 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 + ']';
263 if FileExists(ChangeFileExt(Item.FThreadItem.GetThreadFileName,'.NG')) = true then
264 DeleteFile(ChangeFileExt(Item.FThreadItem.GetThreadFileName,'.NG'));
265 if Assigned(OnDownloadMsg) then
266 Synchronize(FireDownloadMsg);
267 if not DatDownload(Item.DownType, URL, ZERO_DATE, RangeStart, AdjustLen) then
268 Item.State := gdsError;
270 Writeln('
\82 \82Ú
\81[
\82ñ
\8dÄ
\8eæ
\93¾
\8cã');
271 Writeln('ResponseCode: ' + IntToStr(Item.ResponseCode));
273 end else if (Item.DownType = gdtThread) and (AdjustLen = -1) and (Item.Content[1] = #10) then begin
274 //
\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
275 Item.Content := Copy(Item.Content, 2, Length(Item.Content));
278 Item.State := gdsError;
279 if (Item.DownType = gdtBoard) and (Item.ResponseCode = 302) then begin
280 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';
282 if Assigned(OnDownloadMsg) then
283 Synchronize(FireDownloadMsg);
287 //********************
289 //********************
290 if (Item.DownType = gdtThread) and (Item.ResponseCode = 302) then begin
292 Writeln('dat.gz
\8eæ
\93¾');
294 ATitle := Item.ThreadItem.Title;
296 ATitle := '
\81i
\96¼
\8fÌ
\95s
\96¾
\81j';
297 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 + ']';
299 if Assigned(OnDownloadMsg) then
300 Synchronize(FireDownloadMsg);
301 URL := Item.ThreadItem.GetDatgzURL;
302 Modified := Item.ThreadItem.LastModified;
305 if not DatDownload(Item.DownType, URL, Modified, RangeStart, AdjustLen) then
306 Item.State := gdsError;
308 Writeln('ResponseCode: ' + IntToStr(Item.ResponseCode));
312 //********************
314 //********************
316 if (Item.DownType = gdtThread) and (Item.ResponseCode = 302) then begin
317 ATitle := Item.ThreadItem.Title;
319 ATitle := '
\81i
\96¼
\8fÌ
\95s
\96¾
\81j';
320 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 + ']';
322 if Assigned(OnDownloadMsg) then
323 Synchronize(FireDownloadMsg);
324 URL := Item.ThreadItem.GetOldDatgzURL;
325 Modified := Item.ThreadItem.LastModified;
328 if not DatDownload(Item.DownType, URL, Modified, RangeStart, AdjustLen) then
329 Item.State := gdsError;
333 //********************
334 //offlaw.cgi
\82Å
\8eæ
\93¾
335 //********************
337 Synchronize(GetSessionID);
338 if (Item.DownType = gdtThread) and (Item.ResponseCode = 302) and (FSessionID <> '') then begin
340 Writeln('offlaw.cgi
\82Å
\8eæ
\93¾');
342 ATitle := Item.ThreadItem.Title;
344 ATitle := '
\81i
\96¼
\8fÌ
\95s
\96¾
\81j';
345 FMsg := '
\81\9adat.gz
\82ª
\91¶
\8dÝ
\82µ
\82È
\82¢
\82½
\82ßofflaw.cgi
\82ð
\97\98\97p
\82µ
\82Ü
\82· - [' + ATitle + ']';
347 if Assigned(OnDownloadMsg) then
348 Synchronize(FireDownloadMsg);
349 URL := Item.ThreadItem.GetOfflawCgiURL(FSessionID);
350 Modified := Item.ThreadItem.LastModified;
353 if not DatDownload(Item.DownType, URL, Modified, RangeStart, AdjustLen) then begin
355 Writeln('ResponseCode: ' + IntToStr(Item.ResponseCode));
357 Item.State := gdsError;
359 if (Item.DownType = gdtThread) and (Item.ResponseCode = 302) then begin
360 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';
362 if Assigned(OnDownloadMsg) then
363 Synchronize(FireDownloadMsg);
367 CgiStatus := ParseCgiStatus(Item.Content);
369 Writeln('ResponseCode: ' + IntToStr(Item.ResponseCode));
371 case CgiStatus.FStatus of
374 Writeln('CGIStatus: OK');
376 Item.ResponseCode := 200;
377 Item.Content := DeleteStatusLine(Item.Content);
378 Item.ContentLength := CgiStatus.FSize;
381 //
\8d¡
\82Í
\82 \82è
\82¦
\82È
\82¢
383 Writeln('CGIStatus: 206');
385 Item.ResponseCode := 206;
386 Item.Content := DeleteStatusLine(Item.Content);
387 Item.ContentLength := CgiStatus.FSize;
391 Writeln('CGIStatus: 404(ERROR)');
393 Item.ResponseCode := 404;
394 Item.State := gdsError;
395 Item.ErrText := CgiStatus.FErrText;
398 if (Item.ResponseCode = 404) and (AnsiPos('
\89ß
\8b\8e\83\8d\83O
\91q
\8cÉ
\82Å
\94
\8c©', Item.ErrText) <> 0) then begin
400 Writeln('
\89ß
\8b\8e\83\8d\83O
\8eæ
\93¾');
402 ATitle := Item.ThreadItem.Title;
404 ATitle := '
\81i
\96¼
\8fÌ
\95s
\96¾
\81j';
405 FMsg := '
\81\9a\89ß
\8b\8e\83\8d\83O
\91q
\8cÉ
\82Å
\94
\8c© - [' + ATitle + ']';
407 if Assigned(OnDownloadMsg) then
408 Synchronize(FireDownloadMsg);
409 Idx := Pos(' ', Item.ErrText);
410 if Idx <> 0 then begin
411 URL := Copy(Item.ErrText, Idx + 1, Length(Item.ErrText));
412 if Pos('../', URL) = 1 then
413 URL := Copy(URL, 4, Length(URL));
414 URL := GikoSys.UrlToServer(Item.ThreadItem.ParentBoard.URL) + URL;
415 Modified := Item.ThreadItem.LastModified;
418 if not DatDownload(Item.DownType, URL, Modified, RangeStart, AdjustLen) then
419 Item.State := gdsError;
421 Writeln('ResponseCode: ' + IntToStr(Item.ResponseCode));
427 if (Item.DownType = gdtThread) and (Item.ResponseCode = 302) and (FSessionID = '') then begin
429 Writeln('
\83\8d\83O
\83C
\83\93\82³
\82ê
\82Ä
\82È
\82¢
\82Ì
\82Å
\89ß
\8b\8e\83\8d\83O
\8eæ
\93¾
\95s
\89Â');
431 ATitle := Item.ThreadItem.Title;
433 ATitle := '
\81i
\96¼
\8fÌ
\95s
\96¾
\81j';
434 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 + ']';
436 if Assigned(OnDownloadMsg) then
437 Synchronize(FireDownloadMsg);
442 if (Item.DownType = gdtThread) and (Item.ResponseCode = 302) then begin
443 ATitle := Item.ThreadItem.Title;
445 ATitle := '
\81i
\96¼
\8fÌ
\95s
\96¾
\81j';
446 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 + ']';
448 if Assigned(OnDownloadMsg) then
449 Synchronize(FireDownloadMsg);
450 //URL := GikoSys.GetURL( Item.ThreadItem.ParentBoard.BBSID, Item.ThreadItem.FileName );
451 URL := 'http://www.google.co.jp/search?q=cache:' + GikoSys.GetURL( Item.ThreadItem.ParentBoard.BBSID, Item.ThreadItem.FileName );
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 Item.ResponseCode := 206;
461 Item.Content := Copy( Item.Content, Pos( '<dt>', Item.Content ) + Length( '<dt>' ), Length( Item.Content ) );
462 Item.Content := StringReplace( Item.Content, '<dt>', '<>' + #13#10, [rfReplaceAll] );
463 Item.Content := StringReplace( Item.Content, '<a href="mailto:', '', [rfReplaceAll] );
464 Item.Content := StringReplace( Item.Content, '"><b>', '<>', [rfReplaceAll] );
465 Item.Content := StringReplace( Item.Content, '<b>', '<>', [rfReplaceAll] );
466 Item.Content := StringReplace( Item.Content, '</b></a>', '<>', [rfReplaceAll] );
467 Item.Content := StringReplace( Item.Content, '</b>', '<>', [rfReplaceAll] );
468 Item.Content := StringReplace( Item.Content, '<dd>', '<>', [rfReplaceAll] );
473 case Item.ResponseCode of
474 200: Item.State := gdsComplete;
475 206: Item.State := gdsDiffComplete;
476 304: Item.State := gdsNotModify;
478 Item.State := gdsError;
481 //
\96³
\82¢
\82Æ
\8ev
\82¤
\82¯
\82Ç
\81B
\81B
\81B
482 if (Item.ResponseCode in [200, 206]) and (Item.Content = '') then
483 Item.State := gdsError;
484 Item.LastModified := FIndy.Response.LastModified;
485 //
\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é
486 Item.ContentLength := FIndy.Response.ContentLength + AdjustLen;
489 FIndy.Get(URL, ResStream);
490 Item.Content := GikoSys.GzipDecompress(ResStream, FIndy.Response.ContentEncoding);
491 if (Item.DownType = gdtThread) and (AdjustLen = -1) and (Item.Content[1] <> #10) then begin
492 //
\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¾
493 //
\82±
\82±
\82Å
\83\81\83b
\83Z
\81[
\83W
\95\
\8e¦
\83C
\83x
\83\93\83g
495 FMsg := '
\81u
\82 \82Ú
\81[
\82ñ
\81v
\82ð
\8c\9f\8fo
\82µ
\82½
\82Ì
\82Å
\8dÄ
\8eæ
\93¾
\82ð
\8ds
\82¢
\82Ü
\82·';
496 if Assigned(OnDownloadMsg) then
497 Synchronize(FireDownloadMsg);
498 FIndy.Request.ContentRangeStart := 0;
499 FIndy.Request.ContentRangeEnd := 0;
502 FIndy.Get(URL, ResStream);
503 Item.Content := GikoSys.GzipDecompress(ResStream, FIndy.Response.ContentEncoding);
504 end else if (Item.DownType = gdtThread) and (AdjustLen = -1) and (Item.Content[1] = #10) then begin
505 //
\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
506 Item.Content := Copy(Item.Content, 2, Length(Item.Content));
509 Item.State := gdsError;
511 Item.ResponseCode := FIndy.ResponseCode;
516 FIndy.Get(URL, ResStream);
517 Item.Content := GikoSys.GzipDecompress(ResStream, FIndy.Response.ContentEncoding);
519 Item.State := gdsError;
522 CgiStatus := ParseCgiStatus(Item.Content);
523 if CgiStatus.FStatus = gcsOK then begin
524 if CgiStatus.FSize = 0 then
525 Item.State := gdsNotModify
526 else if Item.DownType = gdtBoard then
527 Item.State := gdsComplete
529 Item.State := gdsDiffComplete;
530 end else if CgiStatus.FStatus = gcsINCR then begin
531 Item.State := gdsComplete;
532 end else if CgiStatus.FStatus = gcsERR then begin
533 Item.State := gdsError;
534 Item.ErrText := CgiStatus.FErrText;
536 Item.ContentLength := CgiStatus.FSize;
539 Item.State := gdsError;
541 //Item.ResponseCode := FIndy.ResponseCode;
543 Item.State := gdsAbort;
545 if Assigned(OnDownloadEnd) then
546 Synchronize(FireDownloadEnd);
549 if Terminated then Break;
554 function TDownloadThread.CgiDownload(ItemType: TGikoDownloadType; URL: string; Modified: TDateTime): Boolean;
556 ResponseCode: Integer;
557 ResStream: TMemoryStream;
560 FIndy.Request.ContentRangeStart := 0;
561 FIndy.Request.ContentRangeEnd := 0;
563 FIndy.Request.CustomHeaders.Clear;
564 if (Modified <> 0) and (Modified <> ZERO_DATE) then begin
565 FIndy.Request.LastModified := modified - OffsetFromUTC;
567 FIndy.Request.AcceptEncoding := '';
568 FIndy.Request.Accept := 'text/html';
569 ResStream := TMemoryStream.Create;
574 Writeln('URL: ' + URL);
576 FIndy.Get(URL, ResStream);
577 Item.Content := GikoSys.GzipDecompress(ResStream, FIndy.Response.ContentEncoding);
578 Item.LastModified := FIndy.Response.LastModified;
579 //
\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é
580 Item.ContentLength := Length(Item.Content);
581 //
\96³
\82¢
\82Æ
\8ev
\82¤
\82¯
\82Ç
\81B
\81B
\81B
582 if Item.Content = '' then
587 Writeln('
\8eæ
\93¾
\82Å
\97á
\8aO
\82È
\82µ');
589 ResponseCode := FIndy.ResponseCode;
591 on E: EIdSocketError do begin
593 Item.LastModified := ZERO_DATE;
594 Item.ContentLength := 0;
595 Item.ErrText := E.Message;
598 Screen.Cursor := crDefault;
600 on E: EIdConnectException do begin
602 Item.LastModified := ZERO_DATE;
603 Item.ContentLength := 0;
604 Item.ErrText := E.Message;
607 Screen.Cursor := crDefault;
609 on E: Exception do begin
611 Writeln('
\8eæ
\93¾
\82Å
\97á
\8aO
\82 \82è');
612 Writeln('E.Message: ' + E.Message);
615 Item.LastModified := ZERO_DATE;
616 Item.ContentLength := 0;
617 Item.ErrText := E.Message;
618 ResponseCode := FIndy.ResponseCode;
620 Screen.Cursor := crDefault;
624 if (Item.ContentLength = 0) and (ResponseCode = 206) then
625 Item.ResponseCode := 304
627 Item.ResponseCode := ResponseCode;
632 function TDownloadThread.DatDownload(ItemType: TGikoDownloadType; URL: string; Modified: TDateTime; RangeStart: Integer; AdjustLen: Integer): Boolean;
634 ResponseCode: Integer;
635 ResStream: TMemoryStream;
638 if (ItemType = gdtThread) and (RangeStart > 0) then begin
639 // if (ItemType = gdtThread) and (Item.ThreadItem.Size > 0) then begin
640 // FIndy.Request.ContentRangeStart := Item.ThreadItem.Size + AdjustLen;
641 FIndy.Request.ContentRangeStart := RangeStart + AdjustLen;
642 FIndy.Request.ContentRangeEnd := 0;
644 FIndy.Request.ContentRangeStart := 0;
645 FIndy.Request.ContentRangeEnd := 0;
648 FIndy.Request.CustomHeaders.Clear;
649 FIndy.Request.CacheControl := 'no-cache';
650 FIndy.Request.CustomHeaders.Add('Pragma: no-cache');
651 if (Modified <> 0) and (Modified <> ZERO_DATE) then begin
652 FIndy.Request.LastModified := modified - OffsetFromUTC;
653 //FIndy.Request.CustomHeaders.Add('If-Modified-Since: ' + RFC1123_Date(modified - OffsetFromUTC) + ' GMT');
655 // FIndy.Request.AcceptEncoding := 'gzip';
656 if RangeStart = 0 then
657 FIndy.Request.AcceptEncoding := 'gzip'
659 FIndy.Request.AcceptEncoding := '';
660 ResStream := TMemoryStream.Create;
665 Writeln('URL: ' + URL);
667 FIndy.Get(URL, ResStream);
668 Item.Content := GikoSys.GzipDecompress(ResStream, FIndy.Response.ContentEncoding);
669 Item.LastModified := FIndy.Response.LastModified;
670 //
\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é
671 // Item.ContentLength := FIndy.Response.ContentLength + AdjustLen;
672 Item.ContentLength := Length(Item.Content) + AdjustLen;
673 //
\96³
\82¢
\82Æ
\8ev
\82¤
\82¯
\82Ç
\81B
\81B
\81B
674 // if (FIndy.ResponseCode in [200, 206]) and (Item.Content = '') then
676 if Item.Content = '' then
681 Writeln('
\8eæ
\93¾
\82Å
\97á
\8aO
\82È
\82µ');
683 ResponseCode := FIndy.ResponseCode;
685 on E: EIdSocketError do begin
687 Item.LastModified := ZERO_DATE;
688 Item.ContentLength := 0;
689 Item.ErrText := E.Message;
692 Screen.Cursor := crDefault;
694 on E: EIdConnectException do begin
696 Item.LastModified := ZERO_DATE;
697 Item.ContentLength := 0;
698 Item.ErrText := E.Message;
701 Screen.Cursor := crDefault;
703 on E: Exception do begin
705 Writeln('
\8eæ
\93¾
\82Å
\97á
\8aO
\82 \82è');
706 Writeln('E.Message: ' + E.Message);
709 Item.LastModified := ZERO_DATE;
710 Item.ContentLength := 0;
711 Item.ErrText := E.Message;
712 ResponseCode := FIndy.ResponseCode;
714 Screen.Cursor := crDefault;
718 if (Item.ContentLength = 0) and (ResponseCode = 206) then
719 Item.ResponseCode := 304
721 Item.ResponseCode := ResponseCode;
726 procedure TDownloadThread.FireDownloadEnd;
728 OnDownloadEnd(self, Item);
731 procedure TDownloadThread.FireDownloadMsg;
733 OnDownloadMsg(Self, Item, FMsg, FIcon);
736 procedure TDownloadThread.GetSessionID;
738 FSessionID := GikoSys.Dolib.SessionID;
741 procedure TDownloadThread.Abort;
744 FIndy.DisconnectSocket;
747 procedure TDownloadThread.WorkBegin(Sender: TObject; AWorkMode: TWorkMode; const AWorkCountMax: Integer);
749 if Assigned(OnWorkBegin) then
750 OnWorkBegin(Sender, AWorkMode, AWorkCountMax, FNumber);
753 procedure TDownloadThread.WorkEnd(Sender: TObject; AWorkMode: TWorkMode);
755 if Assigned(OnWorkEnd) then
756 OnWorkEnd(Sender, AWorkMode, FNumber);
759 procedure TDownloadThread.Work(Sender: TObject; AWorkMode: TWorkMode; const AWorkCount: Integer);
761 if Assigned(OnWork) then
762 OnWork(Sender, AWorkMode, AWorkCount, FNumber);
765 function TDownloadThread.ParseCgiStatus(Content: string): TCgiStatus;
774 // [+OK]
\82Ì
\8fê
\8d\87\82Í
\8d·
\95ª
775 // [-INCR] (Incorrect)
\82Ì
\8fê
\8d\87\82Í
\82·
\82×
\82Ä
\82Ì
\83f
\81[
\83^
776 // [-ERR (
\83e
\83L
\83X
\83g)]
\82Ì
\8fê
\8d\87\82Í
\82È
\82ñ
\82©
\83G
\83\89\81[
777 //
\97á
\81F+OK 23094/512K
779 // -ERR
\82»
\82ñ
\82È
\94Â
\82È
\82¢
\82Å
\82·
780 Idx := AnsiPos(#10, Content);
781 StatusLine := Copy(Content, 0, Idx);
783 Idx := AnsiPos(' ', Content);
784 Status := Copy(StatusLine, 0, Idx - 1);
785 Line := Copy(StatusLine, Idx + 1, Length(StatusLine));
787 // Idx := AnsiPos('/', Line);
788 if Trim(Status) = '-ERR' then
791 Size := Copy(Line, 0, Idx - 1);
793 if Trim(Status) = '+OK' then
794 Result.FStatus := gcsOK
795 else if Trim(Status) = '-INCR' then
796 Result.FStatus := gcsINCR
797 else if Trim(Status) = '-ERR' then begin
798 Result.FStatus := gcsERR;
799 Result.FErrText := Msg;
806 Result.FStatus := gcsERR;
807 Result.FErrText := '
\83G
\83\89\81[
\82È
\82ñ
\82¾
\82¯
\82Ç
\81A
\82æ
\82
\95ª
\82©
\82ç
\82È
\82¢
\83G
\83\89\81[';
812 if GikoSys.IsNumeric(Size) then
813 Result.FSize := StrToInt(Size)
816 Result.FStatus := gcsERR;
817 Result.FErrText := '
\83X
\83e
\81[
\83^
\83X
\89ð
\90Í
\8e¸
\94s[' + StatusLine + ']';
821 //
\8eè
\94²
\82«
\82È
\8f\88\97\9d\82Å1
\8ds
\96Ú
\82ð
\8fÁ
\82·
822 function TDownloadThread.DeleteStatusLine(Content: string): string;
826 SList := TStringList.Create;
828 SList.Text := Content;
829 if SList.Count > 1 then
831 Result := SList.Text;
837 procedure TDownloadItem.SaveListFile;
841 NewItem: TThreadItem;
843 // SaveCount: Integer;
848 NewList := TList.Create;
849 Body := TStringList.Create;
851 //
\83_
\83E
\83\93\83\8d\81[
\83h
\93ú
\8e\9e\90Ý
\92è
\81i
\83\8d\81[
\83J
\83\8b\93ú
\8e\9e\81j
852 Board.RoundDate := Now;
853 //
\83T
\81[
\83o
\8fã
\83t
\83@
\83C
\83\8b\82Ì
\8dX
\90V
\8e\9e\8d\8f\90Ý
\92è
854 Board.LastModified := LastModified;
856 //
\90V
\82µ
\82¢
\83\8a\83X
\83g
\82ð
\8dì
\90¬
\82·
\82é
857 //
\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Á
858 //
\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¬
859 Body.Text := Content;
861 for i := 0 to Body.Count - 1 do begin
862 //if i = 0 then Continue; //
\82P
\8ds
\96Ú
\82Í
\83X
\83e
\81[
\83^
\83X
\8ds
\82Ì
\82½
\82ß
\8f\88\97\9d\82È
\82µ
864 Rec := GikoSys.DivideSubject(Body[i]);
865 Rec.FFileName := Trim(Rec.FFileName);
866 if (Rec.FTitle = '') and (Rec.FCount = 0) then Continue;
868 index := Board.GetIndex(Rec.FFileName);
869 if index = -1 then begin
870 //
\90V
\82µ
\82¢
\83X
\83\8c\83b
\83h
871 NewItem := TThreadItem.Create;
872 NewItem.FileName := Rec.FFileName;
873 NewItem.Title := Rec.FTitle;
874 // NewItem.Count := Rec.FCount;
875 NewItem.AllResCount := Rec.FCount;
876 NewItem.ParentBoard := Board;
877 NewItem.No := NumCount;
878 NewItem.RoundDate := ZERO_DATE;
879 NewItem.LastModified := ZERO_DATE;
880 NewItem.AgeSage := gasNew;
881 NewList.Add(NewItem);
883 //Board.Items[index].Count := Count;
884 //Board.Items[index].Count := Rec.FCount;
885 if Board.Items[index].No > NumCount then
886 Board.Items[index].AgeSage := gasAge
887 else if Board.Items[index].AllResCount < Rec.FCount then
888 Board.Items[index].AgeSage := gasSage
890 Board.Items[index].AgeSage := gasNone;
893 Board.Items[index].No := NumCount;
894 Board.Items[index].AllResCount := Rec.FCount;
895 // if not Board.Items[index].IsLogFile then
896 // Board.Items[index].Count := Rec.FCount;
897 NewList.Add(Board.Items[index]);
898 Board.DeleteList(index);
902 //
\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Á
903 for i := 0 to Board.Count - 1 do begin
904 if Board.Items[i].IsLogFile then begin
906 Board.Items[i].No := NumCount;
907 Board.Items[i].AllResCount := Board.Items[i].Count;
908 Board.Items[i].NewResCount := 0;
909 Board.Items[i].AgeSage := gasNone;
910 NewList.Add(Board.Items[i]);
914 //
\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
915 for i := Board.Count - 1 downto 0 do
918 //
\90V
\82µ
\82¢
\83\8a\83X
\83g
\82ð
\83{
\81[
\83h
\83I
\83u
\83W
\83F
\83N
\83g
\82É
\92Ç
\89Á
919 for i := 0 to NewList.Count - 1 do
920 Board.Add(TThreadItem(NewList[i]));
922 //
\83\8a\83X
\83g(subject.txt)
\82ð
\95Û
\91¶
923 // GikoSys.ForceDirectoriesEx(GikoSys.GetLogDir + Board.BBSID);
924 // Body.SaveToFile(GikoSys.GetSubjectFileName(Board.BBSID));
925 GikoSys.ForceDirectoriesEx(ExtractFilePath(Board.GetSubjectFileName));
926 Body.SaveToFile(Board.GetSubjectFileName);
933 {procedure TDownloadItem.SaveListFile;
937 NewItem: TThreadItem;
939 // SaveCount: Integer;
944 NewList := TList.Create;
945 Body := TStringList.Create;
947 //
\8f\84\89ñ
\93ú
\8e\9e\90Ý
\92è
948 Board.RoundDate := Now;
949 //
\83T
\81[
\83o
\8fã
\83t
\83@
\83C
\83\8b\82Ì
\8dX
\90V
\8e\9e\8d\8f\90Ý
\92è
950 Board.LastModified := LastModified;
952 //
\83\8a\83X
\83g
\95Û
\91¶
\8c\8f\90\94\8eæ
\93¾
953 //SaveCount := MaxInt;
955 //
\8cÃ
\82¢
\83\8a\83X
\83g
\82©
\82ç
\83\8d\83O
\96³
\82µ
\83A
\83C
\83e
\83\80\82ð
\8dí
\8f\9c
956 for i := Board.Count - 1 downto 0 do
957 if not Board.Items[i].IsLogFile then
960 //
\90V
\82µ
\82¢
\83\8a\83X
\83g
\82ð
\8dì
\90¬
\82·
\82é
961 //
\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Á
962 //
\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¬
963 Body.Text := Content;
964 // Loop := Min(Body.Count, SaveCount);
966 // for i := 0 to Loop - 1 do begin
967 for i := 0 to Body.Count - 1 do begin
968 if i = 0 then Continue; //
\82P
\8ds
\96Ú
\82Í
\83X
\83e
\81[
\83^
\83X
\8ds
\82Ì
\82½
\82ß
\8f\88\97\9d\82È
\82µ
970 Rec := GikoSys.DivideSubject(Body[i]);
971 if (Rec.FTitle = '') and (Rec.FCount = 0) then Continue;
973 index := Board.GetIndex(Rec.FFileName);
974 if index = -1 then begin
975 NewItem := TThreadItem.Create;
976 NewItem.FileName := Rec.FFileName;
977 NewItem.Title := Rec.FTitle;
978 NewItem.Count := Rec.FCount;
979 NewItem.ParentBoard := Board;
980 NewItem.No := NumCount;
981 NewItem.RoundDate := ZERO_DATE;
982 NewItem.LastModified := ZERO_DATE;
983 NewList.Add(NewItem);
985 //Board.Items[index].Count := Count;
986 Board.Items[index].No := NumCount;
987 NewList.Add(Board.Items[index]);
988 Board.DeleteList(index);
992 //
\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Á
993 for i := 0 to Board.Count - 1 do begin
995 Board.Items[i].No := NumCount;
996 NewList.Add(Board.Items[i]);
999 //
\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
1000 for i := Board.Count - 1 downto 0 do
1001 Board.DeleteList(i);
1003 //
\90V
\82µ
\82¢
\83\8a\83X
\83g
\82ð
\83{
\81[
\83h
\83I
\83u
\83W
\83F
\83N
\83g
\82É
\92Ç
\89Á
1004 for i := 0 to NewList.Count - 1 do
1005 Board.Add(TThreadItem(NewList[i]));
1007 //
\83\8a\83X
\83g(subject.txt)
\82ð
\95Û
\91¶
1008 // GikoSys.ForceDirectoriesEx(GikoSys.GetLogDir + Board.BBSID);
1009 // Body.SaveToFile(GikoSys.GetSubjectFileName(Board.BBSID));
1010 GikoSys.ForceDirectoriesEx(ExtractFilePath(Board.GetSubjectFileName));
1011 Body.SaveToFile(Board.GetSubjectFileName);
1018 procedure TDownloadItem.SaveItemFile;
1028 if Trim(Content) = '' then
1030 FileName := ThreadItem.GetThreadFileName;
1031 GikoSys.ForceDirectoriesEx(ExtractFilePath(FileName));
1034 Body := TStringList.Create;
1036 // if FileExists(FileName) and (ResponseCode = 206) then begin
1037 if FileExists(FileName) and (State = gdsDiffComplete) then begin
1038 // Body.Text := Content;
1039 // if Body.Count > 0 then
1041 // Content := Body.Text;
1042 Body.LoadFromFile(FileName);
1043 OldCnt := Body.Count;
1044 Body.Text := Body.Text + Content;
1045 Body.SaveToFile(FileName);
1046 NewRes := Body.Count - OldCnt;
1049 Body.Text := Content;
1050 // if Body.Count > 0 then
1052 Body.SaveToFile(FileName);
1054 if ThreadItem.Title = '' then begin
1055 Res := GikoSys.DivideStrLine(Body[0]);
1056 ThreadItem.Title := Res.FTitle;
1058 ThreadItem.Size := 0;
1059 //ThreadItem.Count := 0;
1060 ThreadItem.AllResCount := 0;
1061 ThreadItem.NewResCount := 0;
1063 NewRes := Body.Count;
1070 ThreadItem.RoundDate := Now;
1071 ThreadItem.Size := ThreadItem.Size + ContentLength;
1072 ThreadItem.LastModified := LastModified;
1073 ThreadItem.Count := Cnt;
1074 ThreadItem.AllResCount := Cnt;
1075 ThreadItem.NewResCount := NewRes;
1076 ThreadItem.IsLogFile := True;
1077 ThreadItem.NewReceive := OldCnt + 1;
1078 ThreadItem.UnRead := True;
1079 ThreadItem.ParentBoard.UnRead := ThreadItem.ParentBoard.UnRead + 1;
1080 // if ThreadItem.RoundNo = 6 then
1081 // ThreadItem.RoundNo := 0;
1083 //
\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
1084 //
\90³
\8fí
\8fI
\97¹
\8e\9e\82É
\82Í
\8dí
\8f\9c
1085 //
\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
1086 ini := TMemIniFile.Create(ChangeFileExt(FileName, '.tmp'));
1088 ini.WriteDateTime('Setting', 'RoundDate', ThreadItem.RoundDate);
1089 ini.WriteDateTime('Setting', 'LastModified', ThreadItem.LastModified);
1090 ini.WriteInteger('Setting', 'Size', ThreadItem.Size);
1091 ini.WriteInteger('Setting', 'Count', ThreadItem.Count);
1092 ini.WriteInteger('Setting', 'AllResCount', ThreadItem.AllResCount);
1093 ini.WriteInteger('Setting', 'NewResCount', ThreadItem.NewResCount);
1094 ini.WriteInteger('Setting', 'NewReceive', ThreadItem.NewReceive);
1095 // ini.WriteInteger('Setting', 'RoundNo', ThreadItem.RoundNo);
1096 ini.WriteBool('Setting', 'Round', ThreadItem.Round);
1097 ini.WriteBool('Setting', 'UnRead', ThreadItem.UnRead);