OSDN Git Service

・ツールバーの ComboBox で専用のポップアップが出なくなっていたバグを修正。
[gikonavigoeson/gikonavi.git] / ItemDownload.pas
1 unit ItemDownload;
2
3 interface
4
5 uses
6         SysUtils, Classes, ComCtrls, Controls, Forms, IdHTTP,
7         {HTTPApp,} YofUtils, IdGlobal, IdException, IdComponent, IniFiles, {DateUtils,}
8         GikoSystem, BoardGroup, MonaUtils;
9
10 type
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);
16
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;
22
23         TCgiStatus = record
24                 FStatus: TGikoCgiStatus;
25                 FSize: Integer;
26                 FErrText: string;
27         end;
28
29
30         TDownloadThread = class(TThread)
31         private
32                 FIndy: TIdHttp;
33                 FItem: TDownloadItem;
34                 FNumber: Integer;
35                 FAbort: Boolean;
36                 FMsg: string;
37                 FIcon: TGikoMessageIcon;
38                 FSessionID: string;
39                 FOnWork: TGikoWorkEvent;
40                 FOnWorkBegin: TGikoWorkBeginEvent;
41                 FOnWorkEnd: TGikoWorkEndEvent;
42                 FOnDownloadEnd: TDownloadEndEvent;
43                 FOnDownloadMsg: TDownloadMsgEvent;
44
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 DatDownload(ItemType: TGikoDownloadType; URL: string; Modified: TDateTime; RangeStart: Integer; AdjustLen: Integer): Boolean;
53                 function DeleteStatusLine(Content: string): string;
54         protected
55                 procedure Execute; override;
56         public
57                 property Item: TDownloadItem read FItem write FItem;
58                 property Number: Integer read FNumber write FNumber;
59                 constructor Create(CreateSuspended: Boolean);
60                 destructor Destroy; override;
61                 procedure Abort;
62                 property OnWork: TGikoWorkEvent read FOnWork write FOnWork;
63                 property OnWorkBegin: TGikoWorkBeginEvent read FOnWorkBegin write FOnWorkBegin;
64                 property OnWorkEnd: TGikoWorkEndEvent read FOnWorkEnd write FOnWorkEnd;
65                 property OnDownloadEnd: TDownloadEndEvent read FOnDownloadEnd write FOnDownloadEnd;
66                 property OnDownloadMsg: TDownloadMsgEvent read FOnDownloadMsg write FOnDownloadMsg;
67         end;
68
69         TDownloadItem = class(TObject)
70         private
71                 FDownType: TGikoDownloadType;
72                 FBoard: TBoard;
73                 FThreadItem: TThreadItem;
74
75                 FContentLength: Integer;
76                 FLastModified: TDateTime;
77                 FContent: string;
78                 FResponseCode: Smallint;
79                 FState: TGikoDownloadState;
80                 FErrText: string;
81         public
82                 procedure SaveListFile;
83                 procedure SaveItemFile;
84
85                 property DownType: TGikoDownloadType read FDownType write FDownType;
86                 property Board: TBoard read FBoard write FBoard;
87                 property ThreadItem: TThreadItem read FThreadItem write FThreadItem;
88
89                 property ContentLength: Integer read FContentLength write FContentLength;
90                 property LastModified: TDateTime read FLastModified write FLastModified;
91                 property Content: string read FContent write FContent;
92                 property ResponseCode: Smallint read FResponseCode write FResponseCode;
93                 property State: TGikoDownloadState read FState write FState;
94                 property ErrText: string read FErrText write FErrText;
95         end;
96
97 implementation
98
99 constructor TDownloadThread.Create(CreateSuspended: Boolean);
100 begin
101         inherited Create(CreateSuspended);
102         FIndy := TIdHttp.Create(nil);
103
104         FIndy.OnWorkBegin := WorkBegin;
105         FIndy.OnWorkEnd := WorkEnd;
106         FIndy.OnWork := Work;
107 end;
108
109 destructor TDownloadThread.Destroy;
110 begin
111         FIndy.Free;
112         inherited;
113 end;
114
115 function RFC1123_Date(aDate : TDateTime) : String;
116 const
117          StrWeekDay : String = 'MonTueWedThuFriSatSun';
118          StrMonth   : String = 'JanFebMarAprMayJunJulAugSepOctNovDec';
119 var
120          Year, Month, Day       : Word;
121          Hour, Min,   Sec, MSec : Word;
122          DayOfWeek              : Word;
123 begin
124          DecodeDate(aDate, Year, Month, Day);
125          DecodeTime(aDate, Hour, Min,   Sec, MSec);
126          DayOfWeek := ((Trunc(aDate) - 2) mod 7);
127          Result := Copy(StrWeekDay, 1 + DayOfWeek * 3, 3) + ', ' +
128                                                  Format('%2.2d %s %4.4d %2.2d:%2.2d:%2.2d',
129                                                                                 [Day, Copy(StrMonth, 1 + 3 * (Month - 1), 3),
130                                                                                  Year, Hour, Min, Sec]);
131 end;
132
133 procedure TDownloadThread.Execute;
134 var
135         ResStream: TMemoryStream;
136
137         URL: string;
138         CgiStatus: TCgiStatus;
139         Modified: TDateTime;
140         RangeStart: Integer;
141         AdjustLen: Integer;
142         Idx: Integer;
143         ATitle: string;
144         DownloadResult: Boolean;
145         Abone: Boolean;
146 begin
147         while not Terminated do begin
148                 FAbort := False;
149                 FIndy.Request.CustomHeaders.Clear;
150                 FIndy.Response.Clear;
151                 FIndy.Request.Clear;
152                 FIndy.Request.UserAgent := GikoSys.GetUserAgent;
153                 FIndy.RecvBufferSize := Gikosys.Setting.RecvBufferSize;
154                 FIndy.ProxyParams.BasicAuthentication := False;
155                 {$IFDEF DEBUG}
156                 Writeln('------------------------------------------------------------');
157                 {$ENDIF}
158                 //FIndy.AllowCookies := False;
159                 if GikoSys.Setting.ReadProxy then begin
160                         if GikoSys.Setting.ProxyProtocol then
161                                 FIndy.ProtocolVersion := pv1_1
162                         else
163                                 FIndy.ProtocolVersion := pv1_0;
164                         FIndy.ProxyParams.ProxyServer := GikoSys.Setting.ReadProxyAddress;
165                         FIndy.ProxyParams.ProxyPort := GikoSys.Setting.ReadProxyPort;
166                         FIndy.ProxyParams.ProxyUsername := GikoSys.Setting.ReadProxyUserID;
167                         FIndy.ProxyParams.ProxyPassword := GikoSys.Setting.ReadProxyPassword;
168                         if GikoSys.Setting.ReadProxyUserID <> '' then
169                                 FIndy.ProxyParams.BasicAuthentication := True;
170                         {$IFDEF DEBUG}
171                         Writeln('\83v\83\8d\83L\83V\90Ý\92è\82 \82è');
172                         Writeln('\83z\83X\83g: ' + GikoSys.Setting.ReadProxyAddress);
173                         Writeln('\83|\81[\83g: ' + IntToStr(GikoSys.Setting.ReadProxyPort));
174                         {$ENDIF}
175                 end else begin
176                         if GikoSys.Setting.Protocol then
177                                 FIndy.ProtocolVersion := pv1_1
178                         else
179                                 FIndy.ProtocolVersion := pv1_0;
180                         FIndy.ProxyParams.ProxyServer := '';
181                         FIndy.ProxyParams.ProxyPort := 80;
182                         FIndy.ProxyParams.ProxyUsername := '';
183                         FIndy.ProxyParams.ProxyPassword := '';
184                         {$IFDEF DEBUG}
185                         Writeln('\83v\83\8d\83L\83V\90Ý\92è\82È\82µ');
186                         {$ENDIF}
187                 end;
188
189                 FIndy.Request.ContentRangeStart := 0;
190                 FIndy.Request.LastModified := ZERO_DATE;
191                 ResStream := TMemoryStream.Create;
192                 try
193                         try
194                                 //********************
195                                 //DAT or Subject\8eæ\93¾
196                                 //********************
197                                 Item.ResponseCode := 0;
198                                 RangeStart := 0;
199                                 AdjustLen := 0;
200                                 Modified := 0;
201                                 if Item.DownType = gdtBoard then begin
202                                         {$IFDEF DEBUG}
203                                         Writeln('Subject\8eæ\93¾');
204                                         Writeln('URL: ' + Item.Board.GetReadCgiURL);
205                                         Writeln('Modified: ' + FloatToStr(Item.Board.LastModified));
206                                         {$ENDIF}
207                                         URL := Item.Board.GetReadCgiURL;
208                                         Modified := Item.Board.LastModified;
209                                 end else if Item.DownType = gdtThread then begin
210                                         {$IFDEF DEBUG}
211                                         Writeln('DAT\8eæ\93¾');
212                                         Writeln('URL: ' + Item.ThreadItem.GetDatURL);
213                                         Writeln('Modified: ' + FloatToStr(Item.ThreadItem.LastModified));
214                                         {$ENDIF}
215                                         URL := Item.ThreadItem.GetDatURL;
216                                         Modified := Item.ThreadItem.LastModified;
217                                         if Item.ThreadItem.Size > 0 then begin
218                                                 {$IFDEF DEBUG}
219                                                 Writeln('RangeStart: ' + IntToStr(Item.ThreadItem.Size));
220                                                 {$ENDIF}
221                                                 //\82 \82Ú\81[\82ñ\83`\83F\83b\83N\82Ì\82½\82ß\82P\83o\83C\83g\91O\82©\82ç\8eæ\93¾
222                                                 RangeStart := Item.ThreadItem.Size;
223                                                 AdjustLen := -1;
224                                         end;
225                                 end;
226                                 Abone := False;
227                                 DownloadResult := DatDownload(Item.DownType, URL, Modified, RangeStart, AdjustLen);
228                                 {$IFDEF DEBUG}
229                                 Writeln('ResponseCode: ' + IntToStr(FIndy.ResponseCode));
230                                 {$ENDIF}
231                                 if Item.DownType = gdtThread then begin
232                                         if Item.ResponseCode = 416 then begin
233                                                 Abone := True;
234                                                 DownloadResult := True;
235                                         end else if DownloadResult and (AdjustLen = -1) and (Item.Content[1] <> #10) then
236                                                 Abone := True;
237                                 end;
238
239                                 if Trim(FIndy.Response.RawHeaders.Values['Date']) <> '' then begin
240                                         if Item.DownType = gdtBoard then
241                                                 Item.Board.LastGetTime := MonaUtils.DateStrToDateTime(FIndy.Response.RawHeaders.Values['Date'])
242                                         else
243                                                 Item.ThreadItem.ParentBoard.LastGetTime := MonaUtils.DateStrToDateTime(FIndy.Response.RawHeaders.Values['Date']);
244                                 end;
245
246                                 if DownloadResult then begin
247                                         {$IFDEF DEBUG}
248                                         Writeln('Date:' + FIndy.Response.RawHeaders.Values['Date']);
249                                         {$ENDIF}
250                                         if Abone then begin
251                                                 {$IFDEF DEBUG}
252                                                 Writeln('\82 \82Ú\81[\82ñ\8c\9f\8fo');
253                                                 {$ENDIF}
254                                                 ATitle := Item.ThreadItem.Title;
255                                                 if ATitle = '' then
256                                                         ATitle := '\81i\96¼\8fÌ\95s\96¾\81j';
257                                                 //\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¾
258                                                 RangeStart := 0;
259                                                 AdjustLen := 0;
260                                                 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 + ']';
261                                                 FIcon := gmiWhat;
262                         if FileExists(ChangeFileExt(Item.FThreadItem.GetThreadFileName,'.NG')) = true then
263                                                 DeleteFile(ChangeFileExt(Item.FThreadItem.GetThreadFileName,'.NG'));
264                                                 if Assigned(OnDownloadMsg) then
265                                                         Synchronize(FireDownloadMsg);
266                                                 if not DatDownload(Item.DownType, URL, ZERO_DATE, RangeStart, AdjustLen) then
267                                                         Item.State := gdsError;
268                                                 {$IFDEF DEBUG}
269                                                 Writeln('\82 \82Ú\81[\82ñ\8dÄ\8eæ\93¾\8cã');
270                                                 Writeln('ResponseCode: ' + IntToStr(Item.ResponseCode));
271                                                 {$ENDIF}
272                                         end else if (Item.DownType = gdtThread) and (AdjustLen = -1) and (Item.Content[1] = #10) then begin
273                                                 //\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
274                                                 Item.Content := Copy(Item.Content, 2, Length(Item.Content));
275                                         end;
276                                 end else begin
277                                         Item.State := gdsError;
278                                         if (Item.DownType = gdtBoard) and (Item.ResponseCode = 302) then begin
279                                                 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';
280                                                 FIcon := gmiNG;
281                                                 if Assigned(OnDownloadMsg) then
282                                                         Synchronize(FireDownloadMsg);
283                                         end;
284                                 end;
285
286                                 //********************
287                                 //dat.gz\8eæ\93¾(1)
288                                 //********************
289                                 if (Item.DownType = gdtThread) and (Item.ResponseCode = 302) then begin
290                                         {$IFDEF DEBUG}
291                                         Writeln('dat.gz\8eæ\93¾');
292                                         {$ENDIF}
293                                         ATitle := Item.ThreadItem.Title;
294                                         if ATitle = '' then
295                                                 ATitle := '\81i\96¼\8fÌ\95s\96¾\81j';
296                                         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 + ']';
297                                         FIcon := gmiWhat;
298                                         if Assigned(OnDownloadMsg) then
299                                                 Synchronize(FireDownloadMsg);
300                                         URL := Item.ThreadItem.GetDatgzURL;
301                                         Modified := Item.ThreadItem.LastModified;
302                                         RangeStart := 0;
303                                         AdjustLen := 0;
304                                         if not DatDownload(Item.DownType, URL, Modified, RangeStart, AdjustLen) then
305                                                 Item.State := gdsError;
306                                         {$IFDEF DEBUG}
307                                         Writeln('ResponseCode: ' + IntToStr(Item.ResponseCode));
308                                         {$ENDIF}
309                                 end;
310
311                                 //********************
312                                 //dat.gz\8eæ\93¾(2)
313                                 //********************
314 {
315                                 if (Item.DownType = gdtThread) and (Item.ResponseCode = 302) then begin
316                                         ATitle := Item.ThreadItem.Title;
317                                         if ATitle = '' then
318                                                 ATitle := '\81i\96¼\8fÌ\95s\96¾\81j';
319                                         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 + ']';
320                                         FIcon := gmiWhat;
321                                         if Assigned(OnDownloadMsg) then
322                                                 Synchronize(FireDownloadMsg);
323                                         URL := Item.ThreadItem.GetOldDatgzURL;
324                                         Modified := Item.ThreadItem.LastModified;
325                                         RangeStart := 0;
326                                         AdjustLen := 0;
327                                         if not DatDownload(Item.DownType, URL, Modified, RangeStart, AdjustLen) then
328                                                 Item.State := gdsError;
329                                 end;
330 }
331
332                                 //********************
333                                 //offlaw.cgi\82Å\8eæ\93¾
334                                 //********************
335                                 FSessionID := '';
336                                 Synchronize(GetSessionID);
337                                 if (Item.DownType = gdtThread) and (Item.ResponseCode = 302) and (FSessionID <> '') then begin
338                                         {$IFDEF DEBUG}
339                                         Writeln('offlaw.cgi\82Å\8eæ\93¾');
340                                         {$ENDIF}
341                                         ATitle := Item.ThreadItem.Title;
342                                         if ATitle = '' then
343                                                 ATitle := '\81i\96¼\8fÌ\95s\96¾\81j';
344                                         FMsg := '\81\9adat.gz\82ª\91\8dÝ\82µ\82È\82¢\82½\82ßofflaw.cgi\82ð\97\98\97p\82µ\82Ü\82· - [' + ATitle + ']';
345                                         FIcon := gmiWhat;
346                                         if Assigned(OnDownloadMsg) then
347                                                 Synchronize(FireDownloadMsg);
348                                         URL := Item.ThreadItem.GetOfflawCgiURL(FSessionID);
349                                         Modified := Item.ThreadItem.LastModified;
350                                         RangeStart := 0;
351                                         AdjustLen := 0;
352                                         if not DatDownload(Item.DownType, URL, Modified, RangeStart, AdjustLen) then begin
353                                                 {$IFDEF DEBUG}
354                                                 Writeln('ResponseCode: ' + IntToStr(Item.ResponseCode));
355                                                 {$ENDIF}
356                                                 Item.State := gdsError;
357
358                                                 if (Item.DownType = gdtThread) and (Item.ResponseCode = 302) then begin
359                                                         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';
360                                                         FIcon := gmiNG;
361                                                         if Assigned(OnDownloadMsg) then
362                                                                 Synchronize(FireDownloadMsg);
363                                                 end;
364
365                                         end else begin
366                                                 CgiStatus := ParseCgiStatus(Item.Content);
367                                                 {$IFDEF DEBUG}
368                                                 Writeln('ResponseCode: ' + IntToStr(Item.ResponseCode));
369                                                 {$ENDIF}
370                                                 case CgiStatus.FStatus of
371                                                         gcsOK: begin
372                                                                 {$IFDEF DEBUG}
373                                                                 Writeln('CGIStatus: OK');
374                                                                 {$ENDIF}
375                                                                 Item.ResponseCode := 200;
376                                                                 Item.Content := DeleteStatusLine(Item.Content);
377                                                                 Item.ContentLength := CgiStatus.FSize;
378                                                         end;
379                                                         gcsINCR: begin
380                                                                 //\8d¡\82Í\82 \82è\82¦\82È\82¢
381                                                                 {$IFDEF DEBUG}
382                                                                 Writeln('CGIStatus: 206');
383                                                                 {$ENDIF}
384                                                                 Item.ResponseCode := 206;
385                                                                 Item.Content := DeleteStatusLine(Item.Content);
386                                                                 Item.ContentLength := CgiStatus.FSize;
387                                                         end;
388                                                         gcsERR: begin
389                                                                 {$IFDEF DEBUG}
390                                                                 Writeln('CGIStatus: 404(ERROR)');
391                                                                 {$ENDIF}
392                                                                 Item.ResponseCode := 404;
393                                                                 Item.State := gdsError;
394                                                                 Item.ErrText := CgiStatus.FErrText;
395                                                         end;
396                                                 end;
397                                                 if (Item.ResponseCode = 404) and (AnsiPos('\89ß\8b\8e\83\8d\83O\91q\8cÉ\82Å\94­\8c©', Item.ErrText) <> 0) then begin
398                                                         {$IFDEF DEBUG}
399                                                         Writeln('\89ß\8b\8e\83\8d\83O\8eæ\93¾');
400                                                         {$ENDIF}
401                                                         ATitle := Item.ThreadItem.Title;
402                                                         if ATitle = '' then
403                                                                 ATitle := '\81i\96¼\8fÌ\95s\96¾\81j';
404                                                         FMsg := '\81\9a\89ß\8b\8e\83\8d\83O\91q\8cÉ\82Å\94­\8c© - [' + ATitle + ']';
405                                                         FIcon := gmiWhat;
406                                                         if Assigned(OnDownloadMsg) then
407                                                                 Synchronize(FireDownloadMsg);
408                                                         Idx := Pos(' ', Item.ErrText);
409                                                         if Idx <> 0 then begin
410                                                                 URL := Copy(Item.ErrText, Idx + 1, Length(Item.ErrText));
411                                                                 if Pos('../', URL) = 1 then
412                                                                         URL := Copy(URL, 4, Length(URL));
413                                                                 URL := GikoSys.UrlToServer(Item.ThreadItem.ParentBoard.URL) + URL;
414                                                                 Modified := Item.ThreadItem.LastModified;
415                                                                 RangeStart := 0;
416                                                                 AdjustLen := 0;
417                                                                 if not DatDownload(Item.DownType, URL, Modified, RangeStart, AdjustLen) then
418                                                                         Item.State := gdsError;
419                                                                 {$IFDEF DEBUG}
420                                                                 Writeln('ResponseCode: ' + IntToStr(Item.ResponseCode));
421                                                                 {$ENDIF}
422                                                         end;
423                                                 end;
424                                         end;
425                                 end else begin
426                                         if (Item.DownType = gdtThread) and (Item.ResponseCode = 302) and (FSessionID = '') then begin
427                                                 {$IFDEF DEBUG}
428                                                 Writeln('\83\8d\83O\83C\83\93\82³\82ê\82Ä\82È\82¢\82Ì\82Å\89ß\8b\8e\83\8d\83O\8eæ\93¾\95s\89Â');
429                                                 {$ENDIF}
430                                                 ATitle := Item.ThreadItem.Title;
431                                                 if ATitle = '' then
432                                                         ATitle := '\81i\96¼\8fÌ\95s\96¾\81j';
433                                                 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 + ']';
434                                                 FIcon := gmiSAD;
435                                                 if Assigned(OnDownloadMsg) then
436                                                         Synchronize(FireDownloadMsg);
437                                         end;
438                                 end;
439
440                                 case Item.ResponseCode of
441                                         200: Item.State := gdsComplete;
442                                         206: Item.State := gdsDiffComplete;
443                                         304: Item.State := gdsNotModify;
444                                         else
445                                                 Item.State := gdsError;
446                                 end;
447 {
448                                 //\96³\82¢\82Æ\8ev\82¤\82¯\82Ç\81B\81B\81B
449                                 if (Item.ResponseCode in [200, 206]) and (Item.Content = '') then
450                                         Item.State := gdsError;
451                                 Item.LastModified := FIndy.Response.LastModified;
452                                 //\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é
453                                 Item.ContentLength := FIndy.Response.ContentLength + AdjustLen;
454                                 try
455                                         ResStream.Clear;
456                                         FIndy.Get(URL, ResStream);
457                                         Item.Content := GikoSys.GzipDecompress(ResStream, FIndy.Response.ContentEncoding);
458                                         if (Item.DownType = gdtThread) and (AdjustLen = -1) and (Item.Content[1] <> #10) then begin
459                                                 //\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¾
460                                                 //\82±\82±\82Å\83\81\83b\83Z\81[\83W\95\\8e¦\83C\83x\83\93\83g
461                                                 //event
462                                                 FMsg := '\81u\82 \82Ú\81[\82ñ\81v\82ð\8c\9f\8fo\82µ\82½\82Ì\82Å\8dÄ\8eæ\93¾\82ð\8ds\82¢\82Ü\82·';
463                                                 if Assigned(OnDownloadMsg) then
464                                                         Synchronize(FireDownloadMsg);
465                                                 FIndy.Request.ContentRangeStart := 0;
466                                                 FIndy.Request.ContentRangeEnd := 0;
467                                                 AdjustLen := 0;
468                                                 ResStream.Clear;
469                                                 FIndy.Get(URL, ResStream);
470                                                 Item.Content := GikoSys.GzipDecompress(ResStream, FIndy.Response.ContentEncoding);
471                                         end else if (Item.DownType = gdtThread) and (AdjustLen = -1) and (Item.Content[1] = #10) then begin
472                                                 //\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
473                                                 Item.Content := Copy(Item.Content, 2, Length(Item.Content));
474                                         end;
475                                 except
476                                         Item.State := gdsError;
477                                 end;
478                                 Item.ResponseCode := FIndy.ResponseCode;
479 }
480 {
481                                 try
482                                         ResStream.Clear;
483                                         FIndy.Get(URL, ResStream);
484                                         Item.Content := GikoSys.GzipDecompress(ResStream, FIndy.Response.ContentEncoding);
485                                 except
486                                         Item.State := gdsError;
487                                 end;
488
489                                 CgiStatus := ParseCgiStatus(Item.Content);
490                                 if CgiStatus.FStatus = gcsOK then begin
491                                         if CgiStatus.FSize = 0 then
492                                                 Item.State := gdsNotModify
493                                         else if Item.DownType = gdtBoard then
494                                                 Item.State := gdsComplete
495                                         else
496                                                 Item.State := gdsDiffComplete;
497                                 end else if CgiStatus.FStatus = gcsINCR then begin
498                                         Item.State := gdsComplete;
499                                 end else if CgiStatus.FStatus = gcsERR then begin
500                                         Item.State := gdsError;
501                                         Item.ErrText := CgiStatus.FErrText;
502                                 end;
503                                 Item.ContentLength := CgiStatus.FSize;
504                                 }
505                         except
506                                 Item.State := gdsError;
507                         end;
508                         //Item.ResponseCode := FIndy.ResponseCode;
509                         if FAbort then
510                                 Item.State := gdsAbort;
511                 finally
512                         if Assigned(OnDownloadEnd) then
513                                 Synchronize(FireDownloadEnd);
514                         ResStream.Free;
515                 end;
516                 if Terminated then Break;
517                 Suspend;
518         end;
519 end;
520
521 function TDownloadThread.DatDownload(ItemType: TGikoDownloadType; URL: string; Modified: TDateTime; RangeStart: Integer; AdjustLen: Integer): Boolean;
522 var
523         ResponseCode: Integer;
524         ResStream: TMemoryStream;
525 begin
526         ResponseCode := -1;
527         if (ItemType = gdtThread) and (RangeStart > 0) then begin
528 //      if (ItemType = gdtThread) and (Item.ThreadItem.Size > 0) then begin
529 //              FIndy.Request.ContentRangeStart := Item.ThreadItem.Size + AdjustLen;
530                 FIndy.Request.ContentRangeStart := RangeStart + AdjustLen;
531                 FIndy.Request.ContentRangeEnd := 0;
532         end else begin
533                 FIndy.Request.ContentRangeStart := 0;
534                 FIndy.Request.ContentRangeEnd := 0;
535         end;
536
537         FIndy.Request.CustomHeaders.Clear;
538         FIndy.Request.CacheControl := 'no-cache';
539         FIndy.Request.CustomHeaders.Add('Pragma: no-cache');
540         if (Modified <> 0) and (Modified <> ZERO_DATE) then begin
541                 FIndy.Request.LastModified := modified - OffsetFromUTC;
542                 //FIndy.Request.CustomHeaders.Add('If-Modified-Since: ' + RFC1123_Date(modified - OffsetFromUTC) + ' GMT');
543         end;
544 //      FIndy.Request.AcceptEncoding := 'gzip';
545         if RangeStart = 0 then
546                 FIndy.Request.AcceptEncoding := 'gzip'
547         else
548                 FIndy.Request.AcceptEncoding := '';
549         ResStream := TMemoryStream.Create;
550         try
551                 try
552                         ResStream.Clear;
553                         {$IFDEF DEBUG}
554                         Writeln('URL: ' + URL);
555                         {$ENDIF}
556                         FIndy.Get(URL, ResStream);
557                         Item.Content := GikoSys.GzipDecompress(ResStream, FIndy.Response.ContentEncoding);
558                         Item.LastModified := FIndy.Response.LastModified;
559                         //\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é
560 //                      Item.ContentLength := FIndy.Response.ContentLength + AdjustLen;
561                         Item.ContentLength := Length(Item.Content) + AdjustLen;
562                         //\96³\82¢\82Æ\8ev\82¤\82¯\82Ç\81B\81B\81B
563 //                      if (FIndy.ResponseCode in [200, 206]) and (Item.Content = '') then
564 //                              Result := False
565                         if Item.Content = '' then
566                                 Result := False
567                         else
568                                 Result := True;
569                         {$IFDEF DEBUG}
570                         Writeln('\8eæ\93¾\82Å\97á\8aO\82È\82µ');
571                         {$ENDIF}
572                         ResponseCode := FIndy.ResponseCode;
573                 except
574                         on E: EIdSocketError do begin
575                                 Item.Content := '';
576                                 Item.LastModified := ZERO_DATE;
577                                 Item.ContentLength := 0;
578                                 Item.ErrText := E.Message;
579                                 Result := False;
580                                 ResponseCode := -1;
581                 Screen.Cursor := crDefault;
582                         end;
583                         on E: EIdConnectException do begin
584                                 Item.Content := '';
585                                 Item.LastModified := ZERO_DATE;
586                                 Item.ContentLength := 0;
587                                 Item.ErrText := E.Message;
588                                 Result := False;
589                                 ResponseCode := -1;
590                 Screen.Cursor := crDefault;
591                         end;
592                         on E: Exception do begin
593                                 {$IFDEF DEBUG}
594                                 Writeln('\8eæ\93¾\82Å\97á\8aO\82 \82è');
595                                 Writeln('E.Message: ' + E.Message);
596                                 {$ENDIF}
597                                 Item.Content := '';
598                                 Item.LastModified := ZERO_DATE;
599                                 Item.ContentLength := 0;
600                                 Item.ErrText := E.Message;
601                                 ResponseCode := FIndy.ResponseCode;
602                                 Result := False;
603                 Screen.Cursor := crDefault;
604                         end;
605                 end;
606         finally
607                 if (Item.ContentLength = 0) and (ResponseCode = 206) then
608                         Item.ResponseCode := 304
609                 else
610                         Item.ResponseCode := ResponseCode;
611                 ResStream.Free;
612         end;
613 end;
614
615 procedure TDownloadThread.FireDownloadEnd;
616 begin
617         OnDownloadEnd(self, Item);
618 end;
619
620 procedure TDownloadThread.FireDownloadMsg;
621 begin
622         OnDownloadMsg(Self, Item, FMsg, FIcon);
623 end;
624
625 procedure TDownloadThread.GetSessionID;
626 begin
627         FSessionID := GikoSys.Dolib.SessionID;
628 end;
629
630 procedure TDownloadThread.Abort;
631 begin
632         FAbort := True;
633         FIndy.DisconnectSocket;
634 end;
635
636 procedure TDownloadThread.WorkBegin(Sender: TObject; AWorkMode: TWorkMode; const AWorkCountMax: Integer);
637 begin
638         if Assigned(OnWorkBegin) then
639                 OnWorkBegin(Sender, AWorkMode, AWorkCountMax, FNumber);
640 end;
641
642 procedure TDownloadThread.WorkEnd(Sender: TObject; AWorkMode: TWorkMode);
643 begin
644         if Assigned(OnWorkEnd) then
645                 OnWorkEnd(Sender, AWorkMode, FNumber);
646 end;
647
648 procedure TDownloadThread.Work(Sender: TObject; AWorkMode: TWorkMode; const AWorkCount: Integer);
649 begin
650         if Assigned(OnWork) then
651                 OnWork(Sender, AWorkMode, AWorkCount, FNumber);
652 end;
653
654 function TDownloadThread.ParseCgiStatus(Content: string): TCgiStatus;
655 var
656         StatusLine: string;
657         Line: string;
658         Idx: Integer;
659         Status: string;
660         Size: string;
661         Msg: string;
662 begin
663 // [+OK] \82Ì\8fê\8d\87\82Í\8d·\95ª
664 // [-INCR] (Incorrect)\82Ì\8fê\8d\87\82Í\82·\82×\82Ä\82Ì\83f\81[\83^
665 // [-ERR (\83e\83L\83X\83g)]\82Ì\8fê\8d\87\82Í\82È\82ñ\82©\83G\83\89\81[
666 // \97á\81F+OK 23094/512K
667 //     -INCR 23094/512K
668 //     -ERR \82»\82ñ\82È\94Â\82È\82¢\82Å\82·
669         Idx := AnsiPos(#10, Content);
670         StatusLine := Copy(Content, 0, Idx);
671
672         Idx := AnsiPos(' ', Content);
673         Status := Copy(StatusLine, 0, Idx - 1);
674         Line := Copy(StatusLine, Idx + 1, Length(StatusLine));
675
676 //      Idx := AnsiPos('/', Line);
677         if Trim(Status) = '-ERR' then
678                 Msg := Trim(Line)
679         else
680                 Size := Copy(Line, 0, Idx - 1);
681
682         if Trim(Status) = '+OK' then
683                 Result.FStatus := gcsOK
684         else if Trim(Status) = '-INCR' then
685                 Result.FStatus := gcsINCR
686         else if Trim(Status) = '-ERR' then begin
687                 Result.FStatus := gcsERR;
688                 Result.FErrText := Msg;
689                 Result.FSize := 0;
690                 Exit;
691         end else begin
692                 {$IFDEF DEBUG}
693                 Writeln(Status);
694                 {$ENDIF}
695                 Result.FStatus := gcsERR;
696                 Result.FErrText := '\83G\83\89\81[\82È\82ñ\82¾\82¯\82Ç\81A\82æ\82­\95ª\82©\82ç\82È\82¢\83G\83\89\81[';
697                 Result.FSize := 0;
698                 Exit;
699         end;
700
701         if GikoSys.IsNumeric(Size) then
702                 Result.FSize := StrToInt(Size)
703         else begin
704                 Result.FSize := 0;
705                 Result.FStatus := gcsERR;
706                 Result.FErrText := '\83X\83e\81[\83^\83X\89ð\90Í\8e¸\94s[' + StatusLine + ']';
707         end;
708 end;
709
710 //\8eè\94²\82«\82È\8f\88\97\9d\82Å1\8ds\96Ú\82ð\8fÁ\82·
711 function TDownloadThread.DeleteStatusLine(Content: string): string;
712 var
713         SList: TStringList;
714 begin
715         SList := TStringList.Create;
716         try
717                 SList.Text := Content;
718                 if SList.Count > 1 then
719                         SList.Delete(0);
720                 Result := SList.Text;
721         finally
722                 SList.Free;
723         end;
724 end;
725
726 procedure TDownloadItem.SaveListFile;
727 var
728         i: Integer;
729         index: Integer;
730         NewItem: TThreadItem;
731         NewList: TList;
732 //      SaveCount: Integer;
733         NumCount: Integer;
734         Body: TStringList;
735         Rec: TSubjectRec;
736 begin
737         NewList := TList.Create;
738         Body := TStringList.Create;
739         try
740                 //\83_\83E\83\93\83\8d\81[\83h\93ú\8e\9e\90Ý\92è\81i\83\8d\81[\83J\83\8b\93ú\8e\9e\81j
741                 Board.RoundDate := Now;
742                 //\83T\81[\83o\8fã\83t\83@\83C\83\8b\82Ì\8dX\90V\8e\9e\8d\8f\90Ý\92è
743                 Board.LastModified := LastModified;
744
745                 //\90V\82µ\82¢\83\8a\83X\83g\82ð\8dì\90¬\82·\82é
746                 //\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Á
747                 //\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¬
748                 Body.Text := Content;
749                 NumCount := 0;
750                 for i := 0 to Body.Count - 1 do begin
751                         //if i = 0 then Continue;       //\82P\8ds\96Ú\82Í\83X\83e\81[\83^\83X\8ds\82Ì\82½\82ß\8f\88\97\9d\82È\82µ
752
753                         Rec := GikoSys.DivideSubject(Body[i]);
754                         Rec.FFileName := Trim(Rec.FFileName);
755                         if (Rec.FTitle = '') and (Rec.FCount = 0) then Continue;
756                         Inc(NumCount);
757                         index := Board.GetIndex(Rec.FFileName);
758                         if index = -1 then begin
759                                 //\90V\82µ\82¢\83X\83\8c\83b\83h
760                                 NewItem := TThreadItem.Create;
761                                 NewItem.FileName := Rec.FFileName;
762                                 NewItem.Title := Rec.FTitle;
763 //                              NewItem.Count := Rec.FCount;
764                                 NewItem.AllResCount := Rec.FCount;
765                                 NewItem.ParentBoard := Board;
766                                 NewItem.No := NumCount;
767                                 NewItem.RoundDate := ZERO_DATE;
768                                 NewItem.LastModified := ZERO_DATE;
769                                 NewItem.AgeSage := gasNew;
770                                 NewList.Add(NewItem);
771                         end else begin
772                                 //Board.Items[index].Count := Count;
773                                 //Board.Items[index].Count := Rec.FCount;
774                                 if Board.Items[index].No > NumCount then
775                                         Board.Items[index].AgeSage := gasAge
776                                 else if Board.Items[index].AllResCount < Rec.FCount then
777                                         Board.Items[index].AgeSage := gasSage
778                                 else
779                                         Board.Items[index].AgeSage := gasNone;
780
781
782                                 Board.Items[index].No := NumCount;
783                                 Board.Items[index].AllResCount := Rec.FCount;
784 //                              if not Board.Items[index].IsLogFile then
785 //                                      Board.Items[index].Count := Rec.FCount;
786                                 NewList.Add(Board.Items[index]);
787                                 Board.DeleteList(index);
788                         end;
789                 end;
790
791                 //\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Á
792                 for i := 0 to Board.Count - 1 do begin
793                         if Board.Items[i].IsLogFile then begin
794                                 inc(NumCount);
795                                 Board.Items[i].No := NumCount;
796                                 Board.Items[i].AllResCount := Board.Items[i].Count;
797                                 Board.Items[i].NewResCount := 0;
798                                 Board.Items[i].AgeSage := gasNone;
799                                 NewList.Add(Board.Items[i]);
800                         end;
801                 end;
802
803                 //\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
804                 for i := Board.Count - 1 downto 0 do
805                         Board.DeleteList(i);
806
807                 //\90V\82µ\82¢\83\8a\83X\83g\82ð\83{\81[\83h\83I\83u\83W\83F\83N\83g\82É\92Ç\89Á
808                 for i := 0 to NewList.Count - 1 do
809                         Board.Add(TThreadItem(NewList[i]));
810
811                 //\83\8a\83X\83g(subject.txt)\82ð\95Û\91
812 //              GikoSys.ForceDirectoriesEx(GikoSys.GetLogDir + Board.BBSID);
813 //              Body.SaveToFile(GikoSys.GetSubjectFileName(Board.BBSID));
814                 GikoSys.ForceDirectoriesEx(ExtractFilePath(Board.GetSubjectFileName));
815                 Body.SaveToFile(Board.GetSubjectFileName);
816         finally
817                 Body.Free;
818                 NewList.Free;
819         end;
820 end;
821
822 {procedure TDownloadItem.SaveListFile;
823 var
824         i: Integer;
825         index: Integer;
826         NewItem: TThreadItem;
827         NewList: TList;
828 //      SaveCount: Integer;
829         NumCount: Integer;
830         Body: TStringList;
831         Rec: TSubjectRec;
832 begin
833         NewList := TList.Create;
834         Body := TStringList.Create;
835         try
836                 //\8f\84\89ñ\93ú\8e\9e\90Ý\92è
837                 Board.RoundDate := Now;
838                 //\83T\81[\83o\8fã\83t\83@\83C\83\8b\82Ì\8dX\90V\8e\9e\8d\8f\90Ý\92è
839                 Board.LastModified := LastModified;
840
841                 //\83\8a\83X\83g\95Û\91\8c\8f\90\94\8eæ\93¾
842                 //SaveCount := MaxInt;
843
844                 //\8cÃ\82¢\83\8a\83X\83g\82©\82ç\83\8d\83O\96³\82µ\83A\83C\83e\83\80\82ð\8dí\8f\9c
845                 for i := Board.Count - 1 downto 0 do
846                         if not Board.Items[i].IsLogFile then
847                                 Board.Delete(i);
848
849                 //\90V\82µ\82¢\83\8a\83X\83g\82ð\8dì\90¬\82·\82é
850                 //\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Á
851                 //\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¬
852                 Body.Text := Content;
853 //              Loop := Min(Body.Count, SaveCount);
854                 NumCount := 0;
855 //              for i := 0 to Loop - 1 do begin
856                 for i := 0 to Body.Count - 1 do begin
857                         if i = 0 then Continue; //\82P\8ds\96Ú\82Í\83X\83e\81[\83^\83X\8ds\82Ì\82½\82ß\8f\88\97\9d\82È\82µ
858
859                         Rec := GikoSys.DivideSubject(Body[i]);
860                         if (Rec.FTitle = '') and (Rec.FCount = 0) then Continue;
861                         Inc(NumCount);
862                         index := Board.GetIndex(Rec.FFileName);
863                         if index = -1 then begin
864                                 NewItem := TThreadItem.Create;
865                                 NewItem.FileName := Rec.FFileName;
866                                 NewItem.Title := Rec.FTitle;
867                                 NewItem.Count := Rec.FCount;
868                                 NewItem.ParentBoard := Board;
869                                 NewItem.No := NumCount;
870                                 NewItem.RoundDate := ZERO_DATE;
871                                 NewItem.LastModified := ZERO_DATE;
872                                 NewList.Add(NewItem);
873                         end else begin
874                                 //Board.Items[index].Count := Count;
875                                 Board.Items[index].No := NumCount;
876                                 NewList.Add(Board.Items[index]);
877                                 Board.DeleteList(index);
878                         end;
879                 end;
880
881                 //\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Á
882                 for i := 0 to Board.Count - 1 do begin
883                         inc(NumCount);
884                         Board.Items[i].No := NumCount;
885                         NewList.Add(Board.Items[i]);
886                 end;
887
888                 //\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
889                 for i := Board.Count - 1 downto 0 do
890                         Board.DeleteList(i);
891
892                 //\90V\82µ\82¢\83\8a\83X\83g\82ð\83{\81[\83h\83I\83u\83W\83F\83N\83g\82É\92Ç\89Á
893                 for i := 0 to NewList.Count - 1 do
894                         Board.Add(TThreadItem(NewList[i]));
895
896                 //\83\8a\83X\83g(subject.txt)\82ð\95Û\91
897 //              GikoSys.ForceDirectoriesEx(GikoSys.GetLogDir + Board.BBSID);
898 //              Body.SaveToFile(GikoSys.GetSubjectFileName(Board.BBSID));
899                 GikoSys.ForceDirectoriesEx(ExtractFilePath(Board.GetSubjectFileName));
900                 Body.SaveToFile(Board.GetSubjectFileName);
901         finally
902                 Body.Free;
903                 NewList.Free;
904         end;
905 end;
906 }
907 procedure TDownloadItem.SaveItemFile;
908 var
909         Body: TStringList;
910         Cnt: Integer;
911         OldCnt: Integer;
912         FileName: string;
913         ini: TMemIniFile;
914         Res: TResRec;
915         NewRes: Integer;
916 begin
917         if Trim(Content) = '' then
918                 Exit;
919         FileName := ThreadItem.GetThreadFileName;
920         GikoSys.ForceDirectoriesEx(ExtractFilePath(FileName));
921
922 //      Cnt := 0;
923         Body := TStringList.Create;
924         try
925 //              if FileExists(FileName) and (ResponseCode = 206) then begin
926                 if FileExists(FileName) and (State = gdsDiffComplete) then begin
927 //                      Body.Text := Content;
928 //                      if Body.Count > 0 then
929 //                              Body.Delete(0);
930 //                      Content := Body.Text;
931                         Body.LoadFromFile(FileName);
932                         OldCnt := Body.Count;
933                         Body.Text := Body.Text + Content;
934                         Body.SaveToFile(FileName);
935                         NewRes := Body.Count - OldCnt;
936                         Cnt := Body.Count;
937                 end else begin
938                         Body.Text := Content;
939 //                      if Body.Count > 0 then
940 //                              Body.Delete(0);
941                         Body.SaveToFile(FileName);
942
943                         if ThreadItem.Title = '' then begin
944                                 Res := GikoSys.DivideStrLine(Body[0]);
945                                 ThreadItem.Title := Res.FTitle;
946                         end;
947                         ThreadItem.Size := 0;
948                         //ThreadItem.Count := 0;
949                         ThreadItem.AllResCount := 0;
950                         ThreadItem.NewResCount := 0;
951                         OldCnt := 0;
952                         NewRes := Body.Count;
953                         Cnt := Body.Count;
954                 end;
955                 Cnt := Body.Count;
956         finally
957                 Body.Free;
958         end;
959         ThreadItem.RoundDate := Now;
960         ThreadItem.Size := ThreadItem.Size + ContentLength;
961         ThreadItem.LastModified := LastModified;
962         ThreadItem.Count := Cnt;
963         ThreadItem.AllResCount := Cnt;
964         ThreadItem.NewResCount := NewRes;
965         ThreadItem.IsLogFile := True;
966         ThreadItem.NewReceive := OldCnt + 1;
967         ThreadItem.UnRead := True;
968         ThreadItem.ParentBoard.UnRead := ThreadItem.ParentBoard.UnRead + 1;
969 //      if ThreadItem.RoundNo = 6 then
970 //              ThreadItem.RoundNo := 0;
971
972         //\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
973         //\90³\8fí\8fI\97¹\8e\9e\82É\82Í\8dí\8f\9c
974         //\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
975         ini := TMemIniFile.Create(ChangeFileExt(FileName, '.tmp'));
976         try
977                 ini.WriteDateTime('Setting', 'RoundDate', ThreadItem.RoundDate);
978                 ini.WriteDateTime('Setting', 'LastModified', ThreadItem.LastModified);
979                 ini.WriteInteger('Setting', 'Size', ThreadItem.Size);
980                 ini.WriteInteger('Setting', 'Count', ThreadItem.Count);
981                 ini.WriteInteger('Setting', 'AllResCount', ThreadItem.AllResCount);
982                 ini.WriteInteger('Setting', 'NewResCount', ThreadItem.NewResCount);
983                 ini.WriteInteger('Setting', 'NewReceive', ThreadItem.NewReceive);
984 //              ini.WriteInteger('Setting', 'RoundNo', ThreadItem.RoundNo);
985                 ini.WriteBool('Setting', 'Round', ThreadItem.Round);
986                 ini.WriteBool('Setting', 'UnRead', ThreadItem.UnRead);
987                 ini.UpdateFile;
988         finally
989                 ini.Free;
990         end;
991 end;
992
993 end.