X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=ItemDownload.pas;h=36b54972965113506209d93c719b56cb180609e4;hb=HEAD;hp=b36773191242107b20226b92be6f3a95e9caaec6;hpb=613bd8825894cf8a83d3ff1f4282fa006af1261c;p=gikonavigoeson%2Fgikonavi.git diff --git a/ItemDownload.pas b/ItemDownload.pas index b367731..36b5497 100644 --- a/ItemDownload.pas +++ b/ItemDownload.pas @@ -5,7 +5,8 @@ interface uses Windows, SysUtils, Classes, ComCtrls, Controls, Forms, IdHTTP, {HTTPApp,} YofUtils, IdGlobal, IdException, IdComponent, IniFiles, {DateUtils,} - GikoSystem, BoardGroup, MonaUtils, ExternalBoardManager; + GikoSystem, BoardGroup, ExternalBoardManager, ExternalBoardPlugInMain, + Sort, SyncObjs, bmRegExp; type TDownloadItem = class; @@ -15,7 +16,7 @@ type TGikoDLProgress = (gdpStd, gdpAll, gdpDatOchi, gdpOfflaw); TGikoWorkEvent = procedure(Sender: TObject; AWorkMode: TWorkMode; const AWorkCount: Integer; ID: Integer) of object; - TGikoWorkBeginEvent = procedure(Sender: TObject; AWorkMode: TWorkMode; const AWorkCountMax: Integer; ID: Integer) of object; + TGikoWorkBeginEvent = procedure(Sender: TObject; AWorkMode: TWorkMode; const AWorkCountMax: Integer; ID: Integer; const AWorkTitle: string) of object; TGikoWorkEndEvent = procedure(Sender: TObject; AWorkMode: TWorkMode; ID: Integer) of object; TDownloadEndEvent = procedure(Sender: TObject; Item: TDownloadItem) of object; TDownloadMsgEvent = procedure(Sender: TObject; Item: TDownloadItem; Msg: string; Icon: TGikoMessageIcon) of object; @@ -26,7 +27,17 @@ type FErrText: string; end; - + TWorkData = record + //FWorkCS: TCriticalSection; + //IdHttp‚ÌOnWorkAOnWorkBegin,OnWorkEnd‚͕ʂ̃XƒŒƒbƒh‚©‚ç + //ŒÄ‚΂ê‚éˆ×ASynchronize‚Å“¯Šú‚·‚é•K—v‚ª‚ ‚éB + //ƒNƒŠƒeƒBƒJƒ‹ƒZƒNƒVƒ‡ƒ“‚Í–³‚­‚Ä‚à‚½‚Ô‚ñ•½‹C‚¾‚¯‚Ç—pS‚ׁ̈B by eggcake + FWorkCS: TCriticalSection; + FSender: TObject; + FAWorkMode: TWorkMode; + FAWorkCount: Integer; + FAWorkCountMax: Integer + end; TDownloadThread = class(TThread) private FIndy: TIdHttp; @@ -41,6 +52,8 @@ type FOnWorkEnd: TGikoWorkEndEvent; FOnDownloadEnd: TDownloadEndEvent; FOnDownloadMsg: TDownloadMsgEvent; + FDownloadTitle: string; + FWorkData: TWorkData; procedure FireDownloadEnd; procedure FireDownloadMsg; @@ -49,16 +62,23 @@ type procedure WorkEnd(Sender: TObject; AWorkMode: TWorkMode); procedure Work(Sender: TObject; AWorkMode: TWorkMode; const AWorkCount: Integer); function ParseCgiStatus(Content: string): TCgiStatus; + function ParseRokkaStatus(Content: string): TCgiStatus; function CgiDownload(ItemType: TGikoDownloadType; URL: string; Modified: TDateTime): Boolean; function DatDownload(ItemType: TGikoDownloadType; URL: string; Modified: TDateTime; RangeStart: Integer; AdjustLen: Integer): Boolean; - function DeleteStatusLine(Content: string): string; - protected + procedure DeleteStatusLine(Item: TDownloadItem); + procedure InitHttpClient(client: TIdHttp); + procedure ClearHttpClient(client: TIdHttp); + procedure FireWork; + procedure FireWorkBegin; + procedure FireWorkEnd; + procedure GetLastModified; + protected procedure Execute; override; public property Item: TDownloadItem read FItem write FItem; property Number: Integer read FNumber write FNumber; constructor Create(CreateSuspended: Boolean); - destructor Destroy; override; + destructor Destroy; override; procedure Abort; property OnWork: TGikoWorkEvent read FOnWork write FOnWork; property OnWorkBegin: TGikoWorkBeginEvent read FOnWorkBegin write FOnWorkBegin; @@ -79,6 +99,8 @@ type FResponseCode: Smallint; FState: TGikoDownloadState; FErrText: string; + FForceDownload: Boolean; + FIsAbone : Boolean; public procedure SaveListFile; procedure SaveItemFile; @@ -93,13 +115,20 @@ type property ResponseCode: Smallint read FResponseCode write FResponseCode; property State: TGikoDownloadState read FState write FState; property ErrText: string read FErrText write FErrText; + property ForceDownload: Boolean read FForceDownload write FForceDownload; + property IsAbone : Boolean read FIsAbone write FIsAbone; end; implementation +uses + Y_TextConverter, MojuUtils, HTMLCreate, ReplaceDataModule; + constructor TDownloadThread.Create(CreateSuspended: Boolean); begin inherited Create(CreateSuspended); + FWorkData.FWorkCS := TCriticalSection.Create; + FIndy := TIdHttp.Create(nil); FIndy.OnWorkBegin := WorkBegin; @@ -109,7 +138,9 @@ end; destructor TDownloadThread.Destroy; begin + ClearHttpClient(FIndy); FIndy.Free; + FWorkData.FWorkCS.Free; inherited; end; @@ -130,7 +161,66 @@ begin [Day, Copy(StrMonth, 1 + 3 * (Month - 1), 3), Year, Hour, Min, Sec]); end; - +// ****************************************************************** +// HTTPClient‚̏‰Šú‰» +// ****************************************************************** +procedure TDownloadThread.InitHttpClient(client: TIdHttp); +begin + ClearHttpClient(client); + client.Disconnect; + client.Request.UserAgent := GikoSys.GetUserAgent; + client.RecvBufferSize := Gikosys.Setting.RecvBufferSize; + client.ProxyParams.BasicAuthentication := False; + client.ReadTimeout := GikoSys.Setting.ReadTimeOut; + client.ConnectTimeout := GikoSys.Setting.ReadTimeOut; + {$IFDEF DEBUG} + Writeln('------------------------------------------------------------'); + {$ENDIF} + //FIndy.AllowCookies := False; + if GikoSys.Setting.ReadProxy then begin + if GikoSys.Setting.ProxyProtocol then + client.ProtocolVersion := pv1_1 + else + client.ProtocolVersion := pv1_0; + client.ProxyParams.ProxyServer := GikoSys.Setting.ReadProxyAddress; + client.ProxyParams.ProxyPort := GikoSys.Setting.ReadProxyPort; + client.ProxyParams.ProxyUsername := GikoSys.Setting.ReadProxyUserID; + client.ProxyParams.ProxyPassword := GikoSys.Setting.ReadProxyPassword; + if GikoSys.Setting.ReadProxyUserID <> '' then + client.ProxyParams.BasicAuthentication := True; + {$IFDEF DEBUG} + Writeln('ƒvƒƒLƒVÝ’è‚ ‚è'); + Writeln('ƒzƒXƒg: ' + GikoSys.Setting.ReadProxyAddress); + Writeln('ƒ|[ƒg: ' + IntToStr(GikoSys.Setting.ReadProxyPort)); + {$ENDIF} + end else begin + if GikoSys.Setting.Protocol then + client.ProtocolVersion := pv1_1 + else + client.ProtocolVersion := pv1_0; + client.ProxyParams.ProxyServer := ''; + client.ProxyParams.ProxyPort := 80; + client.ProxyParams.ProxyUsername := ''; + client.ProxyParams.ProxyPassword := ''; + {$IFDEF DEBUG} + Writeln('ƒvƒƒLƒVÝ’è‚È‚µ'); + {$ENDIF} + end; +end; +// ****************************************************************** +// HTTPClient‚̃ŠƒNƒGƒXƒg‚ƃŒƒXƒ|ƒ“ƒX‚̃f[ƒ^‚̏Á‹Ž +// ****************************************************************** +procedure TDownloadThread.ClearHttpClient(client: TIdHttp); +begin + client.Request.CustomHeaders.Clear; + client.Request.RawHeaders.Clear; + client.Request.Clear; + client.Response.CustomHeaders.Clear; + client.Response.RawHeaders.Clear; + client.Response.Clear; + + client.ProxyParams.Clear; +end; procedure TDownloadThread.Execute; var ResStream: TMemoryStream; @@ -143,21 +233,28 @@ var Idx: Integer; ATitle: string; DownloadResult: Boolean; - Abone: Boolean; - foundPos: Integer; - boardPlugIn : TBoardPlugIn; - listContent : string; + boardPlugIn : TBoardPlugIn; + lastContent : string; + logFile : TFileStream; + adjustMargin : Integer; + Host: String; + Sep: Integer; +const + ADJUST_MARGIN = 16; begin while not Terminated do begin //===== ƒvƒ‰ƒOƒCƒ“ + FAbort := False; boardPlugIn := nil; ExternalBoardManager.OnWork := Work; ExternalBoardManager.OnWorkBegin := WorkBegin; ExternalBoardManager.OnWorkEnd := WorkEnd; + FDownloadTitle := ''; case FItem.FDownType of gdtBoard: begin + FDownloadTitle := FItem.FBoard.Title; if FItem.FBoard <> nil then begin if FItem.FBoard.IsBoardPlugInAvailable then begin boardPlugIn := FItem.FBoard.BoardPlugIn; @@ -167,18 +264,26 @@ begin end; gdtThread: begin + FDownloadTitle := FItem.FThreadItem.Title; if FItem.FThreadItem <> nil then begin - if FItem.FThreadItem.IsBoardPlugInAvailable then begin - boardPlugIn := FItem.FThreadItem.BoardPlugIn; + if FItem.FThreadItem.ParentBoard.IsBoardPlugInAvailable then begin + boardPlugIn := FItem.FThreadItem.ParentBoard.BoardPlugIn; Item.State := TGikoDownloadState( boardPlugIn.DownloadThread( DWORD( FItem.FThreadItem ) ) ); end; + //if FItem.FThreadItem.IsBoardPlugInAvailable then begin + // boardPlugIn := FItem.FThreadItem.BoardPlugIn; + // Item.State := TGikoDownloadState( boardPlugIn.DownloadThread( DWORD( FItem.FThreadItem ) ) ); + //end; end; end; end; + if Length(FDownloadTitle) = 0 then + FDownloadTitle := 'i–¼Ì•s–¾j'; if boardPlugIn <> nil then begin - if FAbort then + if FAbort then begin Item.State := gdsAbort; + end; if Assigned( OnDownloadEnd ) then Synchronize( FireDownloadEnd ); if Terminated then @@ -188,48 +293,26 @@ begin Continue; end; - //===== ƒvƒ‰ƒOƒCƒ“‚ðŽg—p‚µ‚È‚¢ê‡ FAbort := False; - FIndy.Request.CustomHeaders.Clear; - FIndy.Response.Clear; - FIndy.Request.Clear; - FIndy.ProxyParams.Clear; - FIndy.Disconnect; - FIndy.Request.UserAgent := GikoSys.GetUserAgent; - FIndy.RecvBufferSize := Gikosys.Setting.RecvBufferSize; - FIndy.ProxyParams.BasicAuthentication := False; - {$IFDEF DEBUG} - Writeln('------------------------------------------------------------'); - {$ENDIF} - //FIndy.AllowCookies := False; - if GikoSys.Setting.ReadProxy then begin - if GikoSys.Setting.ProxyProtocol then - FIndy.ProtocolVersion := pv1_1 - else - FIndy.ProtocolVersion := pv1_0; - FIndy.ProxyParams.ProxyServer := GikoSys.Setting.ReadProxyAddress; - FIndy.ProxyParams.ProxyPort := GikoSys.Setting.ReadProxyPort; - FIndy.ProxyParams.ProxyUsername := GikoSys.Setting.ReadProxyUserID; - FIndy.ProxyParams.ProxyPassword := GikoSys.Setting.ReadProxyPassword; - if GikoSys.Setting.ReadProxyUserID <> '' then - FIndy.ProxyParams.BasicAuthentication := True; - {$IFDEF DEBUG} - Writeln('ƒvƒƒLƒVÝ’è‚ ‚è'); - Writeln('ƒzƒXƒg: ' + GikoSys.Setting.ReadProxyAddress); - Writeln('ƒ|[ƒg: ' + IntToStr(GikoSys.Setting.ReadProxyPort)); - {$ENDIF} - end else begin - if GikoSys.Setting.Protocol then - FIndy.ProtocolVersion := pv1_1 - else - FIndy.ProtocolVersion := pv1_0; - FIndy.ProxyParams.ProxyServer := ''; - FIndy.ProxyParams.ProxyPort := 80; - FIndy.ProxyParams.ProxyUsername := ''; - FIndy.ProxyParams.ProxyPassword := ''; - {$IFDEF DEBUG} - Writeln('ƒvƒƒLƒVÝ’è‚È‚µ'); - {$ENDIF} + //===== ƒvƒ‰ƒOƒCƒ“‚ðŽg—p‚µ‚È‚¢ê‡ + InitHttpClient(FIndy); + adjustMargin := 0; + if Item.DownType = gdtThread then begin + if FileExists( Item.ThreadItem.GetThreadFileName ) then begin + // dat ƒtƒ@ƒCƒ‹‚̍Ōã‚ð“ǂݏo‚· + SetLength( lastContent, ADJUST_MARGIN + 1 ); + logFile := TFileStream.Create( Item.ThreadItem.GetThreadFileName, fmOpenRead or fmShareDenyWrite ); + try + logFile.Seek( -(ADJUST_MARGIN + 1), soFromEnd ); + logFile.Read( lastContent[ 1 ], ADJUST_MARGIN + 1 ); + lastContent := StringReplace( lastContent, #13, '', [] ); // CR ‚̍폜 + finally + logFile.Free; + end; + end else begin + lastContent := ''; + end; + adjustMargin := Length( lastContent ); end; FIndy.Request.ContentRangeStart := 0; @@ -251,7 +334,19 @@ begin Writeln('Modified: ' + FloatToStr(Item.Board.LastModified)); {$ENDIF} URL := Item.Board.GetReadCgiURL; - Modified := Item.Board.LastModified; + if Item.ForceDownload then begin + // ‹­§Žæ“¾ + ATitle := Item.Board.Title; + if ATitle = '' then + ATitle := 'i–¼Ì•s–¾j'; + FMsg := 'š‹­§Žæ“¾‚ðs‚¢‚Ü‚· - [' + ATitle + ']'; + FIcon := gmiWhat; + if Assigned(OnDownloadMsg) then + Synchronize(FireDownloadMsg); + Modified := ZERO_DATE + end else begin + Modified := Item.Board.LastModified; + end; end else if Item.DownType = gdtThread then begin {$IFDEF DEBUG} Writeln('DATŽæ“¾'); @@ -259,41 +354,59 @@ begin Writeln('Modified: ' + FloatToStr(Item.ThreadItem.LastModified)); {$ENDIF} URL := Item.ThreadItem.GetDatURL; - Modified := Item.ThreadItem.LastModified; - if Item.ThreadItem.Size > 0 then begin - {$IFDEF DEBUG} - Writeln('RangeStart: ' + IntToStr(Item.ThreadItem.Size)); - {$ENDIF} - //‚ ‚ځ[‚ñƒ`ƒFƒbƒN‚Ì‚½‚ß‚PƒoƒCƒg‘O‚©‚çŽæ“¾ - RangeStart := Item.ThreadItem.Size; - AdjustLen := -1; + if Item.ForceDownload then begin + // ‹­§Žæ“¾ + ATitle := Item.ThreadItem.Title; + if ATitle = '' then + ATitle := 'i–¼Ì•s–¾j'; + FMsg := 'š‹­§Žæ“¾‚ðs‚¢‚Ü‚· - [' + ATitle + ']'; + FIcon := gmiWhat; + if FileExists(ChangeFileExt(Item.FThreadItem.GetThreadFileName,'.NG')) = true then + DeleteFile(ChangeFileExt(Item.FThreadItem.GetThreadFileName,'.NG')); + if Assigned(OnDownloadMsg) then + Synchronize(FireDownloadMsg); + Modified := ZERO_DATE; + RangeStart := 0; + AdjustLen := 0; + end else begin + Modified := Item.ThreadItem.LastModified; + if Item.ThreadItem.Size > 0 then begin + {$IFDEF DEBUG} + Writeln('RangeStart: ' + IntToStr(Item.ThreadItem.Size)); + {$ENDIF} + // ‚ ‚ځ[‚ñƒ`ƒFƒbƒN‚Ì‚½‚ß adjustMargin ƒoƒCƒg‘O‚©‚çŽæ“¾ + RangeStart := Item.ThreadItem.Size; + AdjustLen := -adjustMargin; + end; end; end; - Abone := False; + Item.IsAbone := False; DownloadResult := DatDownload(Item.DownType, URL, Modified, RangeStart, AdjustLen); {$IFDEF DEBUG} Writeln('ResponseCode: ' + IntToStr(FIndy.ResponseCode)); {$ENDIF} if Item.DownType = gdtThread then begin if Item.ResponseCode = 416 then begin - Abone := True; + Item.IsAbone := True; DownloadResult := True; - end else if DownloadResult and (AdjustLen = -1) and (Item.Content[1] <> #10) then - Abone := True; + end else if DownloadResult and (AdjustLen < 0) then begin + if Copy( Item.Content, 1, adjustMargin ) <> lastContent then + Item.IsAbone := True; + end; end; if Trim(FIndy.Response.RawHeaders.Values['Date']) <> '' then begin if Item.DownType = gdtBoard then - Item.Board.LastGetTime := MonaUtils.DateStrToDateTime(FIndy.Response.RawHeaders.Values['Date']) + Item.Board.LastGetTime := GikoSys.DateStrToDateTime(FIndy.Response.RawHeaders.Values['Date']) else - Item.ThreadItem.ParentBoard.LastGetTime := MonaUtils.DateStrToDateTime(FIndy.Response.RawHeaders.Values['Date']); + Item.ThreadItem.ParentBoard.LastGetTime := GikoSys.DateStrToDateTime(FIndy.Response.RawHeaders.Values['Date']); end; if DownloadResult then begin {$IFDEF DEBUG} Writeln('Date:' + FIndy.Response.RawHeaders.Values['Date']); {$ENDIF} - if Abone then begin + if Item.IsAbone then begin {$IFDEF DEBUG} Writeln('‚ ‚ځ[‚ñŒŸo'); {$ENDIF} @@ -315,9 +428,9 @@ begin Writeln('‚ ‚ځ[‚ñÄŽæ“¾Œã'); Writeln('ResponseCode: ' + IntToStr(Item.ResponseCode)); {$ENDIF} - end else if (Item.DownType = gdtThread) and (AdjustLen = -1) and (Item.Content[1] = #10) then begin - //·•ªŽæ“¾‚©‚‚PƒoƒCƒg–Ú‚ªLF‚̏ꍇi³íŽæ“¾j‚Í“ª‚ÌLF‚ðíœ - Item.Content := Copy(Item.Content, 2, Length(Item.Content)); + end else if (Item.DownType = gdtThread) and (AdjustLen < 0) then begin + // ·•ªŽæ“¾‚ªo—ˆ‚½ê‡‚Í‚ ‚ځ[‚ñƒ`ƒFƒbƒN—p‚Ɏ擾‚µ‚½—]•ª‚ȃTƒCƒY‚ðíœ + Item.Content := Copy(Item.Content, adjustMargin + 1, MaxInt); end; end else begin Item.State := gdsError; @@ -355,6 +468,28 @@ begin end; //******************** + //dat.gz@¨@dat‚̎擾@2005”N6ŒŽ’ljÁ@by‚à‚¶‚ã + //******************** + if (Item.DownType = gdtThread) and (Item.ResponseCode = 302) then begin + {$IFDEF DEBUG} + Writeln('datŽæ“¾'); + {$ENDIF} + FMsg := '‰ß‹ŽƒƒO(dat.gz)‚ª‘¶Ý‚µ‚È‚¢‚½‚߉ߋŽƒƒO(dat)‚ð’T‚µ‚Ü‚· - [' + ATitle + ']'; + FIcon := gmiWhat; + if Assigned(OnDownloadMsg) then + Synchronize(FireDownloadMsg); + URL := ChangeFileExt(URL, ''); + Modified := Item.ThreadItem.LastModified; + RangeStart := 0; + AdjustLen := 0; + if not DatDownload(Item.DownType, URL, Modified, RangeStart, AdjustLen) then + Item.State := gdsError; + {$IFDEF DEBUG} + Writeln('ResponseCode: ' + IntToStr(Item.ResponseCode)); + {$ENDIF} + end; + + //******************** //dat.gzŽæ“¾(2) //******************** { @@ -375,6 +510,148 @@ begin end; } + if (Item.DownType = gdtThread) and (Item.ResponseCode = 302) then begin + {$IFDEF DEBUG} + Writeln('offlaw2.so‚Ŏ擾'); + {$ENDIF} + ATitle := Item.ThreadItem.Title; + if ATitle = '' then + ATitle := 'i–¼Ì•s–¾j'; + FMsg := 'šdat.gz‚ª‘¶Ý‚µ‚È‚¢‚½‚ßofflaw2.so‚ð—˜—p‚µ‚Ü‚· - [' + ATitle + ']'; + FIcon := gmiWhat; + if Assigned(OnDownloadMsg) then + Synchronize(FireDownloadMsg); + URL := Item.ThreadItem.GetOfflaw2SoURL; + Modified := Item.ThreadItem.LastModified; + RangeStart := 0; + AdjustLen := 0; + if not DatDownload(Item.DownType, URL, Modified, RangeStart, AdjustLen) then begin + {$IFDEF DEBUG} + Writeln('ResponseCode: ' + IntToStr(Item.ResponseCode)); + {$ENDIF} + Item.State := gdsError; + + if (Item.DownType = gdtThread) and (Item.ResponseCode = 302) then begin + FMsg := '”‚ªˆÚ“]‚µ‚½‚©‚à‚µ‚ê‚È‚¢‚̂ŔXV‚ðs‚Á‚Ä‚­‚¾‚³‚¢B'; + FIcon := gmiNG; + if Assigned(OnDownloadMsg) then + Synchronize(FireDownloadMsg); + end; + + end else begin + {$IFDEF DEBUG} + Writeln('ResponseCode: ' + IntToStr(Item.ResponseCode)); + {$ENDIF} + if Item.ResponseCode = 200 then begin + {$IFDEF DEBUG} + Writeln('CGIStatus: OK'); + {$ENDIF} + if Copy(Item.Content, 1, 5) = 'ERROR' then begin + {$IFDEF DEBUG} + Writeln('Offlow2Error'); + {$ENDIF} + Item.ResponseCode := 404; + Item.State := gdsError; + Item.ErrText := 'ƒXƒŒ‚Í‘¶Ý‚µ‚È‚¢‚悤‚Å‚·B' + Item.Content; + end else begin + GetLastModified; + end; + end else begin + {$IFDEF DEBUG} + Writeln('CGIStatus: 404(ERROR)'); + {$ENDIF} + Item.ResponseCode := 404; + Item.State := gdsError; + Item.ErrText := CgiStatus.FErrText; + end; + end; + end; + + if (Item.DownType = gdtThread) and ((Item.ResponseCode = 302) or (Item.ResponseCode = 404)) then begin + FSessionID := ''; + Synchronize(GetSessionID); + if (FSessionID <> '') then begin + {$IFDEF DEBUG} + Writeln('Rokka‚Ŏ擾'); + {$ENDIF} + ATitle := Item.ThreadItem.Title; + if ATitle = '' then + ATitle := 'i–¼Ì•s–¾j'; + FMsg := 'šofflow2.so‚É‘¶Ý‚µ‚È‚¢‚½‚ßRokka‚ð—˜—p‚µ‚Ü‚· - [' + ATitle + ']'; + FIcon := gmiWhat; + if Assigned(OnDownloadMsg) then + Synchronize(FireDownloadMsg); + URL := Item.ThreadItem.GetRokkaURL(FSessionID); + Modified := Item.ThreadItem.LastModified; + RangeStart := 0; + AdjustLen := 0; + + if not DatDownload(Item.DownType, URL, Modified, RangeStart, AdjustLen) then begin + {$IFDEF DEBUG} + Writeln('ResponseCode: ' + IntToStr(Item.ResponseCode)); + {$ENDIF} + Item.State := gdsError; + end else begin + CgiStatus := ParseRokkaStatus(Item.Content); + {$IFDEF DEBUG} + Writeln('ResponseCode: ' + IntToStr(Item.ResponseCode)); + {$ENDIF} + case CgiStatus.FStatus of + gcsOK: begin + {$IFDEF DEBUG} + Writeln('CGIStatus: OK'); + {$ENDIF} + Item.ResponseCode := 200; + DeleteStatusLine(Item); + end; + gcsERR: begin + {$IFDEF DEBUG} + Writeln('CGIStatus: 404(ERROR)'); + {$ENDIF} + Item.ResponseCode := 404; + Item.State := gdsError; + Item.ErrText := CgiStatus.FErrText; + end; + end; + end; + end; + end; + + //******************** + // 2chŠO•”” + //******************** +// if not GikoSys.Is2chHost(GikoSys.UrlToServer(URL)) then begin + Host := URL; + Sep := Pos('://', Host); + if (Sep > 0) then + Delete(Host, 1, Sep + 2); + Sep := Pos('/', Host); + if (Sep > 0) then + SetLength(Host, Sep - 1); + if not GikoSys.Is2chHost(Host) then begin + if (Item.DownType = gdtThread) and (Item.ResponseCode = 404) then begin + {$IFDEF DEBUG} + Writeln('ŠO•””‰ߋŽƒƒOŽæ“¾'); + {$ENDIF} + ATitle := Item.ThreadItem.Title; + if ATitle = '' then + ATitle := 'i–¼Ì•s–¾j'; + FMsg := 'š‚Q‚¿‚á‚ñ‚Ë‚éŠO•””‚̉ߋŽƒƒOŽæ“¾‚ðs‚¢‚Ü‚· - [' + ATitle + ']'; + FIcon := gmiWhat; + if Assigned(OnDownloadMsg) then + Synchronize(FireDownloadMsg); + URL := Item.ThreadItem.GetExternalBoardKakoDatURL; + Modified := Item.ThreadItem.LastModified; + RangeStart := 0; + AdjustLen := 0; + if not DatDownload(Item.DownType, URL, Modified, RangeStart, AdjustLen) then + Item.State := gdsError; + {$IFDEF DEBUG} + Writeln('ResponseCode: ' + IntToStr(Item.ResponseCode)); + {$ENDIF} + end; + end; +(* //******************** //offlaw.cgi‚Ŏ擾 //******************** @@ -419,8 +696,7 @@ begin Writeln('CGIStatus: OK'); {$ENDIF} Item.ResponseCode := 200; - Item.Content := DeleteStatusLine(Item.Content); - Item.ContentLength := CgiStatus.FSize; + DeleteStatusLine(Item); end; gcsINCR: begin //¡‚Í‚ ‚肦‚È‚¢ @@ -428,8 +704,7 @@ begin Writeln('CGIStatus: 206'); {$ENDIF} Item.ResponseCode := 206; - Item.Content := DeleteStatusLine(Item.Content); - Item.ContentLength := CgiStatus.FSize; + DeleteStatusLine(Item); end; gcsERR: begin {$IFDEF DEBUG} @@ -486,41 +761,7 @@ begin Synchronize(FireDownloadMsg); end; end; - - {$IFDEF DEBUG} - if (Item.DownType = gdtThread) and (Item.ResponseCode = 302) then begin - ATitle := Item.ThreadItem.Title; - if ATitle = '' then - ATitle := 'i–¼Ì•s–¾j'; - FMsg := 'š‰ß‹ŽƒƒO(1)‚ª‘¶Ý‚µ‚È‚¢‚½‚ßgoogleƒLƒƒƒbƒVƒ…‚©‚ç’T‚µ‚Ü‚· - [' + ATitle + ']'; - FIcon := gmiWhat; - if Assigned(OnDownloadMsg) then - Synchronize(FireDownloadMsg); - URL := 'http://www.google.co.jp/search?q=cache:' + Item.ThreadItem.URL; - URL := StringReplace( URL, 'l50', '', [rfReplaceAll] ); - Modified := Item.ThreadItem.LastModified; - Repeat - if not CgiDownload(Item.DownType, URL, Modified) then - Item.State := gdsError; - URL := FIndy.Response.Location; - Until Item.ResponseCode <> 301; - if Item.ResponseCode = 200 then begin - foundPos := Pos( '
', Item.Content ) + Length( '
' ); - Item.Content := Copy( Item.Content, foundPos, Length( Item.Content ) ); - foundPos := Pos( '', Item.Content ); - If foundPos > 0 Then - Item.Content := Copy( Item.Content, 1, foundPos - 1 ); - Item.Content := StringReplace( Item.Content, '
', '<>' + #13#10, [rfReplaceAll] ); - Item.Content := StringReplace( Item.Content, '', '<>', [rfReplaceAll] ); - Item.Content := StringReplace( Item.Content, '', '<>', [rfReplaceAll] ); - Item.Content := StringReplace( Item.Content, '', '<>', [rfReplaceAll] ); - Item.Content := StringReplace( Item.Content, '', '<>', [rfReplaceAll] ); - Item.Content := StringReplace( Item.Content, '
', '<>', [rfReplaceAll] ); - end; - end; - {$ENDIF} - +*) case Item.ResponseCode of 200: Item.State := gdsComplete; 206: Item.State := gdsDiffComplete; @@ -528,68 +769,9 @@ begin else Item.State := gdsError; end; -{ - //–³‚¢‚ÆŽv‚¤‚¯‚ǁBBB - if (Item.ResponseCode in [200, 206]) and (Item.Content = '') then - Item.State := gdsError; - Item.LastModified := FIndy.Response.LastModified; - //·•ªŽæ“¾‚Å‚PƒoƒCƒg‘O‚©‚ç‚Æ‚Á‚Ä‚«‚½‚Æ‚«‚̓}ƒCƒiƒX‚·‚é - Item.ContentLength := FIndy.Response.ContentLength + AdjustLen; - try - ResStream.Clear; - FIndy.Get(URL, ResStream); - Item.Content := GikoSys.GzipDecompress(ResStream, FIndy.Response.ContentEncoding); - if (Item.DownType = gdtThread) and (AdjustLen = -1) and (Item.Content[1] <> #10) then begin - //·•ªŽæ“¾‚©‚‚PƒoƒCƒg–Ú‚ªLF‚Å‚È‚¢ê‡‚́u‚ ‚ځ[‚ñv‚³‚ê‚Ä‚¢‚é‚©‚à‚µ‚ê‚ñ‚̂ōĎ擾 - //‚±‚±‚сƒbƒZ[ƒW•\Ž¦ƒCƒxƒ“ƒg - //event - FMsg := 'u‚ ‚ځ[‚ñv‚ðŒŸo‚µ‚½‚̂ōĎ擾‚ðs‚¢‚Ü‚·'; - if Assigned(OnDownloadMsg) then - Synchronize(FireDownloadMsg); - FIndy.Request.ContentRangeStart := 0; - FIndy.Request.ContentRangeEnd := 0; - AdjustLen := 0; - ResStream.Clear; - FIndy.Get(URL, ResStream); - Item.Content := GikoSys.GzipDecompress(ResStream, FIndy.Response.ContentEncoding); - end else if (Item.DownType = gdtThread) and (AdjustLen = -1) and (Item.Content[1] = #10) then begin - //·•ªŽæ“¾‚©‚‚PƒoƒCƒg–Ú‚ªLF‚̏ꍇi³íŽæ“¾j‚Í“ª‚ÌLF‚ðíœ - Item.Content := Copy(Item.Content, 2, Length(Item.Content)); - end; - except - Item.State := gdsError; - end; - Item.ResponseCode := FIndy.ResponseCode; -} -{ - try - ResStream.Clear; - FIndy.Get(URL, ResStream); - Item.Content := GikoSys.GzipDecompress(ResStream, FIndy.Response.ContentEncoding); - except - Item.State := gdsError; - end; - - CgiStatus := ParseCgiStatus(Item.Content); - if CgiStatus.FStatus = gcsOK then begin - if CgiStatus.FSize = 0 then - Item.State := gdsNotModify - else if Item.DownType = gdtBoard then - Item.State := gdsComplete - else - Item.State := gdsDiffComplete; - end else if CgiStatus.FStatus = gcsINCR then begin - Item.State := gdsComplete; - end else if CgiStatus.FStatus = gcsERR then begin - Item.State := gdsError; - Item.ErrText := CgiStatus.FErrText; - end; - Item.ContentLength := CgiStatus.FSize; - } except Item.State := gdsError; end; - //Item.ResponseCode := FIndy.ResponseCode; if FAbort then Item.State := gdsAbort; finally @@ -597,6 +779,9 @@ begin Synchronize(FireDownloadEnd); ResStream.Free; end; + + ClearHttpClient(FIndy); + if Terminated then Break; Suspend; end; @@ -687,8 +872,6 @@ var begin ResponseCode := -1; if (ItemType = gdtThread) and (RangeStart > 0) then begin -// if (ItemType = gdtThread) and (Item.ThreadItem.Size > 0) then begin -// FIndy.Request.ContentRangeStart := Item.ThreadItem.Size + AdjustLen; FIndy.Request.ContentRangeStart := RangeStart + AdjustLen; FIndy.Request.ContentRangeEnd := 0; end else begin @@ -701,9 +884,7 @@ begin FIndy.Request.CustomHeaders.Add('Pragma: no-cache'); if (Modified <> 0) and (Modified <> ZERO_DATE) then begin FIndy.Request.LastModified := modified - OffsetFromUTC; - //FIndy.Request.CustomHeaders.Add('If-Modified-Since: ' + RFC1123_Date(modified - OffsetFromUTC) + ' GMT'); end; -// FIndy.Request.AcceptEncoding := 'gzip'; if RangeStart = 0 then FIndy.Request.AcceptEncoding := 'gzip' else @@ -716,14 +897,13 @@ begin Writeln('URL: ' + URL); {$ENDIF} FIndy.Get(URL, ResStream); - Item.Content := GikoSys.GzipDecompress(ResStream, FIndy.Response.ContentEncoding); - Item.LastModified := FIndy.Response.LastModified; - //·•ªŽæ“¾‚Å‚PƒoƒCƒg‘O‚©‚ç‚Æ‚Á‚Ä‚«‚½‚Æ‚«‚̓}ƒCƒiƒX‚·‚é -// Item.ContentLength := FIndy.Response.ContentLength + AdjustLen; + Item.Content := GikoSys.GzipDecompress(ResStream, FIndy.Response.ContentEncoding); Item.ContentLength := Length(Item.Content) + AdjustLen; - //–³‚¢‚ÆŽv‚¤‚¯‚ǁBBB -// if (FIndy.ResponseCode in [200, 206]) and (Item.Content = '') then -// Result := False + // ’uŠ·‚·‚é + if GikoSys.Setting.ReplaceDat then begin + Item.Content := ReplaceDM.Replace(Item.Content); + end; + Item.LastModified := FIndy.Response.LastModified; if Item.Content = '' then Result := False else @@ -793,24 +973,77 @@ procedure TDownloadThread.Abort; begin FAbort := True; FIndy.DisconnectSocket; + if socket <> nil then begin + socket.DisconnectSocket; + end; +end; + +procedure TDownloadThread.WorkBegin(Sender: TObject; +AWorkMode: TWorkMode; const AWorkCountMax: Integer); +begin + if Assigned(OnWorkBegin) then begin + FWorkData.FWorkCS.Acquire; + try + FWorkData.FSender := Sender; + FWorkData.FAWorkMode := AWorkMode; + FWorkData.FAWorkCountMax := AWorkCountMax; + Synchronize(FireWorkBegin); + finally + FWorkData.FWorkCS.Release; + end; + end; +end; + +procedure TDownloadThread.WorkEnd(Sender: TObject; +AWorkMode: TWorkMode); +begin + if Assigned(OnWorkEnd) then begin; + FWorkData.FWorkCS.Acquire; + try + FWorkData.FSender := Sender; + FWorkData.FAWorkMode := AWorkMode; + Synchronize(FireWorkEnd); + finally + FWorkData.FWorkCS.Release; + end; + end; +end; + +procedure TDownloadThread.Work(Sender: TObject; AWorkMode: +TWorkMode; const AWorkCount: Integer); +begin + if Assigned(OnWork) then begin + FWorkData.FWorkCS.Acquire; + try + FWorkData.FSender := Sender; + FWorkData.FAWorkMode := AWorkMode; + FWorkData.FAWorkCount := AWorkCount; + Synchronize(FireWork); + finally + FWorkData.FWorkCS.Release; + end; + end; end; -procedure TDownloadThread.WorkBegin(Sender: TObject; AWorkMode: TWorkMode; const AWorkCountMax: Integer); +//‚±‚±‚©‚çV‹Kƒƒ\ƒbƒh +procedure TDownloadThread.FireWorkBegin; begin - if Assigned(OnWorkBegin) then - OnWorkBegin(Sender, AWorkMode, AWorkCountMax, FNumber); + OnWorkBegin(FWorkData.FSender, FWorkData.FAWorkMode, + FWorkData.FAWorkCountMax, + FNumber, FDownloadTitle); end; -procedure TDownloadThread.WorkEnd(Sender: TObject; AWorkMode: TWorkMode); +procedure TDownloadThread.FireWorkEnd; begin - if Assigned(OnWorkEnd) then - OnWorkEnd(Sender, AWorkMode, FNumber); + OnWorkEnd(FWorkData.FSender, FWorkData.FAWorkMode, + FNumber); end; -procedure TDownloadThread.Work(Sender: TObject; AWorkMode: TWorkMode; const AWorkCount: Integer); +procedure TDownloadThread.FireWork; begin - if Assigned(OnWork) then - OnWork(Sender, AWorkMode, AWorkCount, FNumber); + OnWork(FWorkData.FSender, FWorkData.FAWorkMode, + FWorkData.FAWorkCount, + FNumber); end; function TDownloadThread.ParseCgiStatus(Content: string): TCgiStatus; @@ -869,17 +1102,84 @@ begin end; end; -//Žè”²‚«‚ȏˆ—‚Å1s–Ú‚ðÁ‚· -function TDownloadThread.DeleteStatusLine(Content: string): string; +function TDownloadThread.ParseRokkaStatus(Content: string): TCgiStatus; +var + StatusLine: string; + Idx: Integer; + Status: string; +begin +// @ƒŒƒXƒ|ƒ“ƒX : 1s–Ú‚Érokka‚̏ˆ—Œ‹‰Ê‚ª‹Lq‚³‚ê‚Ü‚· +// @@"Success XXX"@- ¬Œ÷@XXX‚Édat‚̏ó‘ԁiŽæ“¾Œ³j‚ª‹Lq‚³‚ê‚Ü‚· +// @@@@@@@@@@@Live@@@@ƒ‰ƒCƒuƒXƒŒƒbƒh +// @@@@@@@@@@@Pool@@@@dat—Ž‚¿ƒXƒŒƒbƒh +// @@@@@@@@@@@Archive @@‰ß‹ŽƒƒO +// @@@@@@@@@@ ˆÈ~‚̍s‚ÉDATŒ`Ž®(name<>email<>datetime<>body<>[title])‚эƒO‚ª‹Lq‚³‚ê‚Ä‚¢‚Ü‚· +// @@"Error XXX"@@- ‰½‚ç‚©‚̃Gƒ‰[‚Å‚·@XXX ‚ªƒGƒ‰[ƒR[ƒh‚Å‚·B +// @@@@@@@@@@@13 @@@not found@@@@@@—v‹‚³‚ꂽdat‚ªŒ©‚‚©‚è‚Ü‚¹‚ñ‚Å‚µ‚½ +// @@@@@@@@@@@8008135@inputError @@@@@ƒŠƒNƒGƒXƒgURL‚ÌSERVER‚©BOARD‚ª³‚µ‚­‚È‚¢‚Å‚· +// @@@@@@@@@@@666@@@urlError @@@@@@OPTIONS‚Ü‚½‚ÍQueryString‚ª³‚µ‚­‚È‚¢‚Å‚· +// @@@@@@@@@@@69 @@@authenticationError@KAGI‚ª•s³i—LŒøŠúŒÀØ‚ê‚»‚Ì‘¼j +// @@@@@@@@@@@420@@@timeLimitError @@@ƒAƒNƒZƒXŠÔŠu‚ª’Z‚·‚¬‚Ü‚· +// @@@@@@@@@@@42 @@@methodError@@@@@‚»‚ÌHTTPƒƒ\ƒbƒh‚Í‹–‰Â‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ + Idx := AnsiPos(#10, Content); + if (Idx > 0) then + StatusLine := Copy(Content, 0, Idx) + else + StatusLine := Content; + + if (AnsiPos('Success', StatusLine) = 1) then begin + Result.FStatus := gcsOK; + Delete(StatusLine, 1, 7); + Status := Trim(StatusLine); + if (Status = 'Live') then // ‘½•ª‚±‚ê‚Í—ˆ‚È‚¢ + Result.FErrText := 'Žæ“¾¬Œ÷iƒ‰ƒCƒuƒXƒŒƒbƒhj' + else if (Status = 'Pool') then + Result.FErrText := 'Žæ“¾¬Œ÷idat—Ž‚¿ƒXƒŒƒbƒhj' + else if (Status = 'Archive') then + Result.FErrText := 'Žæ“¾¬Œ÷i‰ß‹ŽƒƒOj' + else // ??? + Result.FErrText := 'Žæ“¾¬Œ÷'; + end + else if (AnsiPos('Error', StatusLine) = 1) then begin + Result.FStatus := gcsERR; + Delete(StatusLine, 1, 5); + Status := Trim(StatusLine); + if (Status = '13') then + Result.FErrText := '—v‹‚³‚ꂽdat‚ªŒ©‚‚©‚è‚Ü‚¹‚ñ‚Å‚µ‚½' + else if (Status = '8008135') then + Result.FErrText := 'ƒŠƒNƒGƒXƒgURL‚ÌSERVER‚©BOARD‚ª³‚µ‚­‚È‚¢‚Å‚·' + else if (Status = '666') then + Result.FErrText := 'OPTIONS‚Ü‚½‚ÍQueryString‚ª³‚µ‚­‚È‚¢‚Å‚·' + else if (Status = '69') then + Result.FErrText := 'KAGI‚ª•s³i—LŒøŠúŒÀØ‚ê‚»‚Ì‘¼j' + else if (Status = '20') then + Result.FErrText := 'ƒAƒNƒZƒXŠÔŠu‚ª’Z‚·‚¬‚Ü‚·' + else if (Status = '42') then + Result.FErrText := '‚»‚ÌHTTPƒƒ\ƒbƒh‚Í‹–‰Â‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ' + else // ??? + Result.FErrText := 'Žæ“¾ƒGƒ‰[[' + Status + ']'; + end + else begin + Result.FStatus := gcsERR; + Result.FErrText := 'ƒXƒe[ƒ^ƒX‰ðÍŽ¸”s[' + StatusLine + ']'; + end; + Result.FSize := 0; +end; + +//‚Ps–Ú‚ðÁ‚µ‚āAƒRƒ“ƒeƒ“ƒcƒTƒCƒY‚ðÝ’è‚·‚é +procedure TDownloadThread.DeleteStatusLine(Item: TDownloadItem); var SList: TStringList; begin SList := TStringList.Create; try - SList.Text := Content; + SList.Text := Item.Content; + //1s–Ú‚ðíœ if SList.Count > 1 then SList.Delete(0); - Result := SList.Text; + Item.Content := SList.Text; + //‰üsƒR[ƒh‚ðCRLF -> LF‚ƍl‚¦‚āAs”•ª‚¾‚¯ƒ}ƒCƒiƒX + Item.ContentLength := Length(SList.Text) - SList.Count; finally SList.Free; end; @@ -890,10 +1190,12 @@ var i: Integer; index: Integer; NewItem: TThreadItem; -// SaveCount: Integer; NumCount: Integer; Body: TStringList; Rec: TSubjectRec; + {$IFDEF DEBUG} + st, rt : Cardinal; + {$ENDIF} function MakeThreadCallBack( inInstance : DWORD; // TBoardItem ‚̃Cƒ“ƒXƒ^ƒ“ƒX inURL : PChar; // ƒXƒŒƒbƒh‚Ì URL @@ -908,10 +1210,13 @@ var boardItem := TBoard( inInstance ); boardItem.IntData := boardItem.IntData + 1; - index := boardItem.GetIndexFromURL( string( inURL ) ); + if boardItem.IntData < (boardItem.Count shr 2) then + index := boardItem.GetIndexFromURL( string( inURL ) ) + else + index := boardItem.GetIndexFromURL( string( inURL ), True ); if index = -1 then begin //V‚µ‚¢ƒXƒŒƒbƒh - _ThreadItem := TThreadItem.Create( boardItem.BoardPlugIn, string( inURL ) ); + _ThreadItem := TThreadItem.Create( boardItem.BoardPlugIn, boardItem, string( inURL ) ); _ThreadItem.Title := string( inTitle ); _ThreadItem.AllResCount := inCount; @@ -920,23 +1225,29 @@ var _ThreadItem.RoundDate := ZERO_DATE; _ThreadItem.LastModified := ZERO_DATE; _ThreadItem.AgeSage := gasNew; - boardItem.ListData.Add( _ThreadItem ); + boardItem.Add(_ThreadItem); end else begin + //‡ˆÊ‚ªã‚ª‚Á‚Ä‚¢‚ê‚ÎAge‚É‚·‚é if boardItem.Items[index].No > boardItem.IntData then boardItem.Items[index].AgeSage := gasAge - else if boardItem.Items[index].AllResCount < inCount then + //‡ˆÊ‚ªã‚ª‚Á‚Ä‚È‚¢‚¯‚ǁAƒŒƒX‚ª‚‚¢‚Ä‚½‚çASage‚É + else if boardItem.Items[index].AllResCount <> inCount then boardItem.Items[index].AgeSage := gasSage + //‡ˆÊã‚ª‚Á‚Ä‚È‚¢‚µAƒŒƒX‚Ì‘Œ¸‚à–³‚¯‚ê‚΁ANone else boardItem.Items[index].AgeSage := gasNone; boardItem.Items[index].No := boardItem.IntData; boardItem.Items[index].AllResCount := inCount; - boardItem.ListData.Add( boardItem.Items[index] ); - boardItem.DeleteList( index ); end; + end; begin - Board.ListData := TList.Create; +{$IFDEF DEBUG} + st := GetTickCount; + Writeln('SAVELIST'); +{$ENDIF} + //Board.ListData := TList.Create; Body := TStringList.Create; try //ƒ_ƒEƒ“ƒ[ƒh“úŽžÝ’èiƒ[ƒJƒ‹“úŽžj @@ -944,32 +1255,61 @@ begin //ƒT[ƒoãƒtƒ@ƒCƒ‹‚̍XVŽžÝ’è Board.LastModified := LastModified; + + //dat—Ž‚¿ƒXƒŒ‚̃\[ƒg‡‚ðŒˆ’è‚·‚邽‚߂Ƀ\[ƒg‚·‚é + if GikoSys.Setting.DatOchiSortIndex >= 0 then begin + Sort.SetSortNoFlag(true); + Sort.SetSortOrder(GikoSys.Setting.DatOchiSortOrder); + Sort.SetSortIndex(GikoSys.Setting.DatOchiSortIndex); + //Sort.SortNonAcquiredCountFlag := GikoSys.Setting.NonAcquiredCount; + Board.CustomSort(ThreadItemSortProc); + end; + +{$IFDEF DEBUG} + rt := GetTickCount - st; + Writeln('END Sortd' + IntToStr(rt) + ' ms'); +{$ENDIF} + + for i := Board.Count - 1 downto 0 do + Board.Items[i].AgeSage := gasNull; + if Board.IsBoardPlugInAvailable then begin // V‚µ‚¢ƒŠƒXƒg‚ðì¬‚·‚é // V‚µ‚¢ƒŠƒXƒg‚Ɍ¢ƒŠƒXƒg‚̃ƒO‚ª‚ ‚é‚È‚ç‚»‚ê‚ðV‚µ‚¢ƒŠƒXƒg‚ɒljÁ // ŒÃ‚¢ƒƒO‚ª‚È‚¯‚ê‚΁AV‚½‚ɃXƒŒƒIƒuƒWƒFƒNƒg‚ðì¬ Board.IntData := 0; +{$IFDEF DEBUG} + rt := GetTickCount - st; + Writeln('Start Enum' + IntToStr(rt) + ' ms'); +{$ENDIF} + + //‚±‚ꂪ’x‚¢@—v‰ü‘P + Board.BeginUpdate; Board.BoardPlugIn.EnumThread( DWORD( Board ), @MakeThreadCallBack ); + Board.EndUpdate; + +{$IFDEF DEBUG} + rt := GetTickCount - st; + Writeln('End Enum' + IntToStr(rt) + ' ms'); +{$ENDIF} + + //ŒÃ‚¢ƒŠƒXƒg‚É‚µ‚©‚È‚¢‚â‚‚ç‚ðíœ + for i := Board.Count - 1 downto 0 do begin + if( Board.Items[i].AgeSage = gasNull )and not (Board.Items[i].IsLogFile) then + Board.Delete(i); + end; // V‚µ‚¢ƒŠƒXƒg‚É–³‚©‚Á‚½ƒAƒCƒeƒ€‚ðV‚µ‚¢ƒŠƒXƒg‚ɒljÁ for i := 0 to Board.Count - 1 do begin - if Board.Items[i].IsLogFile then begin + if(Board.Items[i].AgeSage = gasNull) and (Board.Items[i].IsLogFile) then begin Board.IntData := Board.IntData + 1; Board.Items[i].No := Board.IntData; Board.Items[i].AllResCount := Board.Items[i].Count; Board.Items[i].NewResCount := 0; - Board.Items[i].AgeSage := gasNone; - Board.ListData.Add( Board.Items[i] ); + Board.Items[i].AgeSage := gasArch; end; end; - // ŒÃ‚¢ƒŠƒXƒg‚ðÁ‚·iƒŠƒXƒg‚̂݁BƒXƒŒƒIƒuƒWƒFƒNƒgŽ©‘̂͏Á‚³‚È‚¢j - for i := Board.Count - 1 downto 0 do - Board.DeleteList( i ); - - // V‚µ‚¢ƒŠƒXƒg‚ðƒ{[ƒhƒIƒuƒWƒFƒNƒg‚ɒljÁ - for i := 0 to Board.ListData.Count - 1 do - Board.Add( TThreadItem(Board.ListData[i]) ); end else begin //V‚µ‚¢ƒŠƒXƒg‚ðì¬‚·‚é //V‚µ‚¢ƒŠƒXƒg‚Ɍ¢ƒŠƒXƒg‚̃ƒO‚ª‚ ‚é‚È‚ç‚»‚ê‚ðV‚µ‚¢ƒŠƒXƒg‚ɒljÁ @@ -977,17 +1317,17 @@ begin Body.Text := Content; NumCount := 0; for i := 0 to Body.Count - 1 do begin - //if i = 0 then Continue; //‚Ps–ڂ̓Xƒe[ƒ^ƒXs‚Ì‚½‚ߏˆ—‚È‚µ - Rec := GikoSys.DivideSubject(Body[i]); Rec.FFileName := Trim(Rec.FFileName); if (Rec.FTitle = '') and (Rec.FCount = 0) then Continue; Inc(NumCount); - index := Board.GetIndex(Rec.FFileName); + index := Board.GetIndexFromFileName(Rec.FFileName); if index = -1 then begin //V‚µ‚¢ƒXƒŒƒbƒh NewItem := TThreadItem.Create( - nil, GikoSys.Get2chBoard2ThreadURL( Board, ChangeFileExt( Rec.FFileName, '' ) ) ); + nil, + Board, + GikoSys.Get2chBoard2ThreadURL( Board, ChangeFileExt( Rec.FFileName, '' ) ) ); NewItem.Title := Rec.FTitle; NewItem.AllResCount := Rec.FCount; NewItem.ParentBoard := Board; @@ -995,7 +1335,7 @@ begin NewItem.RoundDate := ZERO_DATE; NewItem.LastModified := ZERO_DATE; NewItem.AgeSage := gasNew; - Board.ListData.Add(NewItem); + Board.Add(NewItem); end else begin if Board.Items[index].No > NumCount then Board.Items[index].AgeSage := gasAge @@ -1006,41 +1346,34 @@ begin Board.Items[index].No := NumCount; Board.Items[index].AllResCount := Rec.FCount; - Board.ListData.Add(Board.Items[index]); - Board.DeleteList(index); end; end; + //ŒÃ‚¢ƒŠƒXƒg‚̍폜 + for i := Board.Count - 1 downto 0 do begin + if( Board.Items[i].AgeSage = gasNull )and not (Board.Items[i].IsLogFile) then + Board.Delete(i); + end; - //V‚µ‚¢ƒŠƒXƒg‚É–³‚©‚Á‚½ƒAƒCƒeƒ€‚ðV‚µ‚¢ƒŠƒXƒg‚ɒljÁ + //V‚µ‚¢ƒŠƒXƒg‚É–³‚©‚Á‚½ƒAƒCƒeƒ€‚̍XV for i := 0 to Board.Count - 1 do begin - if Board.Items[i].IsLogFile then begin + if( Board.Items[i].AgeSage = gasNull )and (Board.Items[i].IsLogFile) then begin inc(NumCount); Board.Items[i].No := NumCount; Board.Items[i].AllResCount := Board.Items[i].Count; Board.Items[i].NewResCount := 0; - Board.Items[i].AgeSage := gasNone; - Board.ListData.Add(Board.Items[i]); + Board.Items[i].AgeSage := gasArch; end; end; - - //ŒÃ‚¢ƒŠƒXƒg‚ðÁ‚·iƒŠƒXƒg‚̂݁BƒXƒŒƒIƒuƒWƒFƒNƒgŽ©‘̂͏Á‚³‚È‚¢j - for i := Board.Count - 1 downto 0 do - Board.DeleteList(i); - - //V‚µ‚¢ƒŠƒXƒg‚ðƒ{[ƒhƒIƒuƒWƒFƒNƒg‚ɒljÁ - for i := 0 to Board.ListData.Count - 1 do - Board.Add(TThreadItem(Board.ListData[i])); - //ƒŠƒXƒg(subject.txt)‚ð•Û‘¶ - // GikoSys.ForceDirectoriesEx(GikoSys.GetLogDir + Board.BBSID); - // Body.SaveToFile(GikoSys.GetSubjectFileName(Board.BBSID)); GikoSys.ForceDirectoriesEx(ExtractFilePath(Board.GetSubjectFileName)); + Body.Text := MojuUtils.Sanitize(Body.Text); Body.SaveToFile(Board.GetSubjectFileName); end; finally Body.Free; - Board.ListData.Free; end; + + end; {procedure TDownloadItem.SaveListFile; @@ -1130,70 +1463,136 @@ end; } procedure TDownloadItem.SaveItemFile; var - Body: TStringList; + Body, oldBody: TStringList; Cnt: Integer; OldCnt: Integer; FileName: string; ini: TMemIniFile; Res: TResRec; NewRes: Integer; + finish : Boolean; + loopCnt : Integer; + LastIdx : Integer; begin FileName := ThreadItem.GetThreadFileName; - if not ThreadItem.IsBoardPlugInAvailable then begin + //if not ThreadItem.IsBoardPlugInAvailable then begin + if not ThreadItem.ParentBoard.IsBoardPlugInAvailable then begin if Trim(Content) = '' then Exit; + GikoSys.ForceDirectoriesEx(ExtractFilePath(FileName)); - // Cnt := 0; + // Cnt := 0; Body := TStringList.Create; + NewRes := 0; + OldCnt := 0; try - // if FileExists(FileName) and (ResponseCode = 206) then begin + // if FileExists(FileName) and (ResponseCode = 206) then begin if FileExists(FileName) and (State = gdsDiffComplete) then begin - // Body.Text := Content; - // if Body.Count > 0 then - // Body.Delete(0); - // Content := Body.Text; - Body.LoadFromFile(FileName); - OldCnt := Body.Count; - Body.Text := Body.Text + Content; - Body.SaveToFile(FileName); - NewRes := Body.Count - OldCnt; - Cnt := Body.Count; + loopCnt := 10; + repeat + finish := true; + try + Body.LoadFromFile(FileName); + OldCnt := Body.Count; + Body.Text := Body.Text + Content; + Body.SaveToFile(FileName); + NewRes := Body.Count - OldCnt; + except + on E:EFOpenError do begin + sleep(10); + Dec(loopCnt); + if loopCnt > 0 then + finish := false; + end; + end; + until finish; + //Cnt := Body.Count; end else begin - Body.Text := Content; + if IsAbone then begin + // ‚ ‚ځ[‚ñ‚ðŒŸo‚µ‚½‚Ì‚Å‚±‚±‚Ü‚Å“Ç‚ñ‚¾‚ƐV’…ƒŒƒX”Ԃ̂‚¯‚È‚¨‚µ + oldBody := TStringList.Create; + try + loopCnt := 10; + repeat + finish := true; + try + oldBody.LoadFromFile(FileName); + except + on E:EFOpenError do begin + sleep(10); + Dec(loopCnt); + if loopCnt > 0 then + finish := false + else + finish := true; + end; + end; + until finish; + + Body.Text := Content; + if (ThreadItem.Kokomade > 0) and (ThreadItem.Kokomade <= oldBody.Count) then begin + ThreadItem.Kokomade := Body.IndexOf(oldBody.Strings[ ThreadItem.Kokomade - 1 ]); + if ThreadItem.Kokomade <> -1 then ThreadItem.Kokomade := ThreadItem.Kokomade + 1; + end; + + LastIdx := oldBody.Count; + repeat + Dec(LastIdx); + OldCnt := Body.IndexOf(oldBody.Strings[ LastIdx ]) + 1; + until ( OldCnt <> 0 ) or (LastIdx = 0); + + if OldCnt >= Body.Count then OldCnt := Body.Count - 1; + NewRes := Body.Count - OldCnt; + + // ‚±‚±‚Ü‚Å“Ç‚ñ‚¾‚ªV’…ƒŒƒX”Ô‚ð’´‚³‚È‚¢‚悤‚É(ˆÙíI—¹Žž‚̃ŠƒJƒoƒŠ) + if ThreadItem.Kokomade > OldCnt then begin + if OldCnt > 0 then + ThreadItem.Kokomade := OldCnt + else + ThreadItem.Kokomade := 1; + end; + + finally + oldBody.Free; + end; + + end else begin + Body.Text := Content; + //ThreadItem.Count := 0; + OldCnt := 0; + NewRes := Body.Count; + //Cnt := Body.Count; + end; // if Body.Count > 0 then // Body.Delete(0); Body.SaveToFile(FileName); if ThreadItem.Title = '' then begin - Res := GikoSys.DivideStrLine(Body[0]); + THTMLCreate.DivideStrLine(Body[0], @Res); ThreadItem.Title := Res.FTitle; end; ThreadItem.Size := 0; - //ThreadItem.Count := 0; - ThreadItem.AllResCount := 0; - ThreadItem.NewResCount := 0; - OldCnt := 0; - NewRes := Body.Count; - Cnt := Body.Count; end; Cnt := Body.Count; finally Body.Free; end; + ThreadItem.Size := ThreadItem.Size + ContentLength; ThreadItem.LastModified := LastModified; ThreadItem.Count := Cnt; - ThreadItem.AllResCount := Cnt; + //ThreadItem.AllResCount := Cnt; ThreadItem.NewResCount := NewRes; ThreadItem.NewReceive := OldCnt + 1; end; - + ThreadItem.AllResCount := ThreadItem.Count; ThreadItem.IsLogFile := True; ThreadItem.RoundDate := Now; - ThreadItem.UnRead := True; - ThreadItem.ParentBoard.UnRead := ThreadItem.ParentBoard.UnRead + 1; + if not ThreadItem.UnRead then begin + ThreadItem.UnRead := True; + end; // if ThreadItem.RoundNo = 6 then // ThreadItem.RoundNo := 0; @@ -1210,7 +1609,7 @@ begin ini.WriteInteger('Setting', 'NewResCount', ThreadItem.NewResCount); ini.WriteInteger('Setting', 'NewReceive', ThreadItem.NewReceive); // ini.WriteInteger('Setting', 'RoundNo', ThreadItem.RoundNo); - ini.WriteBool('Setting', 'Round', ThreadItem.Round); +// ini.WriteBool('Setting', 'Round', ThreadItem.Round); ini.WriteBool('Setting', 'UnRead', ThreadItem.UnRead); ini.UpdateFile; finally @@ -1218,4 +1617,66 @@ begin end; end; +procedure TDownloadThread.GetLastModified; +var + ResultDate: TDateTime; + ResList: TStringList; + LastRes: String; + KwPos: Integer; + ResRow: Integer; + DTIdx: Integer; + Ok: Boolean; + AWKStr: TAWKStr; + RStart: Integer; + RLength: Integer; +begin + AWKStr := TAWKStr.Create(nil); + Ok := False; + ResultDate := Item.LastModified; + ResList := TStringList.Create; + try + ResList.Text := Item.Content; + for ResRow := ResList.Count - 1 downto 0 do begin + if (ResRow > 999) then + continue; + LastRes := ResList.Strings[ResRow]; + KwPos := Pos('<>', LastRes); + if (KwPos < 1) then + continue; + Delete(LastRes, 1, KwPos + 1); + KwPos := Pos('<>', LastRes); + if (KwPos < 1) then + continue; + Delete(LastRes, 1, KwPos + 1); + // '2013/04/22(ŒŽ) 02:32:36' + SetLength(LastRes, 23); + Delete(LastRes, 11, 4); // —j“úíœ + + // “ú•tŠm”F +// AWKStr.RegExp := '(\d{4})/(0[1-9]|1[0-2])/(0[1-9]|[12][0-9]|3[01])'; + AWKStr.RegExp := '(19|20)([0-9][0-9])/(0[1-9]|1[0-2])/(0[1-9]|[12][0-9]|3[01])'; + if (AWKStr.Match(AWKStr.ProcessEscSeq(LastRes), RStart, RLength) = 1) then begin + + AWKStr.RegExp := '([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])'; + if (AWKStr.Match(AWKStr.ProcessEscSeq(LastRes), RStart, RLength) < 1) then begin + SetLength(LastRes, 10); + LastRes := LastRes + ' 00:00:00'; + end; + + try + ResultDate := StrToDateTime(LastRes); + Ok := True; + except + end; + end; + if (Ok = True) then + break; + end; + finally + ResList.Free; + end; + Item.LastModified :=ResultDate; + FreeAndNil(AWKStr); +end; + end.