Develop and Download Open Source Software

Browse CVS Repository

Annotation of /gikonavigoeson/gikonavi/ItemDownload.pas

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.6.2.2 - (hide annotations) (download) (as text)
Thu Sep 9 16:20:33 2004 UTC (19 years, 7 months ago) by yoffy
Branch: stable
Changes since 1.6.2.1: +196 -91 lines
File MIME type: text/x-pascal
・ミ・ソ48、ヒ・゙。シ・ク。」

1 hi_ 1.1 unit ItemDownload;
2    
3     interface
4    
5     uses
6 yoffy 1.6.2.1 Windows, SysUtils, Classes, ComCtrls, Controls, Forms, IdHTTP,
7 yoffy 1.2 {HTTPApp,} YofUtils, IdGlobal, IdException, IdComponent, IniFiles, {DateUtils,}
8 yoffy 1.6.2.2 GikoSystem, BoardGroup, MonaUtils, ExternalBoardManager, ExternalBoardPlugInMain,
9     Sort;
10 hi_ 1.1
11     type
12     TDownloadItem = class;
13     TGikoDownloadType = (gdtBoard, gdtThread);
14     TGikoDownloadState = (gdsWait, gdsWork, gdsComplete, gdsDiffComplete, gdsNotModify, gdsAbort, gdsError);
15     TGikoCgiStatus = (gcsOK, gcsINCR, gcsERR);
16     TGikoDLProgress = (gdpStd, gdpAll, gdpDatOchi, gdpOfflaw);
17    
18     TGikoWorkEvent = procedure(Sender: TObject; AWorkMode: TWorkMode; const AWorkCount: Integer; ID: Integer) of object;
19 yoffy 1.6.2.1 TGikoWorkBeginEvent = procedure(Sender: TObject; AWorkMode: TWorkMode; const AWorkCountMax: Integer; ID: Integer; const AWorkTitle: string) of object;
20 hi_ 1.1 TGikoWorkEndEvent = procedure(Sender: TObject; AWorkMode: TWorkMode; ID: Integer) of object;
21     TDownloadEndEvent = procedure(Sender: TObject; Item: TDownloadItem) of object;
22     TDownloadMsgEvent = procedure(Sender: TObject; Item: TDownloadItem; Msg: string; Icon: TGikoMessageIcon) of object;
23    
24     TCgiStatus = record
25     FStatus: TGikoCgiStatus;
26     FSize: Integer;
27     FErrText: string;
28     end;
29    
30    
31     TDownloadThread = class(TThread)
32     private
33     FIndy: TIdHttp;
34     FItem: TDownloadItem;
35     FNumber: Integer;
36     FAbort: Boolean;
37     FMsg: string;
38     FIcon: TGikoMessageIcon;
39     FSessionID: string;
40     FOnWork: TGikoWorkEvent;
41     FOnWorkBegin: TGikoWorkBeginEvent;
42     FOnWorkEnd: TGikoWorkEndEvent;
43     FOnDownloadEnd: TDownloadEndEvent;
44     FOnDownloadMsg: TDownloadMsgEvent;
45 yoffy 1.6.2.1 FDownloadTitle: string;
46 hi_ 1.1
47     procedure FireDownloadEnd;
48     procedure FireDownloadMsg;
49     procedure GetSessionID;
50     procedure WorkBegin(Sender: TObject; AWorkMode: TWorkMode; const AWorkCountMax: Integer);
51     procedure WorkEnd(Sender: TObject; AWorkMode: TWorkMode);
52     procedure Work(Sender: TObject; AWorkMode: TWorkMode; const AWorkCount: Integer);
53     function ParseCgiStatus(Content: string): TCgiStatus;
54 yoffy 1.6.2.1 function CgiDownload(ItemType: TGikoDownloadType; URL: string; Modified: TDateTime): Boolean;
55 hi_ 1.1 function DatDownload(ItemType: TGikoDownloadType; URL: string; Modified: TDateTime; RangeStart: Integer; AdjustLen: Integer): Boolean;
56     function DeleteStatusLine(Content: string): string;
57     protected
58     procedure Execute; override;
59     public
60     property Item: TDownloadItem read FItem write FItem;
61     property Number: Integer read FNumber write FNumber;
62     constructor Create(CreateSuspended: Boolean);
63 yoffy 1.6.2.2 destructor Destroy; override;
64 hi_ 1.1 procedure Abort;
65     property OnWork: TGikoWorkEvent read FOnWork write FOnWork;
66     property OnWorkBegin: TGikoWorkBeginEvent read FOnWorkBegin write FOnWorkBegin;
67     property OnWorkEnd: TGikoWorkEndEvent read FOnWorkEnd write FOnWorkEnd;
68     property OnDownloadEnd: TDownloadEndEvent read FOnDownloadEnd write FOnDownloadEnd;
69     property OnDownloadMsg: TDownloadMsgEvent read FOnDownloadMsg write FOnDownloadMsg;
70     end;
71    
72     TDownloadItem = class(TObject)
73     private
74     FDownType: TGikoDownloadType;
75     FBoard: TBoard;
76     FThreadItem: TThreadItem;
77    
78     FContentLength: Integer;
79     FLastModified: TDateTime;
80     FContent: string;
81     FResponseCode: Smallint;
82     FState: TGikoDownloadState;
83     FErrText: string;
84 yoffy 1.6.2.2 FForceDownload: Boolean;
85     FIsAbone : Boolean;
86 hi_ 1.1 public
87     procedure SaveListFile;
88     procedure SaveItemFile;
89    
90     property DownType: TGikoDownloadType read FDownType write FDownType;
91     property Board: TBoard read FBoard write FBoard;
92     property ThreadItem: TThreadItem read FThreadItem write FThreadItem;
93    
94     property ContentLength: Integer read FContentLength write FContentLength;
95     property LastModified: TDateTime read FLastModified write FLastModified;
96     property Content: string read FContent write FContent;
97     property ResponseCode: Smallint read FResponseCode write FResponseCode;
98     property State: TGikoDownloadState read FState write FState;
99     property ErrText: string read FErrText write FErrText;
100 yoffy 1.6.2.2 property ForceDownload: Boolean read FForceDownload write FForceDownload;
101     property IsAbone : Boolean read FIsAbone write FIsAbone;
102 hi_ 1.1 end;
103    
104     implementation
105    
106     constructor TDownloadThread.Create(CreateSuspended: Boolean);
107     begin
108     inherited Create(CreateSuspended);
109     FIndy := TIdHttp.Create(nil);
110    
111     FIndy.OnWorkBegin := WorkBegin;
112     FIndy.OnWorkEnd := WorkEnd;
113     FIndy.OnWork := Work;
114     end;
115    
116     destructor TDownloadThread.Destroy;
117     begin
118 yoffy 1.6.2.1 FIndy.Request.CustomHeaders.Clear;
119     FIndy.Request.RawHeaders.Clear;
120     FIndy.Request.Clear;
121     FIndy.Response.CustomHeaders.Clear;
122     FIndy.Response.RawHeaders.Clear;
123     FIndy.Response.Clear;
124     FIndy.ProxyParams.Clear;
125 hi_ 1.1 FIndy.Free;
126     inherited;
127     end;
128    
129     function RFC1123_Date(aDate : TDateTime) : String;
130     const
131     StrWeekDay : String = 'MonTueWedThuFriSatSun';
132 yoffy 1.6.2.1 StrMonth : String = 'JanFebMarAprMayJunJulAugSepOctNovDec';
133 hi_ 1.1 var
134 yoffy 1.6.2.1 Year, Month, Day : Word;
135     Hour, Min, Sec, MSec : Word;
136     DayOfWeek : Word;
137 hi_ 1.1 begin
138     DecodeDate(aDate, Year, Month, Day);
139 yoffy 1.6.2.1 DecodeTime(aDate, Hour, Min, Sec, MSec);
140 hi_ 1.1 DayOfWeek := ((Trunc(aDate) - 2) mod 7);
141     Result := Copy(StrWeekDay, 1 + DayOfWeek * 3, 3) + ', ' +
142     Format('%2.2d %s %4.4d %2.2d:%2.2d:%2.2d',
143     [Day, Copy(StrMonth, 1 + 3 * (Month - 1), 3),
144     Year, Hour, Min, Sec]);
145     end;
146    
147     procedure TDownloadThread.Execute;
148     var
149     ResStream: TMemoryStream;
150    
151     URL: string;
152     CgiStatus: TCgiStatus;
153     Modified: TDateTime;
154     RangeStart: Integer;
155     AdjustLen: Integer;
156     Idx: Integer;
157     ATitle: string;
158     DownloadResult: Boolean;
159 yoffy 1.6.2.1 foundPos: Integer;
160 yoffy 1.6.2.2 boardPlugIn : TBoardPlugIn;
161     listContent : string;
162     lastContent : string;
163     logFile : TFileStream;
164     adjustMargin : Integer;
165     const
166     ADJUST_MARGIN = 16;
167 hi_ 1.1 begin
168     while not Terminated do begin
169 yoffy 1.6.2.1 //===== ?スv?ス?ス?スO?スC?ス?ス
170 yoffy 1.6.2.2 FAbort := False;
171 yoffy 1.6.2.1 boardPlugIn := nil;
172     ExternalBoardManager.OnWork := Work;
173     ExternalBoardManager.OnWorkBegin := WorkBegin;
174     ExternalBoardManager.OnWorkEnd := WorkEnd;
175    
176     FDownloadTitle := '';
177     case FItem.FDownType of
178     gdtBoard:
179     begin
180     FDownloadTitle := FItem.FBoard.Title;
181     if FItem.FBoard <> nil then begin
182     if FItem.FBoard.IsBoardPlugInAvailable then begin
183     boardPlugIn := FItem.FBoard.BoardPlugIn;
184     Item.State := TGikoDownloadState( boardPlugIn.DownloadBoard( DWORD( FItem.FBoard ) ) );
185     end;
186     end;
187     end;
188     gdtThread:
189     begin
190     FDownloadTitle := FItem.FThreadItem.Title;
191     if FItem.FThreadItem <> nil then begin
192     if FItem.FThreadItem.IsBoardPlugInAvailable then begin
193     boardPlugIn := FItem.FThreadItem.BoardPlugIn;
194     Item.State := TGikoDownloadState( boardPlugIn.DownloadThread( DWORD( FItem.FThreadItem ) ) );
195     end;
196     end;
197     end;
198     end;
199     if Length(FDownloadTitle) = 0 then
200     FDownloadTitle := '?スi?ス?ス?ス?ス?スs?ス?ス?スj';
201    
202     if boardPlugIn <> nil then begin
203 yoffy 1.6.2.2 if FAbort then begin
204 yoffy 1.6.2.1 Item.State := gdsAbort;
205 yoffy 1.6.2.2 end;
206 yoffy 1.6.2.1 if Assigned( OnDownloadEnd ) then
207     Synchronize( FireDownloadEnd );
208     if Terminated then
209     Break;
210    
211     Suspend;
212     Continue;
213     end;
214    
215     //===== ?スv?ス?ス?スO?スC?ス?ス?ス?ス?スg?スp?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス
216 hi_ 1.1 FAbort := False;
217     FIndy.Request.CustomHeaders.Clear;
218     FIndy.Response.Clear;
219     FIndy.Request.Clear;
220 yoffy 1.6.2.1 FIndy.ProxyParams.Clear;
221     FIndy.Disconnect;
222 hi_ 1.1 FIndy.Request.UserAgent := GikoSys.GetUserAgent;
223     FIndy.RecvBufferSize := Gikosys.Setting.RecvBufferSize;
224     FIndy.ProxyParams.BasicAuthentication := False;
225     {$IFDEF DEBUG}
226     Writeln('------------------------------------------------------------');
227     {$ENDIF}
228     //FIndy.AllowCookies := False;
229     if GikoSys.Setting.ReadProxy then begin
230     if GikoSys.Setting.ProxyProtocol then
231     FIndy.ProtocolVersion := pv1_1
232     else
233     FIndy.ProtocolVersion := pv1_0;
234     FIndy.ProxyParams.ProxyServer := GikoSys.Setting.ReadProxyAddress;
235     FIndy.ProxyParams.ProxyPort := GikoSys.Setting.ReadProxyPort;
236     FIndy.ProxyParams.ProxyUsername := GikoSys.Setting.ReadProxyUserID;
237     FIndy.ProxyParams.ProxyPassword := GikoSys.Setting.ReadProxyPassword;
238     if GikoSys.Setting.ReadProxyUserID <> '' then
239     FIndy.ProxyParams.BasicAuthentication := True;
240     {$IFDEF DEBUG}
241     Writeln('?スv?ス?ス?スL?スV?ス?ス?ス?ス?ス?ス?ス?ス');
242     Writeln('?スz?スX?スg: ' + GikoSys.Setting.ReadProxyAddress);
243     Writeln('?ス|?ス[?スg: ' + IntToStr(GikoSys.Setting.ReadProxyPort));
244     {$ENDIF}
245     end else begin
246     if GikoSys.Setting.Protocol then
247     FIndy.ProtocolVersion := pv1_1
248     else
249     FIndy.ProtocolVersion := pv1_0;
250     FIndy.ProxyParams.ProxyServer := '';
251     FIndy.ProxyParams.ProxyPort := 80;
252     FIndy.ProxyParams.ProxyUsername := '';
253     FIndy.ProxyParams.ProxyPassword := '';
254     {$IFDEF DEBUG}
255     Writeln('?スv?ス?ス?スL?スV?ス?ス?ス?ス?ス?ス?ス?ス');
256     {$ENDIF}
257     end;
258    
259 yoffy 1.6.2.2 adjustMargin := 0;
260     if Item.DownType = gdtThread then begin
261     if FileExists( Item.ThreadItem.GetThreadFileName ) then begin
262     // dat ?スt?ス@?スC?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?スo?ス?ス
263     SetLength( lastContent, ADJUST_MARGIN + 1 );
264     logFile := TFileStream.Create( Item.ThreadItem.GetThreadFileName, fmOpenRead or fmShareDenyWrite );
265     try
266     logFile.Seek( -(ADJUST_MARGIN + 1), soFromEnd );
267     logFile.Read( lastContent[ 1 ], ADJUST_MARGIN + 1 );
268     lastContent := StringReplace( lastContent, #13, '', [] ); // CR ?ス?ス?ス?ス?ス?ス
269     finally
270     logFile.Free;
271     end;
272     end else begin
273     lastContent := '';
274     end;
275     adjustMargin := Length( lastContent );
276     end;
277    
278 hi_ 1.1 FIndy.Request.ContentRangeStart := 0;
279     FIndy.Request.LastModified := ZERO_DATE;
280     ResStream := TMemoryStream.Create;
281     try
282     try
283     //********************
284     //DAT or Subject?ス?ス?ス?ス
285     //********************
286     Item.ResponseCode := 0;
287     RangeStart := 0;
288     AdjustLen := 0;
289     Modified := 0;
290     if Item.DownType = gdtBoard then begin
291     {$IFDEF DEBUG}
292     Writeln('Subject?ス?ス?ス?ス');
293     Writeln('URL: ' + Item.Board.GetReadCgiURL);
294     Writeln('Modified: ' + FloatToStr(Item.Board.LastModified));
295     {$ENDIF}
296     URL := Item.Board.GetReadCgiURL;
297 yoffy 1.6.2.2 if Item.ForceDownload then begin
298     // ?ス?ス?ス?ス?ス?ス?ス?ス
299     ATitle := Item.Board.Title;
300     if ATitle = '' then
301     ATitle := '?スi?ス?ス?ス?ス?スs?ス?ス?スj';
302     FMsg := '?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?スs?ス?ス?ス?ス?ス?ス - [' + ATitle + ']';
303     FIcon := gmiWhat;
304     if Assigned(OnDownloadMsg) then
305     Synchronize(FireDownloadMsg);
306     Modified := ZERO_DATE
307     end else begin
308     Modified := Item.Board.LastModified;
309     end;
310 hi_ 1.1 end else if Item.DownType = gdtThread then begin
311     {$IFDEF DEBUG}
312     Writeln('DAT?ス?ス?ス?ス');
313     Writeln('URL: ' + Item.ThreadItem.GetDatURL);
314     Writeln('Modified: ' + FloatToStr(Item.ThreadItem.LastModified));
315     {$ENDIF}
316     URL := Item.ThreadItem.GetDatURL;
317 yoffy 1.6.2.2 if Item.ForceDownload then begin
318     // ?ス?ス?ス?ス?ス?ス?ス?ス
319     ATitle := Item.ThreadItem.Title;
320     if ATitle = '' then
321     ATitle := '?スi?ス?ス?ス?ス?スs?ス?ス?スj';
322     FMsg := '?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?スs?ス?ス?ス?ス?ス?ス - [' + ATitle + ']';
323     FIcon := gmiWhat;
324     if FileExists(ChangeFileExt(Item.FThreadItem.GetThreadFileName,'.NG')) = true then
325     DeleteFile(ChangeFileExt(Item.FThreadItem.GetThreadFileName,'.NG'));
326     if Assigned(OnDownloadMsg) then
327     Synchronize(FireDownloadMsg);
328     Modified := ZERO_DATE;
329     RangeStart := 0;
330     AdjustLen := 0;
331     end else begin
332     Modified := Item.ThreadItem.LastModified;
333     if Item.ThreadItem.Size > 0 then begin
334     {$IFDEF DEBUG}
335     Writeln('RangeStart: ' + IntToStr(Item.ThreadItem.Size));
336     {$ENDIF}
337     // ?ス?ス?ス?ス?ス[?ス?ス?ス`?スF?スb?スN?ス?ス?ス?ス?ス?ス adjustMargin ?スo?スC?スg?スO?ス?ス?ス?ス?ス?ス?ス?ス
338     RangeStart := Item.ThreadItem.Size;
339     AdjustLen := -adjustMargin;
340     end;
341 hi_ 1.1 end;
342     end;
343 yoffy 1.6.2.2 Item.IsAbone := False;
344 hi_ 1.1 DownloadResult := DatDownload(Item.DownType, URL, Modified, RangeStart, AdjustLen);
345     {$IFDEF DEBUG}
346     Writeln('ResponseCode: ' + IntToStr(FIndy.ResponseCode));
347     {$ENDIF}
348     if Item.DownType = gdtThread then begin
349     if Item.ResponseCode = 416 then begin
350 yoffy 1.6.2.2 Item.IsAbone := True;
351 hi_ 1.1 DownloadResult := True;
352 yoffy 1.6.2.2 end else if DownloadResult and (AdjustLen < 0) then begin
353     if Copy( Item.Content, 1, adjustMargin ) <> lastContent then
354     Item.IsAbone := True;
355     end;
356 hi_ 1.1 end;
357    
358     if Trim(FIndy.Response.RawHeaders.Values['Date']) <> '' then begin
359     if Item.DownType = gdtBoard then
360     Item.Board.LastGetTime := MonaUtils.DateStrToDateTime(FIndy.Response.RawHeaders.Values['Date'])
361     else
362     Item.ThreadItem.ParentBoard.LastGetTime := MonaUtils.DateStrToDateTime(FIndy.Response.RawHeaders.Values['Date']);
363     end;
364    
365     if DownloadResult then begin
366     {$IFDEF DEBUG}
367     Writeln('Date:' + FIndy.Response.RawHeaders.Values['Date']);
368     {$ENDIF}
369 yoffy 1.6.2.2 if Item.IsAbone then begin
370 hi_ 1.1 {$IFDEF DEBUG}
371     Writeln('?ス?ス?ス?ス?ス[?ス?ス?ス?ス?スo');
372     {$ENDIF}
373     ATitle := Item.ThreadItem.Title;
374     if ATitle = '' then
375     ATitle := '?スi?ス?ス?ス?ス?スs?ス?ス?スj';
376     //?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?スP?スo?スC?スg?ス?ス?ス?スLF?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?スu?ス?ス?ス?ス?ス[?ス?ス?スv?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス
377     RangeStart := 0;
378     AdjustLen := 0;
379     FMsg := '?ス?ス?スu?ス?ス?ス?ス?ス[?ス?ス?スv?ス?ス?ス?ス?スo?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?スs?ス?ス?ス?ス?ス?ス - [' + ATitle + ']';
380     FIcon := gmiWhat;
381 yoffy 1.6.2.1 if FileExists(ChangeFileExt(Item.FThreadItem.GetThreadFileName,'.NG')) = true then
382     DeleteFile(ChangeFileExt(Item.FThreadItem.GetThreadFileName,'.NG'));
383 hi_ 1.1 if Assigned(OnDownloadMsg) then
384     Synchronize(FireDownloadMsg);
385     if not DatDownload(Item.DownType, URL, ZERO_DATE, RangeStart, AdjustLen) then
386     Item.State := gdsError;
387     {$IFDEF DEBUG}
388     Writeln('?ス?ス?ス?ス?ス[?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス');
389     Writeln('ResponseCode: ' + IntToStr(Item.ResponseCode));
390     {$ENDIF}
391 yoffy 1.6.2.2 end else if (Item.DownType = gdtThread) and (AdjustLen < 0) then begin
392     // ?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?スo?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス[?ス?ス?ス`?スF?スb?スN?スp?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス]?ス?ス?ス?ス?スT?スC?スY?ス?ス?ス?ス?ス?ス
393     Item.Content := Copy(Item.Content, adjustMargin + 1, MaxInt);
394 hi_ 1.1 end;
395     end else begin
396     Item.State := gdsError;
397     if (Item.DownType = gdtBoard) and (Item.ResponseCode = 302) then begin
398     FMsg := '?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス]?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?スX?スV?ス?ス?スs?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス';
399     FIcon := gmiNG;
400     if Assigned(OnDownloadMsg) then
401     Synchronize(FireDownloadMsg);
402     end;
403     end;
404    
405     //********************
406     //dat.gz?ス?ス?ス?ス(1)
407     //********************
408     if (Item.DownType = gdtThread) and (Item.ResponseCode = 302) then begin
409     {$IFDEF DEBUG}
410     Writeln('dat.gz?ス?ス?ス?ス');
411     {$ENDIF}
412     ATitle := Item.ThreadItem.Title;
413     if ATitle = '' then
414     ATitle := '?スi?ス?ス?ス?ス?スs?ス?ス?スj';
415     FMsg := '?ス?スdat?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?スO(dat.gz)?ス?ス?スT?ス?ス?ス?ス?ス?ス - [' + ATitle + ']';
416     FIcon := gmiWhat;
417     if Assigned(OnDownloadMsg) then
418     Synchronize(FireDownloadMsg);
419     URL := Item.ThreadItem.GetDatgzURL;
420     Modified := Item.ThreadItem.LastModified;
421     RangeStart := 0;
422     AdjustLen := 0;
423     if not DatDownload(Item.DownType, URL, Modified, RangeStart, AdjustLen) then
424     Item.State := gdsError;
425     {$IFDEF DEBUG}
426     Writeln('ResponseCode: ' + IntToStr(Item.ResponseCode));
427     {$ENDIF}
428     end;
429    
430     //********************
431     //dat.gz?ス?ス?ス?ス(2)
432     //********************
433     {
434     if (Item.DownType = gdtThread) and (Item.ResponseCode = 302) then begin
435     ATitle := Item.ThreadItem.Title;
436     if ATitle = '' then
437     ATitle := '?スi?ス?ス?ス?ス?スs?ス?ス?スj';
438     FMsg := '?ス?ス?ス?ス?ス?ス?ス?ス?スO(1)?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?スO(2)?ス?ス?ス?ス?スT?ス?ス?ス?ス?ス?ス - [' + ATitle + ']';
439     FIcon := gmiWhat;
440     if Assigned(OnDownloadMsg) then
441     Synchronize(FireDownloadMsg);
442     URL := Item.ThreadItem.GetOldDatgzURL;
443     Modified := Item.ThreadItem.LastModified;
444     RangeStart := 0;
445     AdjustLen := 0;
446     if not DatDownload(Item.DownType, URL, Modified, RangeStart, AdjustLen) then
447     Item.State := gdsError;
448     end;
449     }
450    
451     //********************
452     //offlaw.cgi?ス?ス?ス?ス?ス?ス
453     //********************
454     FSessionID := '';
455     Synchronize(GetSessionID);
456     if (Item.DownType = gdtThread) and (Item.ResponseCode = 302) and (FSessionID <> '') then begin
457     {$IFDEF DEBUG}
458     Writeln('offlaw.cgi?ス?ス?ス?ス?ス?ス');
459     {$ENDIF}
460     ATitle := Item.ThreadItem.Title;
461     if ATitle = '' then
462     ATitle := '?スi?ス?ス?ス?ス?スs?ス?ス?スj';
463     FMsg := '?ス?スdat.gz?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?スofflaw.cgi?ス?ス?ス?ス?スp?ス?ス?ス?ス?ス?ス - [' + ATitle + ']';
464     FIcon := gmiWhat;
465     if Assigned(OnDownloadMsg) then
466     Synchronize(FireDownloadMsg);
467     URL := Item.ThreadItem.GetOfflawCgiURL(FSessionID);
468     Modified := Item.ThreadItem.LastModified;
469     RangeStart := 0;
470     AdjustLen := 0;
471     if not DatDownload(Item.DownType, URL, Modified, RangeStart, AdjustLen) then begin
472     {$IFDEF DEBUG}
473     Writeln('ResponseCode: ' + IntToStr(Item.ResponseCode));
474     {$ENDIF}
475     Item.State := gdsError;
476    
477     if (Item.DownType = gdtThread) and (Item.ResponseCode = 302) then begin
478     FMsg := '?ス?ス?ス?ス?ス?ス?ス]?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?スX?スV?ス?ス?スs?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?スB';
479     FIcon := gmiNG;
480     if Assigned(OnDownloadMsg) then
481     Synchronize(FireDownloadMsg);
482     end;
483    
484     end else begin
485     CgiStatus := ParseCgiStatus(Item.Content);
486     {$IFDEF DEBUG}
487     Writeln('ResponseCode: ' + IntToStr(Item.ResponseCode));
488     {$ENDIF}
489     case CgiStatus.FStatus of
490     gcsOK: begin
491     {$IFDEF DEBUG}
492     Writeln('CGIStatus: OK');
493     {$ENDIF}
494     Item.ResponseCode := 200;
495     Item.Content := DeleteStatusLine(Item.Content);
496     Item.ContentLength := CgiStatus.FSize;
497     end;
498     gcsINCR: begin
499     //?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス
500     {$IFDEF DEBUG}
501     Writeln('CGIStatus: 206');
502     {$ENDIF}
503     Item.ResponseCode := 206;
504     Item.Content := DeleteStatusLine(Item.Content);
505     Item.ContentLength := CgiStatus.FSize;
506     end;
507     gcsERR: begin
508     {$IFDEF DEBUG}
509     Writeln('CGIStatus: 404(ERROR)');
510     {$ENDIF}
511     Item.ResponseCode := 404;
512     Item.State := gdsError;
513     Item.ErrText := CgiStatus.FErrText;
514     end;
515     end;
516     if (Item.ResponseCode = 404) and (AnsiPos('?ス?ス?ス?ス?ス?ス?スO?スq?ス?ス?ス?ス?ス?ス?ス?ス', Item.ErrText) <> 0) then begin
517     {$IFDEF DEBUG}
518     Writeln('?ス?ス?ス?ス?ス?ス?スO?ス?ス?ス?ス');
519     {$ENDIF}
520     ATitle := Item.ThreadItem.Title;
521     if ATitle = '' then
522     ATitle := '?スi?ス?ス?ス?ス?スs?ス?ス?スj';
523     FMsg := '?ス?ス?ス?ス?ス?ス?ス?ス?スO?スq?ス?ス?ス?ス?ス?ス?ス?ス - [' + ATitle + ']';
524     FIcon := gmiWhat;
525     if Assigned(OnDownloadMsg) then
526     Synchronize(FireDownloadMsg);
527     Idx := Pos(' ', Item.ErrText);
528     if Idx <> 0 then begin
529     URL := Copy(Item.ErrText, Idx + 1, Length(Item.ErrText));
530 yoffy 1.6.2.1 if Pos( '://', URL ) = 0 then begin
531     if Pos('../', URL) = 1 then
532     URL := Copy(URL, 4, MaxInt );
533     if Pos( '/', URL ) = 1 then
534     URL := Copy( URL, 2, MaxInt );
535     URL := GikoSys.UrlToServer(Item.ThreadItem.ParentBoard.URL) + URL;
536     end;
537 hi_ 1.1 Modified := Item.ThreadItem.LastModified;
538     RangeStart := 0;
539     AdjustLen := 0;
540     if not DatDownload(Item.DownType, URL, Modified, RangeStart, AdjustLen) then
541     Item.State := gdsError;
542     {$IFDEF DEBUG}
543     Writeln('ResponseCode: ' + IntToStr(Item.ResponseCode));
544     {$ENDIF}
545     end;
546     end;
547     end;
548     end else begin
549     if (Item.DownType = gdtThread) and (Item.ResponseCode = 302) and (FSessionID = '') then begin
550     {$IFDEF DEBUG}
551     Writeln('?ス?ス?スO?スC?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?スO?ス?ス?ス?ス?スs?ス?ス');
552     {$ENDIF}
553     ATitle := Item.ThreadItem.Title;
554     if ATitle = '' then
555     ATitle := '?スi?ス?ス?ス?ス?スs?ス?ス?スj';
556     FMsg := '?ス?ス?ス?ス?スO?スC?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?スT?ス?ス?ス?ス?ス?ス?ス?ス?スo?ス?ス?ス?ス?ス?ス?ス?ス - [' + ATitle + ']';
557     FIcon := gmiSAD;
558     if Assigned(OnDownloadMsg) then
559     Synchronize(FireDownloadMsg);
560     end;
561     end;
562    
563     case Item.ResponseCode of
564     200: Item.State := gdsComplete;
565     206: Item.State := gdsDiffComplete;
566     304: Item.State := gdsNotModify;
567     else
568     Item.State := gdsError;
569     end;
570     {
571     //?ス?ス?ス?ス?ス?ス?スv?ス?ス?ス?ス?ス?ス?スB?スB?スB
572     if (Item.ResponseCode in [200, 206]) and (Item.Content = '') then
573     Item.State := gdsError;
574     Item.LastModified := FIndy.Response.LastModified;
575     //?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?スP?スo?スC?スg?スO?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス}?スC?スi?スX?ス?ス?ス?ス
576     Item.ContentLength := FIndy.Response.ContentLength + AdjustLen;
577     try
578     ResStream.Clear;
579     FIndy.Get(URL, ResStream);
580     Item.Content := GikoSys.GzipDecompress(ResStream, FIndy.Response.ContentEncoding);
581     if (Item.DownType = gdtThread) and (AdjustLen = -1) and (Item.Content[1] <> #10) then begin
582     //?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?スP?スo?スC?スg?ス?ス?ス?スLF?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?スu?ス?ス?ス?ス?ス[?ス?ス?スv?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス
583     //?ス?ス?ス?ス?ス?ス?ス?ス?スb?スZ?ス[?スW?ス\?ス?ス?スC?スx?ス?ス?スg
584     //event
585     FMsg := '?スu?ス?ス?ス?ス?ス[?ス?ス?スv?ス?ス?ス?ス?スo?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?スs?ス?ス?ス?ス?ス?ス';
586     if Assigned(OnDownloadMsg) then
587     Synchronize(FireDownloadMsg);
588     FIndy.Request.ContentRangeStart := 0;
589     FIndy.Request.ContentRangeEnd := 0;
590     AdjustLen := 0;
591     ResStream.Clear;
592     FIndy.Get(URL, ResStream);
593     Item.Content := GikoSys.GzipDecompress(ResStream, FIndy.Response.ContentEncoding);
594     end else if (Item.DownType = gdtThread) and (AdjustLen = -1) and (Item.Content[1] = #10) then begin
595     //?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?スP?スo?スC?スg?ス?ス?ス?スLF?ス?ス?ス?ス?ス?ス?スi?ス?ス?ス?ス?ス?ス?ス?ス?スj?ス?ス?ス?ス?ス?スLF?ス?ス?ス?ス?ス?ス
596     Item.Content := Copy(Item.Content, 2, Length(Item.Content));
597     end;
598     except
599     Item.State := gdsError;
600     end;
601     Item.ResponseCode := FIndy.ResponseCode;
602     }
603     {
604     try
605     ResStream.Clear;
606     FIndy.Get(URL, ResStream);
607     Item.Content := GikoSys.GzipDecompress(ResStream, FIndy.Response.ContentEncoding);
608     except
609     Item.State := gdsError;
610     end;
611    
612     CgiStatus := ParseCgiStatus(Item.Content);
613     if CgiStatus.FStatus = gcsOK then begin
614     if CgiStatus.FSize = 0 then
615     Item.State := gdsNotModify
616     else if Item.DownType = gdtBoard then
617     Item.State := gdsComplete
618     else
619     Item.State := gdsDiffComplete;
620     end else if CgiStatus.FStatus = gcsINCR then begin
621     Item.State := gdsComplete;
622     end else if CgiStatus.FStatus = gcsERR then begin
623     Item.State := gdsError;
624     Item.ErrText := CgiStatus.FErrText;
625     end;
626     Item.ContentLength := CgiStatus.FSize;
627     }
628     except
629     Item.State := gdsError;
630     end;
631     //Item.ResponseCode := FIndy.ResponseCode;
632     if FAbort then
633     Item.State := gdsAbort;
634     finally
635     if Assigned(OnDownloadEnd) then
636     Synchronize(FireDownloadEnd);
637     ResStream.Free;
638     end;
639 yoffy 1.6.2.1
640     FIndy.Request.CustomHeaders.Clear;
641     FIndy.Request.RawHeaders.Clear;
642     FIndy.Request.Clear;
643     FIndy.Response.CustomHeaders.Clear;
644     FIndy.Response.RawHeaders.Clear;
645     FIndy.Response.Clear;
646     FIndy.ProxyParams.Clear;
647    
648 hi_ 1.1 if Terminated then Break;
649     Suspend;
650 yoffy 1.5 end;
651     end;
652    
653     function TDownloadThread.CgiDownload(ItemType: TGikoDownloadType; URL: string; Modified: TDateTime): Boolean;
654     var
655     ResponseCode: Integer;
656     ResStream: TMemoryStream;
657     begin
658     ResponseCode := -1;
659     FIndy.Request.ContentRangeStart := 0;
660     FIndy.Request.ContentRangeEnd := 0;
661    
662     FIndy.Request.CustomHeaders.Clear;
663     if (Modified <> 0) and (Modified <> ZERO_DATE) then begin
664     FIndy.Request.LastModified := modified - OffsetFromUTC;
665     end;
666     FIndy.Request.AcceptEncoding := '';
667 yoffy 1.6.2.1 FIndy.Request.Accept := 'text/html';
668 yoffy 1.5 ResStream := TMemoryStream.Create;
669     try
670     try
671     ResStream.Clear;
672     {$IFDEF DEBUG}
673     Writeln('URL: ' + URL);
674     {$ENDIF}
675     FIndy.Get(URL, ResStream);
676     Item.Content := GikoSys.GzipDecompress(ResStream, FIndy.Response.ContentEncoding);
677     Item.LastModified := FIndy.Response.LastModified;
678     //?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?スP?スo?スC?スg?スO?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス}?スC?スi?スX?ス?ス?ス?ス
679     Item.ContentLength := Length(Item.Content);
680     //?ス?ス?ス?ス?ス?ス?スv?ス?ス?ス?ス?ス?ス?スB?スB?スB
681     if Item.Content = '' then
682     Result := False
683     else
684     Result := True;
685     {$IFDEF DEBUG}
686     Writeln('?ス?ス?ス?ス?ス?ス?ス?ス?スO?ス?ス?ス?ス');
687     {$ENDIF}
688     ResponseCode := FIndy.ResponseCode;
689     except
690     on E: EIdSocketError do begin
691     Item.Content := '';
692     Item.LastModified := ZERO_DATE;
693     Item.ContentLength := 0;
694     Item.ErrText := E.Message;
695     Result := False;
696     ResponseCode := -1;
697 yoffy 1.6.2.1 Screen.Cursor := crDefault;
698 yoffy 1.5 end;
699     on E: EIdConnectException do begin
700     Item.Content := '';
701     Item.LastModified := ZERO_DATE;
702     Item.ContentLength := 0;
703     Item.ErrText := E.Message;
704     Result := False;
705     ResponseCode := -1;
706 yoffy 1.6.2.1 Screen.Cursor := crDefault;
707 yoffy 1.5 end;
708     on E: Exception do begin
709     {$IFDEF DEBUG}
710     Writeln('?ス?ス?ス?ス?ス?ス?ス?ス?スO?ス?ス?ス?ス');
711     Writeln('E.Message: ' + E.Message);
712     {$ENDIF}
713     Item.Content := '';
714     Item.LastModified := ZERO_DATE;
715     Item.ContentLength := 0;
716     Item.ErrText := E.Message;
717     ResponseCode := FIndy.ResponseCode;
718     Result := False;
719 yoffy 1.6.2.1 Screen.Cursor := crDefault;
720 yoffy 1.5 end;
721     end;
722     finally
723     if (Item.ContentLength = 0) and (ResponseCode = 206) then
724     Item.ResponseCode := 304
725     else
726     Item.ResponseCode := ResponseCode;
727     ResStream.Free;
728 hi_ 1.1 end;
729     end;
730    
731     function TDownloadThread.DatDownload(ItemType: TGikoDownloadType; URL: string; Modified: TDateTime; RangeStart: Integer; AdjustLen: Integer): Boolean;
732     var
733     ResponseCode: Integer;
734     ResStream: TMemoryStream;
735     begin
736     ResponseCode := -1;
737     if (ItemType = gdtThread) and (RangeStart > 0) then begin
738     // if (ItemType = gdtThread) and (Item.ThreadItem.Size > 0) then begin
739     // FIndy.Request.ContentRangeStart := Item.ThreadItem.Size + AdjustLen;
740     FIndy.Request.ContentRangeStart := RangeStart + AdjustLen;
741     FIndy.Request.ContentRangeEnd := 0;
742     end else begin
743     FIndy.Request.ContentRangeStart := 0;
744     FIndy.Request.ContentRangeEnd := 0;
745     end;
746    
747     FIndy.Request.CustomHeaders.Clear;
748     FIndy.Request.CacheControl := 'no-cache';
749     FIndy.Request.CustomHeaders.Add('Pragma: no-cache');
750     if (Modified <> 0) and (Modified <> ZERO_DATE) then begin
751     FIndy.Request.LastModified := modified - OffsetFromUTC;
752     //FIndy.Request.CustomHeaders.Add('If-Modified-Since: ' + RFC1123_Date(modified - OffsetFromUTC) + ' GMT');
753     end;
754     // FIndy.Request.AcceptEncoding := 'gzip';
755     if RangeStart = 0 then
756     FIndy.Request.AcceptEncoding := 'gzip'
757     else
758     FIndy.Request.AcceptEncoding := '';
759     ResStream := TMemoryStream.Create;
760     try
761     try
762     ResStream.Clear;
763     {$IFDEF DEBUG}
764     Writeln('URL: ' + URL);
765     {$ENDIF}
766     FIndy.Get(URL, ResStream);
767     Item.Content := GikoSys.GzipDecompress(ResStream, FIndy.Response.ContentEncoding);
768     Item.LastModified := FIndy.Response.LastModified;
769     //?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?スP?スo?スC?スg?スO?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス}?スC?スi?スX?ス?ス?ス?ス
770     // Item.ContentLength := FIndy.Response.ContentLength + AdjustLen;
771     Item.ContentLength := Length(Item.Content) + AdjustLen;
772     //?ス?ス?ス?ス?ス?ス?スv?ス?ス?ス?ス?ス?ス?スB?スB?スB
773     // if (FIndy.ResponseCode in [200, 206]) and (Item.Content = '') then
774     // Result := False
775     if Item.Content = '' then
776     Result := False
777     else
778     Result := True;
779     {$IFDEF DEBUG}
780     Writeln('?ス?ス?ス?ス?ス?ス?ス?ス?スO?ス?ス?ス?ス');
781     {$ENDIF}
782     ResponseCode := FIndy.ResponseCode;
783     except
784     on E: EIdSocketError do begin
785     Item.Content := '';
786     Item.LastModified := ZERO_DATE;
787     Item.ContentLength := 0;
788     Item.ErrText := E.Message;
789     Result := False;
790     ResponseCode := -1;
791 yoffy 1.6.2.1 Screen.Cursor := crDefault;
792 hi_ 1.1 end;
793     on E: EIdConnectException do begin
794     Item.Content := '';
795     Item.LastModified := ZERO_DATE;
796     Item.ContentLength := 0;
797     Item.ErrText := E.Message;
798     Result := False;
799     ResponseCode := -1;
800 yoffy 1.6.2.1 Screen.Cursor := crDefault;
801 hi_ 1.1 end;
802     on E: Exception do begin
803     {$IFDEF DEBUG}
804     Writeln('?ス?ス?ス?ス?ス?ス?ス?ス?スO?ス?ス?ス?ス');
805     Writeln('E.Message: ' + E.Message);
806     {$ENDIF}
807     Item.Content := '';
808     Item.LastModified := ZERO_DATE;
809     Item.ContentLength := 0;
810     Item.ErrText := E.Message;
811     ResponseCode := FIndy.ResponseCode;
812     Result := False;
813 yoffy 1.6.2.1 Screen.Cursor := crDefault;
814 hi_ 1.1 end;
815     end;
816     finally
817     if (Item.ContentLength = 0) and (ResponseCode = 206) then
818     Item.ResponseCode := 304
819     else
820     Item.ResponseCode := ResponseCode;
821     ResStream.Free;
822     end;
823     end;
824    
825     procedure TDownloadThread.FireDownloadEnd;
826     begin
827     OnDownloadEnd(self, Item);
828     end;
829    
830     procedure TDownloadThread.FireDownloadMsg;
831     begin
832     OnDownloadMsg(Self, Item, FMsg, FIcon);
833     end;
834    
835     procedure TDownloadThread.GetSessionID;
836     begin
837     FSessionID := GikoSys.Dolib.SessionID;
838     end;
839    
840     procedure TDownloadThread.Abort;
841     begin
842     FAbort := True;
843     FIndy.DisconnectSocket;
844 yoffy 1.6.2.2 if socket <> nil then begin
845     socket.DisconnectSocket;
846     end;
847 hi_ 1.1 end;
848    
849     procedure TDownloadThread.WorkBegin(Sender: TObject; AWorkMode: TWorkMode; const AWorkCountMax: Integer);
850     begin
851     if Assigned(OnWorkBegin) then
852 yoffy 1.6.2.1 OnWorkBegin(Sender, AWorkMode, AWorkCountMax, FNumber, FDownloadTitle);
853 hi_ 1.1 end;
854    
855     procedure TDownloadThread.WorkEnd(Sender: TObject; AWorkMode: TWorkMode);
856     begin
857     if Assigned(OnWorkEnd) then
858     OnWorkEnd(Sender, AWorkMode, FNumber);
859     end;
860    
861     procedure TDownloadThread.Work(Sender: TObject; AWorkMode: TWorkMode; const AWorkCount: Integer);
862     begin
863     if Assigned(OnWork) then
864     OnWork(Sender, AWorkMode, AWorkCount, FNumber);
865     end;
866    
867     function TDownloadThread.ParseCgiStatus(Content: string): TCgiStatus;
868     var
869     StatusLine: string;
870     Line: string;
871     Idx: Integer;
872     Status: string;
873     Size: string;
874     Msg: string;
875     begin
876     // [+OK] ?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス
877     // [-INCR] (Incorrect)?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?スf?ス[?ス^
878     // [-ERR (?スe?スL?スX?スg)]?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?スG?ス?ス?ス[
879     // ?ス?ス?スF+OK 23094/512K
880 yoffy 1.6.2.1 // -INCR 23094/512K
881     // -ERR ?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス
882 hi_ 1.1 Idx := AnsiPos(#10, Content);
883     StatusLine := Copy(Content, 0, Idx);
884    
885     Idx := AnsiPos(' ', Content);
886     Status := Copy(StatusLine, 0, Idx - 1);
887     Line := Copy(StatusLine, Idx + 1, Length(StatusLine));
888    
889     // Idx := AnsiPos('/', Line);
890     if Trim(Status) = '-ERR' then
891     Msg := Trim(Line)
892     else
893     Size := Copy(Line, 0, Idx - 1);
894    
895     if Trim(Status) = '+OK' then
896     Result.FStatus := gcsOK
897     else if Trim(Status) = '-INCR' then
898     Result.FStatus := gcsINCR
899     else if Trim(Status) = '-ERR' then begin
900     Result.FStatus := gcsERR;
901     Result.FErrText := Msg;
902     Result.FSize := 0;
903     Exit;
904     end else begin
905     {$IFDEF DEBUG}
906     Writeln(Status);
907     {$ENDIF}
908     Result.FStatus := gcsERR;
909     Result.FErrText := '?スG?ス?ス?ス[?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?スA?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?スG?ス?ス?ス[';
910     Result.FSize := 0;
911     Exit;
912     end;
913    
914     if GikoSys.IsNumeric(Size) then
915     Result.FSize := StrToInt(Size)
916     else begin
917     Result.FSize := 0;
918     Result.FStatus := gcsERR;
919     Result.FErrText := '?スX?スe?ス[?ス^?スX?ス?ス?ス?ス?ス?ス?スs[' + StatusLine + ']';
920     end;
921     end;
922    
923     //?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス1?スs?ス?ス?ス?ス?ス?ス?ス?ス
924     function TDownloadThread.DeleteStatusLine(Content: string): string;
925     var
926     SList: TStringList;
927     begin
928     SList := TStringList.Create;
929     try
930     SList.Text := Content;
931     if SList.Count > 1 then
932     SList.Delete(0);
933     Result := SList.Text;
934     finally
935     SList.Free;
936     end;
937     end;
938    
939     procedure TDownloadItem.SaveListFile;
940     var
941     i: Integer;
942     index: Integer;
943     NewItem: TThreadItem;
944     NumCount: Integer;
945     Body: TStringList;
946     Rec: TSubjectRec;
947 yoffy 1.6.2.1 function MakeThreadCallBack(
948     inInstance : DWORD; // TBoardItem ?ス?ス?スC?ス?ス?スX?ス^?ス?ス?スX
949     inURL : PChar; // ?スX?ス?ス?スb?スh?ス?ス URL
950     inTitle : PChar; // ?スX?ス?ス?ス^?スC
951     inCount : DWORD // ?ス?ス?スX?ス?ス?ス?ス
952     ) : Boolean; stdcall; // ?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス True
953     var
954     _ThreadItem : TThreadItem; // '_' ?ス?ス?スN?ス?ス?スX?ス?ス?スv?ス?ス?スp?スe?スB?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス
955     boardItem : TBoard;
956     begin
957     Result := True;
958     boardItem := TBoard( inInstance );
959    
960     boardItem.IntData := boardItem.IntData + 1;
961     index := boardItem.GetIndexFromURL( string( inURL ) );
962     if index = -1 then begin
963     //?スV?ス?ス?ス?ス?スX?ス?ス?スb?スh
964     _ThreadItem := TThreadItem.Create( boardItem.BoardPlugIn, string( inURL ) );
965    
966     _ThreadItem.Title := string( inTitle );
967     _ThreadItem.AllResCount := inCount;
968     _ThreadItem.ParentBoard := Board;
969     _ThreadItem.No := boardItem.IntData;
970     _ThreadItem.RoundDate := ZERO_DATE;
971     _ThreadItem.LastModified := ZERO_DATE;
972     _ThreadItem.AgeSage := gasNew;
973 yoffy 1.6.2.2 boardItem.Add(_ThreadItem);
974 yoffy 1.6.2.1 end else begin
975     if boardItem.Items[index].No > boardItem.IntData then
976     boardItem.Items[index].AgeSage := gasAge
977     else if boardItem.Items[index].AllResCount < inCount then
978     boardItem.Items[index].AgeSage := gasSage
979     else
980     boardItem.Items[index].AgeSage := gasNone;
981    
982     boardItem.Items[index].No := boardItem.IntData;
983     boardItem.Items[index].AllResCount := inCount;
984     end;
985     end;
986 hi_ 1.1 begin
987 yoffy 1.6.2.2 //Board.ListData := TList.Create;
988 hi_ 1.1 Body := TStringList.Create;
989     try
990     //?ス_?スE?ス?ス?ス?ス?ス[?スh?ス?ス?ス?ス?ス?ス?ス?ス?スi?ス?ス?ス[?スJ?ス?ス?ス?ス?ス?ス?スj
991     Board.RoundDate := Now;
992     //?スT?ス[?スo?ス?ス?スt?ス@?スC?ス?ス?ス?ス?スX?スV?ス?ス?ス?ス?ス?ス?ス?ス
993     Board.LastModified := LastModified;
994    
995 yoffy 1.6.2.2 //dat?ス?ス?ス?ス?スX?ス?ス?ス?ス?ス\?ス[?スg?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス\?ス[?スg?ス?ス?ス?ス
996     if GikoSys.Setting.DatOchiSortIndex >= 0 then begin
997     Sort.SortNoFlag := true;
998     Sort.SortOrder := GikoSys.Setting.DatOchiSortOrder;
999     Sort.SortIndex := GikoSys.Setting.DatOchiSortIndex;
1000     //Sort.SortNonAcquiredCountFlag := GikoSys.Setting.NonAcquiredCount;
1001     Board.CustomSort(ThreadItemSortProc);
1002     end;
1003    
1004     for i := Board.Count - 1 downto 0 do
1005     Board.Items[i].AgeSage := gasNull;
1006    
1007 yoffy 1.6.2.1 if Board.IsBoardPlugInAvailable then begin
1008     // ?スV?ス?ス?ス?ス?ス?ス?スX?スg?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス
1009     // ?スV?ス?ス?ス?ス?ス?ス?スX?スg?ス?ス?ス?ス?ス?ス?ス?ス?スX?スg?ス?ス?ス?ス?スO?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?スV?ス?ス?ス?ス?ス?ス?スX?スg?ス?ス?ス?ス?ス?ス
1010     // ?ス?ス?ス?ス?ス?ス?スO?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?スA?スV?ス?ス?ス?ス?スX?ス?ス?スI?スu?スW?スF?スN?スg?ス?ス?ス?ス?ス?ス
1011     Board.IntData := 0;
1012     Board.BoardPlugIn.EnumThread( DWORD( Board ), @MakeThreadCallBack );
1013    
1014 yoffy 1.6.2.2 //?ス?ス?ス?ス?ス?ス?スX?スg?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス
1015     for i := Board.Count - 1 downto 0 do begin
1016     if( Board.Items[i].AgeSage = gasNull )and not (Board.Items[i].IsLogFile) then
1017     Board.Delete(i);
1018     end;
1019    
1020 yoffy 1.6.2.1 // ?スV?ス?ス?ス?ス?ス?ス?スX?スg?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?スA?スC?スe?ス?ス?ス?ス?スV?ス?ス?ス?ス?ス?ス?スX?スg?ス?ス?ス?ス?ス?ス
1021     for i := 0 to Board.Count - 1 do begin
1022 yoffy 1.6.2.2 if(Board.Items[i].AgeSage = gasNull) and (Board.Items[i].IsLogFile) then begin
1023 yoffy 1.6.2.1 Board.IntData := Board.IntData + 1;
1024     Board.Items[i].No := Board.IntData;
1025     Board.Items[i].AllResCount := Board.Items[i].Count;
1026     Board.Items[i].NewResCount := 0;
1027     Board.Items[i].AgeSage := gasNone;
1028     end;
1029     end;
1030     end else begin
1031     //?スV?ス?ス?ス?ス?ス?ス?スX?スg?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス
1032     //?スV?ス?ス?ス?ス?ス?ス?スX?スg?ス?ス?ス?ス?ス?ス?ス?ス?スX?スg?ス?ス?ス?ス?スO?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?スV?ス?ス?ス?ス?ス?ス?スX?スg?ス?ス?ス?ス?ス?ス
1033     //?ス?ス?ス?ス?ス?ス?スO?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?スA?スV?ス?ス?ス?ス?スX?ス?ス?スI?スu?スW?スF?スN?スg?ス?ス?ス?ス?ス?ス
1034     Body.Text := Content;
1035     NumCount := 0;
1036     for i := 0 to Body.Count - 1 do begin
1037     Rec := GikoSys.DivideSubject(Body[i]);
1038     Rec.FFileName := Trim(Rec.FFileName);
1039     if (Rec.FTitle = '') and (Rec.FCount = 0) then Continue;
1040     Inc(NumCount);
1041     index := Board.GetIndexFromFileName(Rec.FFileName);
1042     if index = -1 then begin
1043     //?スV?ス?ス?ス?ス?スX?ス?ス?スb?スh
1044     NewItem := TThreadItem.Create(
1045 yoffy 1.6.2.2 nil, GikoSys.Get2chBoard2ThreadURL( Board, ChangeFileExt( Rec.FFileName, '' ) ) );
1046 yoffy 1.6.2.1 NewItem.Title := Rec.FTitle;
1047     NewItem.AllResCount := Rec.FCount;
1048     NewItem.ParentBoard := Board;
1049     NewItem.No := NumCount;
1050     NewItem.RoundDate := ZERO_DATE;
1051     NewItem.LastModified := ZERO_DATE;
1052     NewItem.AgeSage := gasNew;
1053 yoffy 1.6.2.2 Board.Add(NewItem);
1054 yoffy 1.6.2.1 end else begin
1055     if Board.Items[index].No > NumCount then
1056     Board.Items[index].AgeSage := gasAge
1057     else if Board.Items[index].AllResCount < Rec.FCount then
1058     Board.Items[index].AgeSage := gasSage
1059     else
1060     Board.Items[index].AgeSage := gasNone;
1061 hi_ 1.1
1062 yoffy 1.6.2.1 Board.Items[index].No := NumCount;
1063     Board.Items[index].AllResCount := Rec.FCount;
1064     end;
1065 hi_ 1.1 end;
1066 yoffy 1.6.2.2 //?ス?ス?ス?ス?ス?ス?スX?スg?ス?ス?ス?ス?ス?ス
1067     for i := Board.Count - 1 downto 0 do begin
1068     if( Board.Items[i].AgeSage = gasNull )and not (Board.Items[i].IsLogFile) then
1069     Board.Delete(i);
1070     end;
1071 hi_ 1.1
1072 yoffy 1.6.2.2 //?スV?ス?ス?ス?ス?ス?ス?スX?スg?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?スA?スC?スe?ス?ス?ス?ス?スX?スV
1073 yoffy 1.6.2.1 for i := 0 to Board.Count - 1 do begin
1074 yoffy 1.6.2.2 if( Board.Items[i].AgeSage = gasNull )and (Board.Items[i].IsLogFile) then begin
1075 yoffy 1.6.2.1 inc(NumCount);
1076     Board.Items[i].No := NumCount;
1077     Board.Items[i].AllResCount := Board.Items[i].Count;
1078     Board.Items[i].NewResCount := 0;
1079     Board.Items[i].AgeSage := gasNone;
1080     end;
1081 hi_ 1.1 end;
1082 yoffy 1.6.2.1 //?ス?ス?スX?スg(subject.txt)?ス?ス?ス?ス?ス?ス
1083     GikoSys.ForceDirectoriesEx(ExtractFilePath(Board.GetSubjectFileName));
1084     Body.SaveToFile(Board.GetSubjectFileName);
1085     end;
1086 hi_ 1.1 finally
1087     Body.Free;
1088     end;
1089 yoffy 1.6.2.2
1090    
1091 hi_ 1.1 end;
1092    
1093     {procedure TDownloadItem.SaveListFile;
1094     var
1095     i: Integer;
1096     index: Integer;
1097     NewItem: TThreadItem;
1098     NewList: TList;
1099     // SaveCount: Integer;
1100     NumCount: Integer;
1101     Body: TStringList;
1102     Rec: TSubjectRec;
1103     begin
1104     NewList := TList.Create;
1105     Body := TStringList.Create;
1106     try
1107     //?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス
1108     Board.RoundDate := Now;
1109     //?スT?ス[?スo?ス?ス?スt?ス@?スC?ス?ス?ス?ス?スX?スV?ス?ス?ス?ス?ス?ス?ス?ス
1110     Board.LastModified := LastModified;
1111    
1112     //?ス?ス?スX?スg?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス
1113     //SaveCount := MaxInt;
1114    
1115     //?ス?ス?ス?ス?ス?ス?スX?スg?ス?ス?ス?ス?ス?ス?スO?ス?ス?ス?ス?スA?スC?スe?ス?ス?ス?ス?ス?ス?ス?ス
1116     for i := Board.Count - 1 downto 0 do
1117     if not Board.Items[i].IsLogFile then
1118     Board.Delete(i);
1119    
1120     //?スV?ス?ス?ス?ス?ス?ス?スX?スg?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス
1121     //?スV?ス?ス?ス?ス?ス?ス?スX?スg?ス?ス?ス?ス?ス?ス?ス?ス?スX?スg?ス?ス?ス?ス?スO?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?スV?ス?ス?ス?ス?ス?ス?スX?スg?ス?ス?ス?ス?ス?ス
1122     //?ス?ス?ス?ス?ス?ス?スO?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?スA?スV?ス?ス?ス?ス?スX?ス?ス?スI?スu?スW?スF?スN?スg?ス?ス?ス?ス?ス?ス
1123     Body.Text := Content;
1124     // Loop := Min(Body.Count, SaveCount);
1125     NumCount := 0;
1126     // for i := 0 to Loop - 1 do begin
1127     for i := 0 to Body.Count - 1 do begin
1128     if i = 0 then Continue; //?スP?スs?ス?ス?ス?ス?スX?スe?ス[?ス^?スX?スs?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス
1129    
1130     Rec := GikoSys.DivideSubject(Body[i]);
1131     if (Rec.FTitle = '') and (Rec.FCount = 0) then Continue;
1132     Inc(NumCount);
1133     index := Board.GetIndex(Rec.FFileName);
1134     if index = -1 then begin
1135     NewItem := TThreadItem.Create;
1136     NewItem.FileName := Rec.FFileName;
1137     NewItem.Title := Rec.FTitle;
1138     NewItem.Count := Rec.FCount;
1139     NewItem.ParentBoard := Board;
1140     NewItem.No := NumCount;
1141     NewItem.RoundDate := ZERO_DATE;
1142     NewItem.LastModified := ZERO_DATE;
1143     NewList.Add(NewItem);
1144     end else begin
1145     //Board.Items[index].Count := Count;
1146     Board.Items[index].No := NumCount;
1147     NewList.Add(Board.Items[index]);
1148     Board.DeleteList(index);
1149     end;
1150     end;
1151    
1152     //?スV?ス?ス?ス?ス?ス?ス?スX?スg?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?スO?スL?ス?ス?スA?スC?スe?ス?ス?ス?ス?スV?ス?ス?ス?ス?ス?ス?スX?スg?ス?ス?ス?ス?ス?ス
1153     for i := 0 to Board.Count - 1 do begin
1154     inc(NumCount);
1155     Board.Items[i].No := NumCount;
1156     NewList.Add(Board.Items[i]);
1157     end;
1158    
1159     //?ス?ス?ス?ス?ス?ス?スX?スg?ス?ス?ス?ス?ス?ス?スi?ス?ス?スX?スg?ス?ス?ス?ス?スB?スX?ス?ス?スI?スu?スW?スF?スN?スg?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?スj
1160     for i := Board.Count - 1 downto 0 do
1161     Board.DeleteList(i);
1162    
1163     //?スV?ス?ス?ス?ス?ス?ス?スX?スg?ス?ス?ス{?ス[?スh?スI?スu?スW?スF?スN?スg?ス?ス?ス?ス?ス?ス
1164     for i := 0 to NewList.Count - 1 do
1165     Board.Add(TThreadItem(NewList[i]));
1166    
1167     //?ス?ス?スX?スg(subject.txt)?ス?ス?ス?ス?ス?ス
1168     // GikoSys.ForceDirectoriesEx(GikoSys.GetLogDir + Board.BBSID);
1169     // Body.SaveToFile(GikoSys.GetSubjectFileName(Board.BBSID));
1170     GikoSys.ForceDirectoriesEx(ExtractFilePath(Board.GetSubjectFileName));
1171     Body.SaveToFile(Board.GetSubjectFileName);
1172     finally
1173     Body.Free;
1174     NewList.Free;
1175     end;
1176     end;
1177     }
1178     procedure TDownloadItem.SaveItemFile;
1179     var
1180     Body: TStringList;
1181     Cnt: Integer;
1182     OldCnt: Integer;
1183     FileName: string;
1184     ini: TMemIniFile;
1185     Res: TResRec;
1186     NewRes: Integer;
1187 yoffy 1.6.2.2 finish : Boolean;
1188     loopCnt : Integer;
1189     KokoTxt : string;
1190     KokoIdx : Integer;
1191     NewTxt : string;
1192     NewIdx : Integer;
1193     LastTxt : string;
1194     LastIdx : Integer;
1195 hi_ 1.1 begin
1196     FileName := ThreadItem.GetThreadFileName;
1197    
1198 yoffy 1.6.2.1 if not ThreadItem.IsBoardPlugInAvailable then begin
1199     if Trim(Content) = '' then
1200     Exit;
1201 yoffy 1.6.2.2
1202 yoffy 1.6.2.1 GikoSys.ForceDirectoriesEx(ExtractFilePath(FileName));
1203    
1204 yoffy 1.6.2.2 // Cnt := 0;
1205 yoffy 1.6.2.1 Body := TStringList.Create;
1206 yoffy 1.6.2.2 NewRes := 0;
1207     OldCnt := 0;
1208 yoffy 1.6.2.1 try
1209 yoffy 1.6.2.2 // if FileExists(FileName) and (ResponseCode = 206) then begin
1210 yoffy 1.6.2.1 if FileExists(FileName) and (State = gdsDiffComplete) then begin
1211 yoffy 1.6.2.2 // Body.Text := Content;
1212     // if Body.Count > 0 then
1213     // Body.Delete(0);
1214     // Content := Body.Text;
1215     loopCnt := 10;
1216 yoffy 1.6.2.1 repeat
1217 yoffy 1.6.2.2 finish := true;
1218     try
1219 yoffy 1.6.2.1 Body.LoadFromFile(FileName);
1220     OldCnt := Body.Count;
1221     Body.Text := Body.Text + Content;
1222     Body.SaveToFile(FileName);
1223     NewRes := Body.Count - OldCnt;
1224 yoffy 1.6.2.2 except
1225     on E:EFOpenError do begin
1226     sleep(10);
1227     finish := false;
1228     Dec(loopCnt);
1229     end;
1230     end;
1231     until finish and ( loopCnt > 0 );
1232 yoffy 1.6.2.1 //Cnt := Body.Count;
1233     end else begin
1234 yoffy 1.6.2.2 if IsAbone then begin
1235     // ?ス?ス?ス?ス?ス[?ス?ス?ス?ス?ス?ス?スo?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?スV?ス?ス?ス?ス?スX?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス
1236     loopCnt := 10;
1237     repeat
1238     finish := true;
1239     try
1240     Body.LoadFromFile(FileName);
1241     except
1242     on E:EFOpenError do begin
1243     sleep(10);
1244     finish := false;
1245     Dec(loopCnt);
1246     end;
1247     end;
1248     until finish and ( loopCnt > 0 );
1249     LastTxt := Body.Strings[ Body.Count - 1 ];
1250     if ThreadItem.Kokomade > 0 then begin
1251     KokoTxt := Body.Strings[ ThreadItem.Kokomade - 1 ];
1252     end;
1253     if ThreadItem.NewReceive > 0 then begin
1254     NewTxt := Body.Strings[ ThreadItem.NewReceive - 1 ];
1255     end;
1256    
1257     Body.Text := Content;
1258     Body.Find( LastTxt, LastIdx );
1259     OldCnt := LastIdx + 1;
1260     NewRes := Body.Count - OldCnt;
1261    
1262     if ThreadItem.Kokomade > 0 then begin
1263     Body.Find( KokoTxt, KokoIdx );
1264     ThreadItem.Kokomade := KokoIdx + 1;
1265     end;
1266     if ThreadItem.NewReceive > 0 then begin
1267     Body.Find( NewTxt, NewIdx );
1268     Inc( NewIdx );
1269     if OldCnt < NewIdx then begin
1270     OldCnt := NewIdx;
1271     NewRes := Body.Count - NewIdx;
1272     end;
1273     end;
1274     end else begin
1275     Body.Text := Content;
1276     //ThreadItem.Count := 0;
1277     OldCnt := 0;
1278     NewRes := Body.Count;
1279     //Cnt := Body.Count;
1280     end;
1281 yoffy 1.6.2.1 // if Body.Count > 0 then
1282     // Body.Delete(0);
1283     Body.SaveToFile(FileName);
1284    
1285     if ThreadItem.Title = '' then begin
1286     Res := GikoSys.DivideStrLine(Body[0]);
1287     ThreadItem.Title := Res.FTitle;
1288     end;
1289     ThreadItem.Size := 0;
1290 hi_ 1.1 end;
1291     Cnt := Body.Count;
1292 yoffy 1.6.2.1 finally
1293     Body.Free;
1294 hi_ 1.1 end;
1295 yoffy 1.6.2.2
1296 yoffy 1.6.2.1 ThreadItem.Size := ThreadItem.Size + ContentLength;
1297     ThreadItem.LastModified := LastModified;
1298     ThreadItem.Count := Cnt;
1299     //ThreadItem.AllResCount := Cnt;
1300     ThreadItem.NewResCount := NewRes;
1301     ThreadItem.NewReceive := OldCnt + 1;
1302 hi_ 1.1 end;
1303 yoffy 1.6.2.2 ThreadItem.AllResCount := ThreadItem.Count;
1304 hi_ 1.1 ThreadItem.IsLogFile := True;
1305 yoffy 1.6.2.1 ThreadItem.RoundDate := Now;
1306 hi_ 1.1 ThreadItem.UnRead := True;
1307     ThreadItem.ParentBoard.UnRead := ThreadItem.ParentBoard.UnRead + 1;
1308     // if ThreadItem.RoundNo = 6 then
1309     // ThreadItem.RoundNo := 0;
1310    
1311     //?ス?ス?ス?ス?スI?ス?ス?ス?ス?ス?ス?スC?ス?ス?スf?スb?スN?スX?ス?ス?スX?スV?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?スA?スe?ス?ス?ス|?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?スB
1312     //?ス?ス?ス?ス?スI?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス
1313     //?ス?ス?ス?ス?スI?ス?ス?ス?ス?ス?ス?スA?ス?ス?ス?ス?スN?ス?ス?ス?ス?ス?ス?スe?ス?ス?ス|?ス?ス?ス?ス?ス?ス?ス?ス?ス?ス?スX?スV
1314     ini := TMemIniFile.Create(ChangeFileExt(FileName, '.tmp'));
1315     try
1316     ini.WriteDateTime('Setting', 'RoundDate', ThreadItem.RoundDate);
1317     ini.WriteDateTime('Setting', 'LastModified', ThreadItem.LastModified);
1318     ini.WriteInteger('Setting', 'Size', ThreadItem.Size);
1319     ini.WriteInteger('Setting', 'Count', ThreadItem.Count);
1320     ini.WriteInteger('Setting', 'AllResCount', ThreadItem.AllResCount);
1321     ini.WriteInteger('Setting', 'NewResCount', ThreadItem.NewResCount);
1322     ini.WriteInteger('Setting', 'NewReceive', ThreadItem.NewReceive);
1323     // ini.WriteInteger('Setting', 'RoundNo', ThreadItem.RoundNo);
1324     ini.WriteBool('Setting', 'Round', ThreadItem.Round);
1325     ini.WriteBool('Setting', 'UnRead', ThreadItem.UnRead);
1326 yoffy 1.6.2.2 ini.UpdateFile;
1327 hi_ 1.1 finally
1328     ini.Free;
1329     end;
1330     end;
1331    
1332     end.

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26