6 Windows, SysUtils, Classes, ComCtrls, Controls, Forms, IdHTTP,
7 {HTTPApp,} YofUtils, IdGlobal, IdException, IdComponent, IniFiles, {DateUtils,}
8 GikoSystem, BoardGroup, ExternalBoardManager, ExternalBoardPlugInMain,
9 Sort, SyncObjs, bmRegExp;
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);
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;
25 FStatus: TGikoCgiStatus;
31 //FWorkCS: TCriticalSection;
32 //IdHttp
\82ÌOnWork
\81AOnWorkBegin,OnWorkEnd
\82Í
\95Ê
\82Ì
\83X
\83\8c\83b
\83h
\82©
\82ç
33 //
\8cÄ
\82Î
\82ê
\82é
\88×
\81ASynchronize
\82Å
\93¯
\8aú
\82·
\82é
\95K
\97v
\82ª
\82 \82é
\81B
34 //
\83N
\83\8a\83e
\83B
\83J
\83\8b\83Z
\83N
\83V
\83\87\83\93\82Í
\96³
\82
\82Ä
\82à
\82½
\82Ô
\82ñ
\95½
\8bC
\82¾
\82¯
\82Ç
\97p
\90S
\82Ì
\88×
\81B by eggcake
35 FWorkCS: TCriticalSection;
37 FAWorkMode: TWorkMode;
39 FAWorkCountMax: Integer
41 TDownloadThread = class(TThread)
48 FIcon: TGikoMessageIcon;
50 FOnWork: TGikoWorkEvent;
51 FOnWorkBegin: TGikoWorkBeginEvent;
52 FOnWorkEnd: TGikoWorkEndEvent;
53 FOnDownloadEnd: TDownloadEndEvent;
54 FOnDownloadMsg: TDownloadMsgEvent;
55 FDownloadTitle: string;
58 procedure FireDownloadEnd;
59 procedure FireDownloadMsg;
60 procedure GetSessionID;
61 procedure WorkBegin(Sender: TObject; AWorkMode: TWorkMode; const AWorkCountMax: Integer);
62 procedure WorkEnd(Sender: TObject; AWorkMode: TWorkMode);
63 procedure Work(Sender: TObject; AWorkMode: TWorkMode; const AWorkCount: Integer);
64 function ParseCgiStatus(Content: string): TCgiStatus;
65 function ParseRokkaStatus(Content: string): TCgiStatus;
66 function CgiDownload(ItemType: TGikoDownloadType; URL: string; Modified: TDateTime): Boolean;
67 function DatDownload(ItemType: TGikoDownloadType; URL: string; Modified: TDateTime; RangeStart: Integer; AdjustLen: Integer): Boolean;
68 procedure DeleteStatusLine(Item: TDownloadItem);
69 procedure InitHttpClient(client: TIdHttp);
70 procedure ClearHttpClient(client: TIdHttp);
72 procedure FireWorkBegin;
73 procedure FireWorkEnd;
74 procedure GetLastModified;
76 procedure Execute; override;
78 property Item: TDownloadItem read FItem write FItem;
79 property Number: Integer read FNumber write FNumber;
80 constructor Create(CreateSuspended: Boolean);
81 destructor Destroy; override;
83 property OnWork: TGikoWorkEvent read FOnWork write FOnWork;
84 property OnWorkBegin: TGikoWorkBeginEvent read FOnWorkBegin write FOnWorkBegin;
85 property OnWorkEnd: TGikoWorkEndEvent read FOnWorkEnd write FOnWorkEnd;
86 property OnDownloadEnd: TDownloadEndEvent read FOnDownloadEnd write FOnDownloadEnd;
87 property OnDownloadMsg: TDownloadMsgEvent read FOnDownloadMsg write FOnDownloadMsg;
90 TDownloadItem = class(TObject)
92 FDownType: TGikoDownloadType;
94 FThreadItem: TThreadItem;
96 FContentLength: Integer;
97 FLastModified: TDateTime;
99 FResponseCode: Smallint;
100 FState: TGikoDownloadState;
102 FForceDownload: Boolean;
105 procedure SaveListFile;
106 procedure SaveItemFile;
108 property DownType: TGikoDownloadType read FDownType write FDownType;
109 property Board: TBoard read FBoard write FBoard;
110 property ThreadItem: TThreadItem read FThreadItem write FThreadItem;
112 property ContentLength: Integer read FContentLength write FContentLength;
113 property LastModified: TDateTime read FLastModified write FLastModified;
114 property Content: string read FContent write FContent;
115 property ResponseCode: Smallint read FResponseCode write FResponseCode;
116 property State: TGikoDownloadState read FState write FState;
117 property ErrText: string read FErrText write FErrText;
118 property ForceDownload: Boolean read FForceDownload write FForceDownload;
119 property IsAbone : Boolean read FIsAbone write FIsAbone;
125 Y_TextConverter, MojuUtils, HTMLCreate, ReplaceDataModule;
127 constructor TDownloadThread.Create(CreateSuspended: Boolean);
129 inherited Create(CreateSuspended);
130 FWorkData.FWorkCS := TCriticalSection.Create;
132 FIndy := TIdHttp.Create(nil);
134 FIndy.OnWorkBegin := WorkBegin;
135 FIndy.OnWorkEnd := WorkEnd;
136 FIndy.OnWork := Work;
139 destructor TDownloadThread.Destroy;
141 ClearHttpClient(FIndy);
143 FWorkData.FWorkCS.Free;
147 function RFC1123_Date(aDate : TDateTime) : String;
149 StrWeekDay : String = 'MonTueWedThuFriSatSun';
150 StrMonth : String = 'JanFebMarAprMayJunJulAugSepOctNovDec';
152 Year, Month, Day : Word;
153 Hour, Min, Sec, MSec : Word;
156 DecodeDate(aDate, Year, Month, Day);
157 DecodeTime(aDate, Hour, Min, Sec, MSec);
158 DayOfWeek := ((Trunc(aDate) - 2) mod 7);
159 Result := Copy(StrWeekDay, 1 + DayOfWeek * 3, 3) + ', ' +
160 Format('%2.2d %s %4.4d %2.2d:%2.2d:%2.2d',
161 [Day, Copy(StrMonth, 1 + 3 * (Month - 1), 3),
162 Year, Hour, Min, Sec]);
164 // ******************************************************************
165 // HTTPClient
\82Ì
\8f\89\8aú
\89»
166 // ******************************************************************
167 procedure TDownloadThread.InitHttpClient(client: TIdHttp);
169 ClearHttpClient(client);
171 client.Request.UserAgent := GikoSys.GetUserAgent;
172 client.RecvBufferSize := Gikosys.Setting.RecvBufferSize;
173 client.ProxyParams.BasicAuthentication := False;
174 client.ReadTimeout := GikoSys.Setting.ReadTimeOut;
175 client.ConnectTimeout := GikoSys.Setting.ReadTimeOut;
177 Writeln('------------------------------------------------------------');
179 //FIndy.AllowCookies := False;
180 if GikoSys.Setting.ReadProxy then begin
181 if GikoSys.Setting.ProxyProtocol then
182 client.ProtocolVersion := pv1_1
184 client.ProtocolVersion := pv1_0;
185 client.ProxyParams.ProxyServer := GikoSys.Setting.ReadProxyAddress;
186 client.ProxyParams.ProxyPort := GikoSys.Setting.ReadProxyPort;
187 client.ProxyParams.ProxyUsername := GikoSys.Setting.ReadProxyUserID;
188 client.ProxyParams.ProxyPassword := GikoSys.Setting.ReadProxyPassword;
189 if GikoSys.Setting.ReadProxyUserID <> '' then
190 client.ProxyParams.BasicAuthentication := True;
192 Writeln('
\83v
\83\8d\83L
\83V
\90Ý
\92è
\82 \82è');
193 Writeln('
\83z
\83X
\83g: ' + GikoSys.Setting.ReadProxyAddress);
194 Writeln('
\83|
\81[
\83g: ' + IntToStr(GikoSys.Setting.ReadProxyPort));
197 if GikoSys.Setting.Protocol then
198 client.ProtocolVersion := pv1_1
200 client.ProtocolVersion := pv1_0;
201 client.ProxyParams.ProxyServer := '';
202 client.ProxyParams.ProxyPort := 80;
203 client.ProxyParams.ProxyUsername := '';
204 client.ProxyParams.ProxyPassword := '';
206 Writeln('
\83v
\83\8d\83L
\83V
\90Ý
\92è
\82È
\82µ');
210 // ******************************************************************
211 // HTTPClient
\82Ì
\83\8a\83N
\83G
\83X
\83g
\82Æ
\83\8c\83X
\83|
\83\93\83X
\82Ì
\83f
\81[
\83^
\82Ì
\8fÁ
\8b\8e
212 // ******************************************************************
213 procedure TDownloadThread.ClearHttpClient(client: TIdHttp);
215 client.Request.CustomHeaders.Clear;
216 client.Request.RawHeaders.Clear;
217 client.Request.Clear;
218 client.Response.CustomHeaders.Clear;
219 client.Response.RawHeaders.Clear;
220 client.Response.Clear;
222 client.ProxyParams.Clear;
224 procedure TDownloadThread.Execute;
226 ResStream: TMemoryStream;
229 CgiStatus: TCgiStatus;
235 DownloadResult: Boolean;
236 boardPlugIn : TBoardPlugIn;
237 lastContent : string;
238 logFile : TFileStream;
239 adjustMargin : Integer;
245 while not Terminated do begin
246 //=====
\83v
\83\89\83O
\83C
\83\93
249 ExternalBoardManager.OnWork := Work;
250 ExternalBoardManager.OnWorkBegin := WorkBegin;
251 ExternalBoardManager.OnWorkEnd := WorkEnd;
253 FDownloadTitle := '';
254 case FItem.FDownType of
257 FDownloadTitle := FItem.FBoard.Title;
258 if FItem.FBoard <> nil then begin
259 if FItem.FBoard.IsBoardPlugInAvailable then begin
260 boardPlugIn := FItem.FBoard.BoardPlugIn;
261 Item.State := TGikoDownloadState( boardPlugIn.DownloadBoard( DWORD( FItem.FBoard ) ) );
267 FDownloadTitle := FItem.FThreadItem.Title;
268 if FItem.FThreadItem <> nil then begin
269 if FItem.FThreadItem.ParentBoard.IsBoardPlugInAvailable then begin
270 boardPlugIn := FItem.FThreadItem.ParentBoard.BoardPlugIn;
271 Item.State := TGikoDownloadState( boardPlugIn.DownloadThread( DWORD( FItem.FThreadItem ) ) );
273 //if FItem.FThreadItem.IsBoardPlugInAvailable then begin
274 // boardPlugIn := FItem.FThreadItem.BoardPlugIn;
275 // Item.State := TGikoDownloadState( boardPlugIn.DownloadThread( DWORD( FItem.FThreadItem ) ) );
280 if Length(FDownloadTitle) = 0 then
281 FDownloadTitle := '
\81i
\96¼
\8fÌ
\95s
\96¾
\81j';
283 if boardPlugIn <> nil then begin
285 Item.State := gdsAbort;
287 if Assigned( OnDownloadEnd ) then
288 Synchronize( FireDownloadEnd );
297 //=====
\83v
\83\89\83O
\83C
\83\93\82ð
\8eg
\97p
\82µ
\82È
\82¢
\8fê
\8d\87
298 InitHttpClient(FIndy);
300 if Item.DownType = gdtThread then begin
301 if FileExists( Item.ThreadItem.GetThreadFileName ) then begin
302 // dat
\83t
\83@
\83C
\83\8b\82Ì
\8dÅ
\8cã
\82ð
\93Ç
\82Ý
\8fo
\82·
303 SetLength( lastContent, ADJUST_MARGIN + 1 );
304 logFile := TFileStream.Create( Item.ThreadItem.GetThreadFileName, fmOpenRead or fmShareDenyWrite );
306 logFile.Seek( -(ADJUST_MARGIN + 1), soFromEnd );
307 logFile.Read( lastContent[ 1 ], ADJUST_MARGIN + 1 );
308 lastContent := StringReplace( lastContent, #13, '', [] ); // CR
\82Ì
\8dí
\8f\9c
315 adjustMargin := Length( lastContent );
318 FIndy.Request.ContentRangeStart := 0;
319 FIndy.Request.LastModified := ZERO_DATE;
320 ResStream := TMemoryStream.Create;
323 //********************
324 //DAT or Subject
\8eæ
\93¾
325 //********************
326 Item.ResponseCode := 0;
330 if Item.DownType = gdtBoard then begin
332 Writeln('Subject
\8eæ
\93¾');
333 Writeln('URL: ' + Item.Board.GetReadCgiURL);
334 Writeln('Modified: ' + FloatToStr(Item.Board.LastModified));
336 URL := Item.Board.GetReadCgiURL;
337 if Item.ForceDownload then begin
339 ATitle := Item.Board.Title;
341 ATitle := '
\81i
\96¼
\8fÌ
\95s
\96¾
\81j';
342 FMsg := '
\81\9a\8b
\90§
\8eæ
\93¾
\82ð
\8ds
\82¢
\82Ü
\82· - [' + ATitle + ']';
344 if Assigned(OnDownloadMsg) then
345 Synchronize(FireDownloadMsg);
346 Modified := ZERO_DATE
348 Modified := Item.Board.LastModified;
350 end else if Item.DownType = gdtThread then begin
352 Writeln('DAT
\8eæ
\93¾');
353 Writeln('URL: ' + Item.ThreadItem.GetDatURL);
354 Writeln('Modified: ' + FloatToStr(Item.ThreadItem.LastModified));
356 URL := Item.ThreadItem.GetDatURL;
357 if Item.ForceDownload then begin
359 ATitle := Item.ThreadItem.Title;
361 ATitle := '
\81i
\96¼
\8fÌ
\95s
\96¾
\81j';
362 FMsg := '
\81\9a\8b
\90§
\8eæ
\93¾
\82ð
\8ds
\82¢
\82Ü
\82· - [' + ATitle + ']';
364 if FileExists(ChangeFileExt(Item.FThreadItem.GetThreadFileName,'.NG')) = true then
365 DeleteFile(ChangeFileExt(Item.FThreadItem.GetThreadFileName,'.NG'));
366 if Assigned(OnDownloadMsg) then
367 Synchronize(FireDownloadMsg);
368 Modified := ZERO_DATE;
372 Modified := Item.ThreadItem.LastModified;
373 if Item.ThreadItem.Size > 0 then begin
375 Writeln('RangeStart: ' + IntToStr(Item.ThreadItem.Size));
377 //
\82 \82Ú
\81[
\82ñ
\83`
\83F
\83b
\83N
\82Ì
\82½
\82ß adjustMargin
\83o
\83C
\83g
\91O
\82©
\82ç
\8eæ
\93¾
378 RangeStart := Item.ThreadItem.Size;
379 AdjustLen := -adjustMargin;
383 Item.IsAbone := False;
384 DownloadResult := DatDownload(Item.DownType, URL, Modified, RangeStart, AdjustLen);
386 Writeln('ResponseCode: ' + IntToStr(FIndy.ResponseCode));
388 if Item.DownType = gdtThread then begin
389 if Item.ResponseCode = 416 then begin
390 Item.IsAbone := True;
391 DownloadResult := True;
392 end else if DownloadResult and (AdjustLen < 0) then begin
393 if Copy( Item.Content, 1, adjustMargin ) <> lastContent then
394 Item.IsAbone := True;
398 if Trim(FIndy.Response.RawHeaders.Values['Date']) <> '' then begin
399 if Item.DownType = gdtBoard then
400 Item.Board.LastGetTime := GikoSys.DateStrToDateTime(FIndy.Response.RawHeaders.Values['Date'])
402 Item.ThreadItem.ParentBoard.LastGetTime := GikoSys.DateStrToDateTime(FIndy.Response.RawHeaders.Values['Date']);
405 if DownloadResult then begin
407 Writeln('Date:' + FIndy.Response.RawHeaders.Values['Date']);
409 if Item.IsAbone then begin
411 Writeln('
\82 \82Ú
\81[
\82ñ
\8c\9f\8fo');
413 ATitle := Item.ThreadItem.Title;
415 ATitle := '
\81i
\96¼
\8fÌ
\95s
\96¾
\81j';
416 //
\8d·
\95ª
\8eæ
\93¾
\82©
\82Â
\82P
\83o
\83C
\83g
\96Ú
\82ªLF
\82Å
\82È
\82¢
\8fê
\8d\87\82Í
\81u
\82 \82Ú
\81[
\82ñ
\81v
\82³
\82ê
\82Ä
\82¢
\82é
\82©
\82à
\82µ
\82ê
\82ñ
\82Ì
\82Å
\8dÄ
\8eæ
\93¾
419 FMsg := '
\81\9a\81u
\82 \82Ú
\81[
\82ñ
\81v
\82ð
\8c\9f\8fo
\82µ
\82½
\82Ì
\82Å
\8dÄ
\8eæ
\93¾
\82ð
\8ds
\82¢
\82Ü
\82· - [' + ATitle + ']';
421 if FileExists(ChangeFileExt(Item.FThreadItem.GetThreadFileName,'.NG')) = true then
422 DeleteFile(ChangeFileExt(Item.FThreadItem.GetThreadFileName,'.NG'));
423 if Assigned(OnDownloadMsg) then
424 Synchronize(FireDownloadMsg);
425 if not DatDownload(Item.DownType, URL, ZERO_DATE, RangeStart, AdjustLen) then
426 Item.State := gdsError;
428 Writeln('
\82 \82Ú
\81[
\82ñ
\8dÄ
\8eæ
\93¾
\8cã');
429 Writeln('ResponseCode: ' + IntToStr(Item.ResponseCode));
431 end else if (Item.DownType = gdtThread) and (AdjustLen < 0) then begin
432 //
\8d·
\95ª
\8eæ
\93¾
\82ª
\8fo
\97\88\82½
\8fê
\8d\87\82Í
\82 \82Ú
\81[
\82ñ
\83`
\83F
\83b
\83N
\97p
\82É
\8eæ
\93¾
\82µ
\82½
\97]
\95ª
\82È
\83T
\83C
\83Y
\82ð
\8dí
\8f\9c
433 Item.Content := Copy(Item.Content, adjustMargin + 1, MaxInt);
436 Item.State := gdsError;
437 if (Item.DownType = gdtBoard) and (Item.ResponseCode = 302) then begin
438 FMsg := '
\81\9a\81\9a\94Â
\82ª
\88Ú
\93]
\82µ
\82½
\82©
\82à
\82µ
\82ê
\82È
\82¢
\82Ì
\82Å
\94Â
\8dX
\90V
\82ð
\8ds
\82Á
\82Ä
\82
\82¾
\82³
\82¢
\81\9a\81\9a';
440 if Assigned(OnDownloadMsg) then
441 Synchronize(FireDownloadMsg);
445 //********************
447 //********************
448 if (Item.DownType = gdtThread) and (Item.ResponseCode = 302) then begin
450 Writeln('dat.gz
\8eæ
\93¾');
452 ATitle := Item.ThreadItem.Title;
454 ATitle := '
\81i
\96¼
\8fÌ
\95s
\96¾
\81j';
455 FMsg := '
\81\9adat
\82ª
\91¶
\8dÝ
\82µ
\82È
\82¢
\82½
\82ß
\89ß
\8b\8e\83\8d\83O(dat.gz)
\82ð
\92T
\82µ
\82Ü
\82· - [' + ATitle + ']';
457 if Assigned(OnDownloadMsg) then
458 Synchronize(FireDownloadMsg);
459 URL := Item.ThreadItem.GetDatgzURL;
460 Modified := Item.ThreadItem.LastModified;
463 if not DatDownload(Item.DownType, URL, Modified, RangeStart, AdjustLen) then
464 Item.State := gdsError;
466 Writeln('ResponseCode: ' + IntToStr(Item.ResponseCode));
470 //********************
471 //dat.gz
\81@
\81¨
\81@dat
\82Ì
\8eæ
\93¾
\81@2005
\94N6
\8c\8e\92Ç
\89Á
\81@by
\82à
\82¶
\82ã
472 //********************
473 if (Item.DownType = gdtThread) and (Item.ResponseCode = 302) then begin
475 Writeln('dat
\8eæ
\93¾');
477 FMsg := '
\89ß
\8b\8e\83\8d\83O(dat.gz)
\82ª
\91¶
\8dÝ
\82µ
\82È
\82¢
\82½
\82ß
\89ß
\8b\8e\83\8d\83O(dat)
\82ð
\92T
\82µ
\82Ü
\82· - [' + ATitle + ']';
479 if Assigned(OnDownloadMsg) then
480 Synchronize(FireDownloadMsg);
481 URL := ChangeFileExt(URL, '');
482 Modified := Item.ThreadItem.LastModified;
485 if not DatDownload(Item.DownType, URL, Modified, RangeStart, AdjustLen) then
486 Item.State := gdsError;
488 Writeln('ResponseCode: ' + IntToStr(Item.ResponseCode));
492 //********************
494 //********************
496 if (Item.DownType = gdtThread) and (Item.ResponseCode = 302) then begin
497 ATitle := Item.ThreadItem.Title;
499 ATitle := '
\81i
\96¼
\8fÌ
\95s
\96¾
\81j';
500 FMsg := '
\81\9a\89ß
\8b\8e\83\8d\83O(1)
\82ª
\91¶
\8dÝ
\82µ
\82È
\82¢
\82½
\82ß
\89ß
\8b\8e\83\8d\83O(2)
\82©
\82ç
\92T
\82µ
\82Ü
\82· - [' + ATitle + ']';
502 if Assigned(OnDownloadMsg) then
503 Synchronize(FireDownloadMsg);
504 URL := Item.ThreadItem.GetOldDatgzURL;
505 Modified := Item.ThreadItem.LastModified;
508 if not DatDownload(Item.DownType, URL, Modified, RangeStart, AdjustLen) then
509 Item.State := gdsError;
513 if (Item.DownType = gdtThread) and (Item.ResponseCode = 302) then begin
515 Writeln('offlaw2.so
\82Å
\8eæ
\93¾');
517 ATitle := Item.ThreadItem.Title;
519 ATitle := '
\81i
\96¼
\8fÌ
\95s
\96¾
\81j';
520 FMsg := '
\81\9adat.gz
\82ª
\91¶
\8dÝ
\82µ
\82È
\82¢
\82½
\82ßofflaw2.so
\82ð
\97\98\97p
\82µ
\82Ü
\82· - [' + ATitle + ']';
522 if Assigned(OnDownloadMsg) then
523 Synchronize(FireDownloadMsg);
524 URL := Item.ThreadItem.GetOfflaw2SoURL;
525 Modified := Item.ThreadItem.LastModified;
528 if not DatDownload(Item.DownType, URL, Modified, RangeStart, AdjustLen) then begin
530 Writeln('ResponseCode: ' + IntToStr(Item.ResponseCode));
532 Item.State := gdsError;
534 if (Item.DownType = gdtThread) and (Item.ResponseCode = 302) then begin
535 FMsg := '
\94Â
\82ª
\88Ú
\93]
\82µ
\82½
\82©
\82à
\82µ
\82ê
\82È
\82¢
\82Ì
\82Å
\94Â
\8dX
\90V
\82ð
\8ds
\82Á
\82Ä
\82
\82¾
\82³
\82¢
\81B';
537 if Assigned(OnDownloadMsg) then
538 Synchronize(FireDownloadMsg);
543 Writeln('ResponseCode: ' + IntToStr(Item.ResponseCode));
545 if Item.ResponseCode = 200 then begin
547 Writeln('CGIStatus: OK');
549 if Copy(Item.Content, 1, 5) = 'ERROR' then begin
551 Writeln('Offlow2Error');
553 Item.ResponseCode := 404;
554 Item.State := gdsError;
555 Item.ErrText := '
\83X
\83\8c\82Í
\91¶
\8dÝ
\82µ
\82È
\82¢
\82æ
\82¤
\82Å
\82·
\81B' + Item.Content;
561 Writeln('CGIStatus: 404(ERROR)');
563 Item.ResponseCode := 404;
564 Item.State := gdsError;
565 Item.ErrText := CgiStatus.FErrText;
570 if (Item.DownType = gdtThread) and ((Item.ResponseCode = 302) or (Item.ResponseCode = 404)) then begin
572 Synchronize(GetSessionID);
573 if (FSessionID <> '') then begin
575 Writeln('Rokka
\82Å
\8eæ
\93¾');
577 ATitle := Item.ThreadItem.Title;
579 ATitle := '
\81i
\96¼
\8fÌ
\95s
\96¾
\81j';
580 FMsg := '
\81\9aofflow2.so
\82É
\91¶
\8dÝ
\82µ
\82È
\82¢
\82½
\82ßRokka
\82ð
\97\98\97p
\82µ
\82Ü
\82· - [' + ATitle + ']';
582 if Assigned(OnDownloadMsg) then
583 Synchronize(FireDownloadMsg);
584 URL := Item.ThreadItem.GetRokkaURL(FSessionID);
585 Modified := Item.ThreadItem.LastModified;
589 if not DatDownload(Item.DownType, URL, Modified, RangeStart, AdjustLen) then begin
591 Writeln('ResponseCode: ' + IntToStr(Item.ResponseCode));
593 Item.State := gdsError;
595 CgiStatus := ParseRokkaStatus(Item.Content);
597 Writeln('ResponseCode: ' + IntToStr(Item.ResponseCode));
599 case CgiStatus.FStatus of
602 Writeln('CGIStatus: OK');
604 Item.ResponseCode := 200;
605 DeleteStatusLine(Item);
609 Writeln('CGIStatus: 404(ERROR)');
611 Item.ResponseCode := 404;
612 Item.State := gdsError;
613 Item.ErrText := CgiStatus.FErrText;
620 //********************
622 //********************
623 // if not GikoSys.Is2chHost(GikoSys.UrlToServer(URL)) then begin
625 Sep := Pos('://', Host);
627 Delete(Host, 1, Sep + 2);
628 Sep := Pos('/', Host);
630 SetLength(Host, Sep - 1);
631 if not GikoSys.Is2chHost(Host) then begin
632 if (Item.DownType = gdtThread) and (Item.ResponseCode = 404) then begin
634 Writeln('
\8aO
\95\94\94Â
\89ß
\8b\8e\83\8d\83O
\8eæ
\93¾');
636 ATitle := Item.ThreadItem.Title;
638 ATitle := '
\81i
\96¼
\8fÌ
\95s
\96¾
\81j';
639 FMsg := '
\81\9a\82Q
\82¿
\82á
\82ñ
\82Ë
\82é
\8aO
\95\94\94Â
\82Ì
\89ß
\8b\8e\83\8d\83O
\8eæ
\93¾
\82ð
\8ds
\82¢
\82Ü
\82· - [' + ATitle + ']';
641 if Assigned(OnDownloadMsg) then
642 Synchronize(FireDownloadMsg);
643 URL := Item.ThreadItem.GetExternalBoardKakoDatURL;
644 Modified := Item.ThreadItem.LastModified;
647 if not DatDownload(Item.DownType, URL, Modified, RangeStart, AdjustLen) then
648 Item.State := gdsError;
650 Writeln('ResponseCode: ' + IntToStr(Item.ResponseCode));
655 //********************
656 //offlaw.cgi
\82Å
\8eæ
\93¾
657 //********************
659 Synchronize(GetSessionID);
660 if (Item.DownType = gdtThread) and (Item.ResponseCode = 302) and (FSessionID <> '') then begin
662 Writeln('offlaw.cgi
\82Å
\8eæ
\93¾');
664 ATitle := Item.ThreadItem.Title;
666 ATitle := '
\81i
\96¼
\8fÌ
\95s
\96¾
\81j';
667 FMsg := '
\81\9adat.gz
\82ª
\91¶
\8dÝ
\82µ
\82È
\82¢
\82½
\82ßofflaw.cgi
\82ð
\97\98\97p
\82µ
\82Ü
\82· - [' + ATitle + ']';
669 if Assigned(OnDownloadMsg) then
670 Synchronize(FireDownloadMsg);
671 URL := Item.ThreadItem.GetOfflawCgiURL(FSessionID);
672 Modified := Item.ThreadItem.LastModified;
675 if not DatDownload(Item.DownType, URL, Modified, RangeStart, AdjustLen) then begin
677 Writeln('ResponseCode: ' + IntToStr(Item.ResponseCode));
679 Item.State := gdsError;
681 if (Item.DownType = gdtThread) and (Item.ResponseCode = 302) then begin
682 FMsg := '
\94Â
\82ª
\88Ú
\93]
\82µ
\82½
\82©
\82à
\82µ
\82ê
\82È
\82¢
\82Ì
\82Å
\94Â
\8dX
\90V
\82ð
\8ds
\82Á
\82Ä
\82
\82¾
\82³
\82¢
\81B';
684 if Assigned(OnDownloadMsg) then
685 Synchronize(FireDownloadMsg);
689 CgiStatus := ParseCgiStatus(Item.Content);
691 Writeln('ResponseCode: ' + IntToStr(Item.ResponseCode));
693 case CgiStatus.FStatus of
696 Writeln('CGIStatus: OK');
698 Item.ResponseCode := 200;
699 DeleteStatusLine(Item);
702 //
\8d¡
\82Í
\82 \82è
\82¦
\82È
\82¢
704 Writeln('CGIStatus: 206');
706 Item.ResponseCode := 206;
707 DeleteStatusLine(Item);
711 Writeln('CGIStatus: 404(ERROR)');
713 Item.ResponseCode := 404;
714 Item.State := gdsError;
715 Item.ErrText := CgiStatus.FErrText;
718 if (Item.ResponseCode = 404) and (AnsiPos('
\89ß
\8b\8e\83\8d\83O
\91q
\8cÉ
\82Å
\94
\8c©', Item.ErrText) <> 0) then begin
720 Writeln('
\89ß
\8b\8e\83\8d\83O
\8eæ
\93¾');
722 ATitle := Item.ThreadItem.Title;
724 ATitle := '
\81i
\96¼
\8fÌ
\95s
\96¾
\81j';
725 FMsg := '
\81\9a\89ß
\8b\8e\83\8d\83O
\91q
\8cÉ
\82Å
\94
\8c© - [' + ATitle + ']';
727 if Assigned(OnDownloadMsg) then
728 Synchronize(FireDownloadMsg);
729 Idx := Pos(' ', Item.ErrText);
730 if Idx <> 0 then begin
731 URL := Copy(Item.ErrText, Idx + 1, Length(Item.ErrText));
732 if Pos( '://', URL ) = 0 then begin
733 if Pos('../', URL) = 1 then
734 URL := Copy(URL, 4, MaxInt );
735 if Pos( '/', URL ) = 1 then
736 URL := Copy( URL, 2, MaxInt );
737 URL := GikoSys.UrlToServer(Item.ThreadItem.ParentBoard.URL) + URL;
739 Modified := Item.ThreadItem.LastModified;
742 if not DatDownload(Item.DownType, URL, Modified, RangeStart, AdjustLen) then
743 Item.State := gdsError;
745 Writeln('ResponseCode: ' + IntToStr(Item.ResponseCode));
751 if (Item.DownType = gdtThread) and (Item.ResponseCode = 302) and (FSessionID = '') then begin
753 Writeln('
\83\8d\83O
\83C
\83\93\82³
\82ê
\82Ä
\82È
\82¢
\82Ì
\82Å
\89ß
\8b\8e\83\8d\83O
\8eæ
\93¾
\95s
\89Â');
755 ATitle := Item.ThreadItem.Title;
757 ATitle := '
\81i
\96¼
\8fÌ
\95s
\96¾
\81j';
758 FMsg := '
\81\9a\83\8d\83O
\83C
\83\93\82³
\82ê
\82Ä
\82¢
\82È
\82¢
\82½
\82ß
\92T
\82·
\82±
\82Æ
\82ª
\8fo
\97\88\82Ü
\82¹
\82ñ - [' + ATitle + ']';
760 if Assigned(OnDownloadMsg) then
761 Synchronize(FireDownloadMsg);
765 case Item.ResponseCode of
766 200: Item.State := gdsComplete;
767 206: Item.State := gdsDiffComplete;
768 304: Item.State := gdsNotModify;
770 Item.State := gdsError;
773 Item.State := gdsError;
776 Item.State := gdsAbort;
778 if Assigned(OnDownloadEnd) then
779 Synchronize(FireDownloadEnd);
783 ClearHttpClient(FIndy);
785 if Terminated then Break;
790 function TDownloadThread.CgiDownload(ItemType: TGikoDownloadType; URL: string; Modified: TDateTime): Boolean;
792 ResponseCode: Integer;
793 ResStream: TMemoryStream;
796 FIndy.Request.ContentRangeStart := 0;
797 FIndy.Request.ContentRangeEnd := 0;
799 FIndy.Request.CustomHeaders.Clear;
800 if (Modified <> 0) and (Modified <> ZERO_DATE) then begin
801 FIndy.Request.LastModified := modified - OffsetFromUTC;
803 FIndy.Request.AcceptEncoding := '';
804 FIndy.Request.Accept := 'text/html';
805 ResStream := TMemoryStream.Create;
810 Writeln('URL: ' + URL);
812 FIndy.Get(URL, ResStream);
813 Item.Content := GikoSys.GzipDecompress(ResStream, FIndy.Response.ContentEncoding);
814 Item.LastModified := FIndy.Response.LastModified;
815 //
\8d·
\95ª
\8eæ
\93¾
\82Å
\82P
\83o
\83C
\83g
\91O
\82©
\82ç
\82Æ
\82Á
\82Ä
\82«
\82½
\82Æ
\82«
\82Í
\83}
\83C
\83i
\83X
\82·
\82é
816 Item.ContentLength := Length(Item.Content);
817 //
\96³
\82¢
\82Æ
\8ev
\82¤
\82¯
\82Ç
\81B
\81B
\81B
818 if Item.Content = '' then
823 Writeln('
\8eæ
\93¾
\82Å
\97á
\8aO
\82È
\82µ');
825 ResponseCode := FIndy.ResponseCode;
827 on E: EIdSocketError do begin
829 Item.LastModified := ZERO_DATE;
830 Item.ContentLength := 0;
831 Item.ErrText := E.Message;
834 Screen.Cursor := crDefault;
836 on E: EIdConnectException do begin
838 Item.LastModified := ZERO_DATE;
839 Item.ContentLength := 0;
840 Item.ErrText := E.Message;
843 Screen.Cursor := crDefault;
845 on E: Exception do begin
847 Writeln('
\8eæ
\93¾
\82Å
\97á
\8aO
\82 \82è');
848 Writeln('E.Message: ' + E.Message);
851 Item.LastModified := ZERO_DATE;
852 Item.ContentLength := 0;
853 Item.ErrText := E.Message;
854 ResponseCode := FIndy.ResponseCode;
856 Screen.Cursor := crDefault;
860 if (Item.ContentLength = 0) and (ResponseCode = 206) then
861 Item.ResponseCode := 304
863 Item.ResponseCode := ResponseCode;
868 function TDownloadThread.DatDownload(ItemType: TGikoDownloadType; URL: string; Modified: TDateTime; RangeStart: Integer; AdjustLen: Integer): Boolean;
870 ResponseCode: Integer;
871 ResStream: TMemoryStream;
874 if (ItemType = gdtThread) and (RangeStart > 0) then begin
875 FIndy.Request.ContentRangeStart := RangeStart + AdjustLen;
876 FIndy.Request.ContentRangeEnd := 0;
878 FIndy.Request.ContentRangeStart := 0;
879 FIndy.Request.ContentRangeEnd := 0;
882 FIndy.Request.CustomHeaders.Clear;
883 FIndy.Request.CacheControl := 'no-cache';
884 FIndy.Request.CustomHeaders.Add('Pragma: no-cache');
885 if (Modified <> 0) and (Modified <> ZERO_DATE) then begin
886 FIndy.Request.LastModified := modified - OffsetFromUTC;
888 if RangeStart = 0 then
889 FIndy.Request.AcceptEncoding := 'gzip'
891 FIndy.Request.AcceptEncoding := '';
892 ResStream := TMemoryStream.Create;
897 Writeln('URL: ' + URL);
899 FIndy.Get(URL, ResStream);
900 Item.Content := GikoSys.GzipDecompress(ResStream, FIndy.Response.ContentEncoding);
901 Item.ContentLength := Length(Item.Content) + AdjustLen;
903 if GikoSys.Setting.ReplaceDat then begin
904 Item.Content := ReplaceDM.Replace(Item.Content);
906 Item.LastModified := FIndy.Response.LastModified;
907 if Item.Content = '' then
912 Writeln('
\8eæ
\93¾
\82Å
\97á
\8aO
\82È
\82µ');
914 ResponseCode := FIndy.ResponseCode;
916 on E: EIdSocketError do begin
918 Item.LastModified := ZERO_DATE;
919 Item.ContentLength := 0;
920 Item.ErrText := E.Message;
923 Screen.Cursor := crDefault;
925 on E: EIdConnectException do begin
927 Item.LastModified := ZERO_DATE;
928 Item.ContentLength := 0;
929 Item.ErrText := E.Message;
932 Screen.Cursor := crDefault;
934 on E: Exception do begin
936 Writeln('
\8eæ
\93¾
\82Å
\97á
\8aO
\82 \82è');
937 Writeln('E.Message: ' + E.Message);
940 Item.LastModified := ZERO_DATE;
941 Item.ContentLength := 0;
942 Item.ErrText := E.Message;
943 ResponseCode := FIndy.ResponseCode;
945 Screen.Cursor := crDefault;
949 if (Item.ContentLength = 0) and (ResponseCode = 206) then
950 Item.ResponseCode := 304
952 Item.ResponseCode := ResponseCode;
957 procedure TDownloadThread.FireDownloadEnd;
959 OnDownloadEnd(self, Item);
962 procedure TDownloadThread.FireDownloadMsg;
964 OnDownloadMsg(Self, Item, FMsg, FIcon);
967 procedure TDownloadThread.GetSessionID;
969 FSessionID := GikoSys.Dolib.SessionID;
972 procedure TDownloadThread.Abort;
975 FIndy.DisconnectSocket;
976 if socket <> nil then begin
977 socket.DisconnectSocket;
981 procedure TDownloadThread.WorkBegin(Sender: TObject;
982 AWorkMode: TWorkMode; const AWorkCountMax: Integer);
984 if Assigned(OnWorkBegin) then begin
985 FWorkData.FWorkCS.Acquire;
987 FWorkData.FSender := Sender;
988 FWorkData.FAWorkMode := AWorkMode;
989 FWorkData.FAWorkCountMax := AWorkCountMax;
990 Synchronize(FireWorkBegin);
992 FWorkData.FWorkCS.Release;
997 procedure TDownloadThread.WorkEnd(Sender: TObject;
998 AWorkMode: TWorkMode);
1000 if Assigned(OnWorkEnd) then begin;
1001 FWorkData.FWorkCS.Acquire;
1003 FWorkData.FSender := Sender;
1004 FWorkData.FAWorkMode := AWorkMode;
1005 Synchronize(FireWorkEnd);
1007 FWorkData.FWorkCS.Release;
1012 procedure TDownloadThread.Work(Sender: TObject; AWorkMode:
1013 TWorkMode; const AWorkCount: Integer);
1015 if Assigned(OnWork) then begin
1016 FWorkData.FWorkCS.Acquire;
1018 FWorkData.FSender := Sender;
1019 FWorkData.FAWorkMode := AWorkMode;
1020 FWorkData.FAWorkCount := AWorkCount;
1021 Synchronize(FireWork);
1023 FWorkData.FWorkCS.Release;
1028 //
\82±
\82±
\82©
\82ç
\90V
\8bK
\83\81\83\
\83b
\83h
1029 procedure TDownloadThread.FireWorkBegin;
1031 OnWorkBegin(FWorkData.FSender, FWorkData.FAWorkMode,
1032 FWorkData.FAWorkCountMax,
1033 FNumber, FDownloadTitle);
1036 procedure TDownloadThread.FireWorkEnd;
1038 OnWorkEnd(FWorkData.FSender, FWorkData.FAWorkMode,
1042 procedure TDownloadThread.FireWork;
1044 OnWork(FWorkData.FSender, FWorkData.FAWorkMode,
1045 FWorkData.FAWorkCount,
1049 function TDownloadThread.ParseCgiStatus(Content: string): TCgiStatus;
1058 // [+OK]
\82Ì
\8fê
\8d\87\82Í
\8d·
\95ª
1059 // [-INCR] (Incorrect)
\82Ì
\8fê
\8d\87\82Í
\82·
\82×
\82Ä
\82Ì
\83f
\81[
\83^
1060 // [-ERR (
\83e
\83L
\83X
\83g)]
\82Ì
\8fê
\8d\87\82Í
\82È
\82ñ
\82©
\83G
\83\89\81[
1061 //
\97á
\81F+OK 23094/512K
1063 // -ERR
\82»
\82ñ
\82È
\94Â
\82È
\82¢
\82Å
\82·
1064 Idx := AnsiPos(#10, Content);
1065 StatusLine := Copy(Content, 0, Idx);
1067 Idx := AnsiPos(' ', Content);
1068 Status := Copy(StatusLine, 0, Idx - 1);
1069 Line := Copy(StatusLine, Idx + 1, Length(StatusLine));
1071 // Idx := AnsiPos('/', Line);
1072 if Trim(Status) = '-ERR' then
1075 Size := Copy(Line, 0, Idx - 1);
1077 if Trim(Status) = '+OK' then
1078 Result.FStatus := gcsOK
1079 else if Trim(Status) = '-INCR' then
1080 Result.FStatus := gcsINCR
1081 else if Trim(Status) = '-ERR' then begin
1082 Result.FStatus := gcsERR;
1083 Result.FErrText := Msg;
1090 Result.FStatus := gcsERR;
1091 Result.FErrText := '
\83G
\83\89\81[
\82È
\82ñ
\82¾
\82¯
\82Ç
\81A
\82æ
\82
\95ª
\82©
\82ç
\82È
\82¢
\83G
\83\89\81[';
1096 if GikoSys.IsNumeric(Size) then
1097 Result.FSize := StrToInt(Size)
1100 Result.FStatus := gcsERR;
1101 Result.FErrText := '
\83X
\83e
\81[
\83^
\83X
\89ð
\90Í
\8e¸
\94s[' + StatusLine + ']';
1105 function TDownloadThread.ParseRokkaStatus(Content: string): TCgiStatus;
1111 //
\81@
\83\8c\83X
\83|
\83\93\83X : 1
\8ds
\96Ú
\82Érokka
\82Ì
\8f\88\97\9d\8c\8b\89Ê
\82ª
\8bL
\8fq
\82³
\82ê
\82Ü
\82·
1112 //
\81@
\81@"Success XXX"
\81@-
\90¬
\8c÷
\81@XXX
\82Édat
\82Ì
\8fó
\91Ô
\81i
\8eæ
\93¾
\8c³
\81j
\82ª
\8bL
\8fq
\82³
\82ê
\82Ü
\82·
1113 //
\81@
\81@
\81@
\81@
\81@
\81@
\81@
\81@
\81@
\81@
\81@Live
\81@
\81@
\81@
\81@
\83\89\83C
\83u
\83X
\83\8c\83b
\83h
1114 //
\81@
\81@
\81@
\81@
\81@
\81@
\81@
\81@
\81@
\81@
\81@Pool
\81@
\81@
\81@
\81@dat
\97\8e\82¿
\83X
\83\8c\83b
\83h
1115 //
\81@
\81@
\81@
\81@
\81@
\81@
\81@
\81@
\81@
\81@
\81@Archive
\81@
\81@
\89ß
\8b\8e\83\8d\83O
1116 //
\81@
\81@
\81@
\81@
\81@
\81@
\81@
\81@
\81@
\81@
\88È
\8d~
\82Ì
\8ds
\82ÉDAT
\8c`
\8e®(name<>email<>datetime<>body<>[title])
\82Å
\83\8d\83O
\82ª
\8bL
\8fq
\82³
\82ê
\82Ä
\82¢
\82Ü
\82·
1117 //
\81@
\81@"Error XXX"
\81@
\81@-
\89½
\82ç
\82©
\82Ì
\83G
\83\89\81[
\82Å
\82·
\81@XXX
\82ª
\83G
\83\89\81[
\83R
\81[
\83h
\82Å
\82·
\81B
1118 //
\81@
\81@
\81@
\81@
\81@
\81@
\81@
\81@
\81@
\81@
\81@13
\81@
\81@
\81@not found
\81@
\81@
\81@
\81@
\81@
\81@
\97v
\8b\81\82³
\82ê
\82½dat
\82ª
\8c©
\82Â
\82©
\82è
\82Ü
\82¹
\82ñ
\82Å
\82µ
\82½
1119 //
\81@
\81@
\81@
\81@
\81@
\81@
\81@
\81@
\81@
\81@
\81@8008135
\81@inputError
\81@
\81@
\81@
\81@
\81@
\83\8a\83N
\83G
\83X
\83gURL
\82ÌSERVER
\82©BOARD
\82ª
\90³
\82µ
\82
\82È
\82¢
\82Å
\82·
1120 //
\81@
\81@
\81@
\81@
\81@
\81@
\81@
\81@
\81@
\81@
\81@666
\81@
\81@
\81@urlError
\81@
\81@
\81@
\81@
\81@
\81@OPTIONS
\82Ü
\82½
\82ÍQueryString
\82ª
\90³
\82µ
\82
\82È
\82¢
\82Å
\82·
1121 //
\81@
\81@
\81@
\81@
\81@
\81@
\81@
\81@
\81@
\81@
\81@69
\81@
\81@
\81@authenticationError
\81@KAGI
\82ª
\95s
\90³
\81i
\97L
\8cø
\8aú
\8cÀ
\90Ø
\82ê
\82»
\82Ì
\91¼
\81j
1122 //
\81@
\81@
\81@
\81@
\81@
\81@
\81@
\81@
\81@
\81@
\81@420
\81@
\81@
\81@timeLimitError
\81@
\81@
\81@
\83A
\83N
\83Z
\83X
\8aÔ
\8au
\82ª
\92Z
\82·
\82¬
\82Ü
\82·
1123 //
\81@
\81@
\81@
\81@
\81@
\81@
\81@
\81@
\81@
\81@
\81@42
\81@
\81@
\81@methodError
\81@
\81@
\81@
\81@
\81@
\82»
\82ÌHTTP
\83\81\83\
\83b
\83h
\82Í
\8b\96\89Â
\82³
\82ê
\82Ä
\82¢
\82Ü
\82¹
\82ñ
1124 Idx := AnsiPos(#10, Content);
1126 StatusLine := Copy(Content, 0, Idx)
1128 StatusLine := Content;
1130 if (AnsiPos('Success', StatusLine) = 1) then begin
1131 Result.FStatus := gcsOK;
1132 Delete(StatusLine, 1, 7);
1133 Status := Trim(StatusLine);
1134 if (Status = 'Live') then //
\91½
\95ª
\82±
\82ê
\82Í
\97\88\82È
\82¢
1135 Result.FErrText := '
\8eæ
\93¾
\90¬
\8c÷
\81i
\83\89\83C
\83u
\83X
\83\8c\83b
\83h
\81j'
1136 else if (Status = 'Pool') then
1137 Result.FErrText := '
\8eæ
\93¾
\90¬
\8c÷
\81idat
\97\8e\82¿
\83X
\83\8c\83b
\83h
\81j'
1138 else if (Status = 'Archive') then
1139 Result.FErrText := '
\8eæ
\93¾
\90¬
\8c÷
\81i
\89ß
\8b\8e\83\8d\83O
\81j'
1141 Result.FErrText := '
\8eæ
\93¾
\90¬
\8c÷';
1143 else if (AnsiPos('Error', StatusLine) = 1) then begin
1144 Result.FStatus := gcsERR;
1145 Delete(StatusLine, 1, 5);
1146 Status := Trim(StatusLine);
1147 if (Status = '13') then
1148 Result.FErrText := '
\97v
\8b\81\82³
\82ê
\82½dat
\82ª
\8c©
\82Â
\82©
\82è
\82Ü
\82¹
\82ñ
\82Å
\82µ
\82½'
1149 else if (Status = '8008135') then
1150 Result.FErrText := '
\83\8a\83N
\83G
\83X
\83gURL
\82ÌSERVER
\82©BOARD
\82ª
\90³
\82µ
\82
\82È
\82¢
\82Å
\82·'
1151 else if (Status = '666') then
1152 Result.FErrText := 'OPTIONS
\82Ü
\82½
\82ÍQueryString
\82ª
\90³
\82µ
\82
\82È
\82¢
\82Å
\82·'
1153 else if (Status = '69') then
1154 Result.FErrText := 'KAGI
\82ª
\95s
\90³
\81i
\97L
\8cø
\8aú
\8cÀ
\90Ø
\82ê
\82»
\82Ì
\91¼
\81j'
1155 else if (Status = '20') then
1156 Result.FErrText := '
\83A
\83N
\83Z
\83X
\8aÔ
\8au
\82ª
\92Z
\82·
\82¬
\82Ü
\82·'
1157 else if (Status = '42') then
1158 Result.FErrText := '
\82»
\82ÌHTTP
\83\81\83\
\83b
\83h
\82Í
\8b\96\89Â
\82³
\82ê
\82Ä
\82¢
\82Ü
\82¹
\82ñ'
1160 Result.FErrText := '
\8eæ
\93¾
\83G
\83\89\81[[' + Status + ']';
1163 Result.FStatus := gcsERR;
1164 Result.FErrText := '
\83X
\83e
\81[
\83^
\83X
\89ð
\90Í
\8e¸
\94s[' + StatusLine + ']';
1169 //
\82P
\8ds
\96Ú
\82ð
\8fÁ
\82µ
\82Ä
\81A
\83R
\83\93\83e
\83\93\83c
\83T
\83C
\83Y
\82ð
\90Ý
\92è
\82·
\82é
1170 procedure TDownloadThread.DeleteStatusLine(Item: TDownloadItem);
1174 SList := TStringList.Create;
1176 SList.Text := Item.Content;
1177 //1
\8ds
\96Ú
\82ð
\8dí
\8f\9c
1178 if SList.Count > 1 then
1180 Item.Content := SList.Text;
1181 //
\89ü
\8ds
\83R
\81[
\83h
\82ðCRLF -> LF
\82Æ
\8dl
\82¦
\82Ä
\81A
\8ds
\90\94\95ª
\82¾
\82¯
\83}
\83C
\83i
\83X
1182 Item.ContentLength := Length(SList.Text) - SList.Count;
1188 procedure TDownloadItem.SaveListFile;
1192 NewItem: TThreadItem;
1199 function MakeThreadCallBack(
1200 inInstance : DWORD; // TBoardItem
\82Ì
\83C
\83\93\83X
\83^
\83\93\83X
1201 inURL : PChar; //
\83X
\83\8c\83b
\83h
\82Ì URL
1202 inTitle : PChar; //
\83X
\83\8c\83^
\83C
1203 inCount : DWORD //
\83\8c\83X
\82Ì
\90\94
1204 ) : Boolean; stdcall; //
\97ñ
\8b\93\82ð
\91±
\82¯
\82é
\82È
\82ç True
1206 _ThreadItem : TThreadItem; // '_'
\82Í
\83N
\83\89\83X
\82Ì
\83v
\83\8d\83p
\83e
\83B
\82Æ
\82©
\82Ô
\82Á
\82Ä
\82é
\82Ì
\82Å
1210 boardItem := TBoard( inInstance );
1212 boardItem.IntData := boardItem.IntData + 1;
1213 if boardItem.IntData < (boardItem.Count shr 2) then
1214 index := boardItem.GetIndexFromURL( string( inURL ) )
1216 index := boardItem.GetIndexFromURL( string( inURL ), True );
1217 if index = -1 then begin
1218 //
\90V
\82µ
\82¢
\83X
\83\8c\83b
\83h
1219 _ThreadItem := TThreadItem.Create( boardItem.BoardPlugIn, boardItem, string( inURL ) );
1221 _ThreadItem.Title := string( inTitle );
1222 _ThreadItem.AllResCount := inCount;
1223 _ThreadItem.ParentBoard := Board;
1224 _ThreadItem.No := boardItem.IntData;
1225 _ThreadItem.RoundDate := ZERO_DATE;
1226 _ThreadItem.LastModified := ZERO_DATE;
1227 _ThreadItem.AgeSage := gasNew;
1228 boardItem.Add(_ThreadItem);
1230 //
\8f\87\88Ê
\82ª
\8fã
\82ª
\82Á
\82Ä
\82¢
\82ê
\82ÎAge
\82É
\82·
\82é
1231 if boardItem.Items[index].No > boardItem.IntData then
1232 boardItem.Items[index].AgeSage := gasAge
1233 //
\8f\87\88Ê
\82ª
\8fã
\82ª
\82Á
\82Ä
\82È
\82¢
\82¯
\82Ç
\81A
\83\8c\83X
\82ª
\82Â
\82¢
\82Ä
\82½
\82ç
\81ASage
\82É
1234 else if boardItem.Items[index].AllResCount <> inCount then
1235 boardItem.Items[index].AgeSage := gasSage
1236 //
\8f\87\88Ê
\8fã
\82ª
\82Á
\82Ä
\82È
\82¢
\82µ
\81A
\83\8c\83X
\82Ì
\91\9d\8c¸
\82à
\96³
\82¯
\82ê
\82Î
\81ANone
1238 boardItem.Items[index].AgeSage := gasNone;
1240 boardItem.Items[index].No := boardItem.IntData;
1241 boardItem.Items[index].AllResCount := inCount;
1248 Writeln('SAVELIST');
1250 //Board.ListData := TList.Create;
1251 Body := TStringList.Create;
1253 //
\83_
\83E
\83\93\83\8d\81[
\83h
\93ú
\8e\9e\90Ý
\92è
\81i
\83\8d\81[
\83J
\83\8b\93ú
\8e\9e\81j
1254 Board.RoundDate := Now;
1255 //
\83T
\81[
\83o
\8fã
\83t
\83@
\83C
\83\8b\82Ì
\8dX
\90V
\8e\9e\8d\8f\90Ý
\92è
1256 Board.LastModified := LastModified;
1259 //dat
\97\8e\82¿
\83X
\83\8c\82Ì
\83\
\81[
\83g
\8f\87\82ð
\8c\88\92è
\82·
\82é
\82½
\82ß
\82É
\83\
\81[
\83g
\82·
\82é
1260 if GikoSys.Setting.DatOchiSortIndex >= 0 then begin
1261 Sort.SetSortNoFlag(true);
1262 Sort.SetSortOrder(GikoSys.Setting.DatOchiSortOrder);
1263 Sort.SetSortIndex(GikoSys.Setting.DatOchiSortIndex);
1264 //Sort.SortNonAcquiredCountFlag := GikoSys.Setting.NonAcquiredCount;
1265 Board.CustomSort(ThreadItemSortProc);
1269 rt := GetTickCount - st;
1270 Writeln('END Sortd' + IntToStr(rt) + ' ms');
1273 for i := Board.Count - 1 downto 0 do
1274 Board.Items[i].AgeSage := gasNull;
1276 if Board.IsBoardPlugInAvailable then begin
1277 //
\90V
\82µ
\82¢
\83\8a\83X
\83g
\82ð
\8dì
\90¬
\82·
\82é
1278 //
\90V
\82µ
\82¢
\83\8a\83X
\83g
\82É
\8cÃ
\82¢
\83\8a\83X
\83g
\82Ì
\83\8d\83O
\82ª
\82 \82é
\82È
\82ç
\82»
\82ê
\82ð
\90V
\82µ
\82¢
\83\8a\83X
\83g
\82É
\92Ç
\89Á
1279 //
\8cÃ
\82¢
\83\8d\83O
\82ª
\82È
\82¯
\82ê
\82Î
\81A
\90V
\82½
\82É
\83X
\83\8c\83I
\83u
\83W
\83F
\83N
\83g
\82ð
\8dì
\90¬
1282 rt := GetTickCount - st;
1283 Writeln('Start Enum' + IntToStr(rt) + ' ms');
1286 //
\82±
\82ê
\82ª
\92x
\82¢
\81@
\97v
\89ü
\91P
1288 Board.BoardPlugIn.EnumThread( DWORD( Board ), @MakeThreadCallBack );
1292 rt := GetTickCount - st;
1293 Writeln('End Enum' + IntToStr(rt) + ' ms');
1296 //
\8cÃ
\82¢
\83\8a\83X
\83g
\82É
\82µ
\82©
\82È
\82¢
\82â
\82Â
\82ç
\82ð
\8dí
\8f\9c
1297 for i := Board.Count - 1 downto 0 do begin
1298 if( Board.Items[i].AgeSage = gasNull )and not (Board.Items[i].IsLogFile) then
1302 //
\90V
\82µ
\82¢
\83\8a\83X
\83g
\82É
\96³
\82©
\82Á
\82½
\83A
\83C
\83e
\83\80\82ð
\90V
\82µ
\82¢
\83\8a\83X
\83g
\82É
\92Ç
\89Á
1303 for i := 0 to Board.Count - 1 do begin
1304 if(Board.Items[i].AgeSage = gasNull) and (Board.Items[i].IsLogFile) then begin
1305 Board.IntData := Board.IntData + 1;
1306 Board.Items[i].No := Board.IntData;
1307 Board.Items[i].AllResCount := Board.Items[i].Count;
1308 Board.Items[i].NewResCount := 0;
1309 Board.Items[i].AgeSage := gasArch;
1314 //
\90V
\82µ
\82¢
\83\8a\83X
\83g
\82ð
\8dì
\90¬
\82·
\82é
1315 //
\90V
\82µ
\82¢
\83\8a\83X
\83g
\82É
\8cÃ
\82¢
\83\8a\83X
\83g
\82Ì
\83\8d\83O
\82ª
\82 \82é
\82È
\82ç
\82»
\82ê
\82ð
\90V
\82µ
\82¢
\83\8a\83X
\83g
\82É
\92Ç
\89Á
1316 //
\8cÃ
\82¢
\83\8d\83O
\82ª
\82È
\82¯
\82ê
\82Î
\81A
\90V
\82½
\82É
\83X
\83\8c\83I
\83u
\83W
\83F
\83N
\83g
\82ð
\8dì
\90¬
1317 Body.Text := Content;
1319 for i := 0 to Body.Count - 1 do begin
1320 Rec := GikoSys.DivideSubject(Body[i]);
1321 Rec.FFileName := Trim(Rec.FFileName);
1322 if (Rec.FTitle = '') and (Rec.FCount = 0) then Continue;
1324 index := Board.GetIndexFromFileName(Rec.FFileName);
1325 if index = -1 then begin
1326 //
\90V
\82µ
\82¢
\83X
\83\8c\83b
\83h
1327 NewItem := TThreadItem.Create(
1330 GikoSys.Get2chBoard2ThreadURL( Board, ChangeFileExt( Rec.FFileName, '' ) ) );
1331 NewItem.Title := Rec.FTitle;
1332 NewItem.AllResCount := Rec.FCount;
1333 NewItem.ParentBoard := Board;
1334 NewItem.No := NumCount;
1335 NewItem.RoundDate := ZERO_DATE;
1336 NewItem.LastModified := ZERO_DATE;
1337 NewItem.AgeSage := gasNew;
1340 if Board.Items[index].No > NumCount then
1341 Board.Items[index].AgeSage := gasAge
1342 else if Board.Items[index].AllResCount < Rec.FCount then
1343 Board.Items[index].AgeSage := gasSage
1345 Board.Items[index].AgeSage := gasNone;
1347 Board.Items[index].No := NumCount;
1348 Board.Items[index].AllResCount := Rec.FCount;
1351 //
\8cÃ
\82¢
\83\8a\83X
\83g
\82Ì
\8dí
\8f\9c
1352 for i := Board.Count - 1 downto 0 do begin
1353 if( Board.Items[i].AgeSage = gasNull )and not (Board.Items[i].IsLogFile) then
1357 //
\90V
\82µ
\82¢
\83\8a\83X
\83g
\82É
\96³
\82©
\82Á
\82½
\83A
\83C
\83e
\83\80\82Ì
\8dX
\90V
1358 for i := 0 to Board.Count - 1 do begin
1359 if( Board.Items[i].AgeSage = gasNull )and (Board.Items[i].IsLogFile) then begin
1361 Board.Items[i].No := NumCount;
1362 Board.Items[i].AllResCount := Board.Items[i].Count;
1363 Board.Items[i].NewResCount := 0;
1364 Board.Items[i].AgeSage := gasArch;
1367 //
\83\8a\83X
\83g(subject.txt)
\82ð
\95Û
\91¶
1368 GikoSys.ForceDirectoriesEx(ExtractFilePath(Board.GetSubjectFileName));
1369 Body.Text := MojuUtils.Sanitize(Body.Text);
1370 Body.SaveToFile(Board.GetSubjectFileName);
1379 {procedure TDownloadItem.SaveListFile;
1383 NewItem: TThreadItem;
1385 // SaveCount: Integer;
1390 NewList := TList.Create;
1391 Body := TStringList.Create;
1393 //
\8f\84\89ñ
\93ú
\8e\9e\90Ý
\92è
1394 Board.RoundDate := Now;
1395 //
\83T
\81[
\83o
\8fã
\83t
\83@
\83C
\83\8b\82Ì
\8dX
\90V
\8e\9e\8d\8f\90Ý
\92è
1396 Board.LastModified := LastModified;
1398 //
\83\8a\83X
\83g
\95Û
\91¶
\8c\8f\90\94\8eæ
\93¾
1399 //SaveCount := MaxInt;
1401 //
\8cÃ
\82¢
\83\8a\83X
\83g
\82©
\82ç
\83\8d\83O
\96³
\82µ
\83A
\83C
\83e
\83\80\82ð
\8dí
\8f\9c
1402 for i := Board.Count - 1 downto 0 do
1403 if not Board.Items[i].IsLogFile then
1406 //
\90V
\82µ
\82¢
\83\8a\83X
\83g
\82ð
\8dì
\90¬
\82·
\82é
1407 //
\90V
\82µ
\82¢
\83\8a\83X
\83g
\82É
\8cÃ
\82¢
\83\8a\83X
\83g
\82Ì
\83\8d\83O
\82ª
\82 \82é
\82È
\82ç
\82»
\82ê
\82ð
\90V
\82µ
\82¢
\83\8a\83X
\83g
\82É
\92Ç
\89Á
1408 //
\8cÃ
\82¢
\83\8d\83O
\82ª
\82È
\82¯
\82ê
\82Î
\81A
\90V
\82½
\82É
\83X
\83\8c\83I
\83u
\83W
\83F
\83N
\83g
\82ð
\8dì
\90¬
1409 Body.Text := Content;
1410 // Loop := Min(Body.Count, SaveCount);
1412 // for i := 0 to Loop - 1 do begin
1413 for i := 0 to Body.Count - 1 do begin
1414 if i = 0 then Continue; //
\82P
\8ds
\96Ú
\82Í
\83X
\83e
\81[
\83^
\83X
\8ds
\82Ì
\82½
\82ß
\8f\88\97\9d\82È
\82µ
1416 Rec := GikoSys.DivideSubject(Body[i]);
1417 if (Rec.FTitle = '') and (Rec.FCount = 0) then Continue;
1419 index := Board.GetIndex(Rec.FFileName);
1420 if index = -1 then begin
1421 NewItem := TThreadItem.Create;
1422 NewItem.FileName := Rec.FFileName;
1423 NewItem.Title := Rec.FTitle;
1424 NewItem.Count := Rec.FCount;
1425 NewItem.ParentBoard := Board;
1426 NewItem.No := NumCount;
1427 NewItem.RoundDate := ZERO_DATE;
1428 NewItem.LastModified := ZERO_DATE;
1429 NewList.Add(NewItem);
1431 //Board.Items[index].Count := Count;
1432 Board.Items[index].No := NumCount;
1433 NewList.Add(Board.Items[index]);
1434 Board.DeleteList(index);
1438 //
\90V
\82µ
\82¢
\83\8a\83X
\83g
\82É
\96³
\82©
\82Á
\82½
\8cÃ
\82¢
\83\8d\83O
\97L
\82è
\83A
\83C
\83e
\83\80\82ð
\90V
\82µ
\82¢
\83\8a\83X
\83g
\82É
\92Ç
\89Á
1439 for i := 0 to Board.Count - 1 do begin
1441 Board.Items[i].No := NumCount;
1442 NewList.Add(Board.Items[i]);
1445 //
\8cÃ
\82¢
\83\8a\83X
\83g
\82ð
\8fÁ
\82·
\81i
\83\8a\83X
\83g
\82Ì
\82Ý
\81B
\83X
\83\8c\83I
\83u
\83W
\83F
\83N
\83g
\8e©
\91Ì
\82Í
\8fÁ
\82³
\82È
\82¢
\81j
1446 for i := Board.Count - 1 downto 0 do
1447 Board.DeleteList(i);
1449 //
\90V
\82µ
\82¢
\83\8a\83X
\83g
\82ð
\83{
\81[
\83h
\83I
\83u
\83W
\83F
\83N
\83g
\82É
\92Ç
\89Á
1450 for i := 0 to NewList.Count - 1 do
1451 Board.Add(TThreadItem(NewList[i]));
1453 //
\83\8a\83X
\83g(subject.txt)
\82ð
\95Û
\91¶
1454 // GikoSys.ForceDirectoriesEx(GikoSys.GetLogDir + Board.BBSID);
1455 // Body.SaveToFile(GikoSys.GetSubjectFileName(Board.BBSID));
1456 GikoSys.ForceDirectoriesEx(ExtractFilePath(Board.GetSubjectFileName));
1457 Body.SaveToFile(Board.GetSubjectFileName);
1464 procedure TDownloadItem.SaveItemFile;
1466 Body, oldBody: TStringList;
1477 FileName := ThreadItem.GetThreadFileName;
1479 //if not ThreadItem.IsBoardPlugInAvailable then begin
1480 if not ThreadItem.ParentBoard.IsBoardPlugInAvailable then begin
1481 if Trim(Content) = '' then
1484 GikoSys.ForceDirectoriesEx(ExtractFilePath(FileName));
1487 Body := TStringList.Create;
1491 // if FileExists(FileName) and (ResponseCode = 206) then begin
1492 if FileExists(FileName) and (State = gdsDiffComplete) then begin
1497 Body.LoadFromFile(FileName);
1498 OldCnt := Body.Count;
1499 Body.Text := Body.Text + Content;
1500 Body.SaveToFile(FileName);
1501 NewRes := Body.Count - OldCnt;
1503 on E:EFOpenError do begin
1511 //Cnt := Body.Count;
1513 if IsAbone then begin
1514 //
\82 \82Ú
\81[
\82ñ
\82ð
\8c\9f\8fo
\82µ
\82½
\82Ì
\82Å
\82±
\82±
\82Ü
\82Å
\93Ç
\82ñ
\82¾
\82Æ
\90V
\92\85\83\8c\83X
\94Ô
\82Ì
\82Â
\82¯
\82È
\82¨
\82µ
1515 oldBody := TStringList.Create;
1521 oldBody.LoadFromFile(FileName);
1523 on E:EFOpenError do begin
1534 Body.Text := Content;
1535 if (ThreadItem.Kokomade > 0) and (ThreadItem.Kokomade <= oldBody.Count) then begin
1536 ThreadItem.Kokomade := Body.IndexOf(oldBody.Strings[ ThreadItem.Kokomade - 1 ]);
1537 if ThreadItem.Kokomade <> -1 then ThreadItem.Kokomade := ThreadItem.Kokomade + 1;
1540 LastIdx := oldBody.Count;
1543 OldCnt := Body.IndexOf(oldBody.Strings[ LastIdx ]) + 1;
1544 until ( OldCnt <> 0 ) or (LastIdx = 0);
1546 if OldCnt >= Body.Count then OldCnt := Body.Count - 1;
1547 NewRes := Body.Count - OldCnt;
1549 //
\82±
\82±
\82Ü
\82Å
\93Ç
\82ñ
\82¾
\82ª
\90V
\92\85\83\8c\83X
\94Ô
\82ð
\92´
\82³
\82È
\82¢
\82æ
\82¤
\82É(
\88Ù
\8fí
\8fI
\97¹
\8e\9e\82Ì
\83\8a\83J
\83o
\83\8a)
1550 if ThreadItem.Kokomade > OldCnt then begin
1552 ThreadItem.Kokomade := OldCnt
1554 ThreadItem.Kokomade := 1;
1562 Body.Text := Content;
1563 //ThreadItem.Count := 0;
1565 NewRes := Body.Count;
1566 //Cnt := Body.Count;
1568 // if Body.Count > 0 then
1570 Body.SaveToFile(FileName);
1572 if ThreadItem.Title = '' then begin
1573 THTMLCreate.DivideStrLine(Body[0], @Res);
1574 ThreadItem.Title := Res.FTitle;
1576 ThreadItem.Size := 0;
1583 ThreadItem.Size := ThreadItem.Size + ContentLength;
1584 ThreadItem.LastModified := LastModified;
1585 ThreadItem.Count := Cnt;
1586 //ThreadItem.AllResCount := Cnt;
1587 ThreadItem.NewResCount := NewRes;
1588 ThreadItem.NewReceive := OldCnt + 1;
1590 ThreadItem.AllResCount := ThreadItem.Count;
1591 ThreadItem.IsLogFile := True;
1592 ThreadItem.RoundDate := Now;
1593 if not ThreadItem.UnRead then begin
1594 ThreadItem.UnRead := True;
1596 // if ThreadItem.RoundNo = 6 then
1597 // ThreadItem.RoundNo := 0;
1599 //
\88Ù
\8fí
\8fI
\97¹
\8e\9e\82Í
\83C
\83\93\83f
\83b
\83N
\83X
\82ª
\8dX
\90V
\82³
\82ê
\82È
\82¢
\82½
\82ß
\81A
\83e
\83\93\83|
\83\89\83\8a\82ð
\8dì
\90¬
\82·
\82é
\81B
1600 //
\90³
\8fí
\8fI
\97¹
\8e\9e\82É
\82Í
\8dí
\8f\9c
1601 //
\88Ù
\8fí
\8fI
\97¹
\8e\9e\82Í
\81A
\8e\9f\89ñ
\8bN
\93®
\8e\9e\82É
\83e
\83\93\83|
\83\89\83\8a\82ð
\8c©
\82Ä
\8dX
\90V
1602 ini := TMemIniFile.Create(ChangeFileExt(FileName, '.tmp'));
1604 ini.WriteDateTime('Setting', 'RoundDate', ThreadItem.RoundDate);
1605 ini.WriteDateTime('Setting', 'LastModified', ThreadItem.LastModified);
1606 ini.WriteInteger('Setting', 'Size', ThreadItem.Size);
1607 ini.WriteInteger('Setting', 'Count', ThreadItem.Count);
1608 ini.WriteInteger('Setting', 'AllResCount', ThreadItem.AllResCount);
1609 ini.WriteInteger('Setting', 'NewResCount', ThreadItem.NewResCount);
1610 ini.WriteInteger('Setting', 'NewReceive', ThreadItem.NewReceive);
1611 // ini.WriteInteger('Setting', 'RoundNo', ThreadItem.RoundNo);
1612 // ini.WriteBool('Setting', 'Round', ThreadItem.Round);
1613 ini.WriteBool('Setting', 'UnRead', ThreadItem.UnRead);
1620 procedure TDownloadThread.GetLastModified;
1622 ResultDate: TDateTime;
1623 ResList: TStringList;
1633 AWKStr := TAWKStr.Create(nil);
1635 ResultDate := Item.LastModified;
1636 ResList := TStringList.Create;
1638 ResList.Text := Item.Content;
1639 for ResRow := ResList.Count - 1 downto 0 do begin
1640 if (ResRow > 999) then
1642 LastRes := ResList.Strings[ResRow];
1643 KwPos := Pos('<>', LastRes);
1646 Delete(LastRes, 1, KwPos + 1);
1647 KwPos := Pos('<>', LastRes);
1650 Delete(LastRes, 1, KwPos + 1);
1651 // '2013/04/22(
\8c\8e) 02:32:36'
1652 SetLength(LastRes, 23);
1653 Delete(LastRes, 11, 4); //
\97j
\93ú
\8dí
\8f\9c
1656 // AWKStr.RegExp := '(\d{4})/(0[1-9]|1[0-2])/(0[1-9]|[12][0-9]|3[01])';
1657 AWKStr.RegExp := '(19|20)([0-9][0-9])/(0[1-9]|1[0-2])/(0[1-9]|[12][0-9]|3[01])';
1658 if (AWKStr.Match(AWKStr.ProcessEscSeq(LastRes), RStart, RLength) = 1) then begin
1660 AWKStr.RegExp := '([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])';
1661 if (AWKStr.Match(AWKStr.ProcessEscSeq(LastRes), RStart, RLength) < 1) then begin
1662 SetLength(LastRes, 10);
1663 LastRes := LastRes + ' 00:00:00';
1667 ResultDate := StrToDateTime(LastRes);
1678 Item.LastModified :=ResultDate;