Develop and Download Open Source Software

Browse CVS Repository

Contents of /gikonavigoeson/gikonavi/ItemDownload.pas

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


Revision 1.43 - (show annotations) (download) (as text)
Sat Jun 25 11:27:21 2005 UTC (18 years, 9 months ago) by h677
Branch: MAIN
CVS Tags: v1_50_0_590, merged-remodeling, root-of-Bb50
Branch point for: Bb50
Changes since 1.42: +58 -11 lines
File MIME type: text/x-pascal
remodelingブランチから、最新版をマージ

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

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