OSDN Git Service

まちBBSでエラー文字列を受信した場合に削除レスと同じ扱いにしてしまう不具合を修正
[gikonavigoeson/gikonavi.git] / ItemDownload.pas
index 11120c5..36b5497 100644 (file)
@@ -5,8 +5,8 @@ interface
 uses
        Windows, SysUtils, Classes, ComCtrls, Controls, Forms, IdHTTP,
        {HTTPApp,} YofUtils, IdGlobal, IdException, IdComponent, IniFiles, {DateUtils,}
-       GikoSystem, BoardGroup, MonaUtils, ExternalBoardManager, ExternalBoardPlugInMain,
-       Sort;
+       GikoSystem, BoardGroup, ExternalBoardManager, ExternalBoardPlugInMain,
+       Sort, SyncObjs, bmRegExp;
 
 type
        TDownloadItem = class;
@@ -27,7 +27,17 @@ type
                FErrText: string;
        end;
 
-
+       TWorkData = record
+           //FWorkCS: TCriticalSection;
+               //IdHttp\82ÌOnWork\81AOnWorkBegin,OnWorkEnd\82Í\95Ê\82Ì\83X\83\8c\83b\83h\82©\82ç
+        //\8cÄ\82Î\82ê\82é\88×\81ASynchronize\82Å\93¯\8aú\82·\82é\95K\97v\82ª\82 \82é\81B
+               //\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
+               FWorkCS: TCriticalSection;
+               FSender: TObject;
+               FAWorkMode: TWorkMode;
+               FAWorkCount: Integer;
+               FAWorkCountMax: Integer
+       end;
        TDownloadThread = class(TThread)
        private
                FIndy: TIdHttp;
@@ -43,6 +53,7 @@ type
                FOnDownloadEnd: TDownloadEndEvent;
                FOnDownloadMsg: TDownloadMsgEvent;
                FDownloadTitle: string;
+        FWorkData: TWorkData;
 
                procedure FireDownloadEnd;
                procedure FireDownloadMsg;
@@ -51,12 +62,17 @@ 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;
                procedure DeleteStatusLine(Item: TDownloadItem);
                procedure InitHttpClient(client: TIdHttp);
                procedure ClearHttpClient(client: TIdHttp);
-       protected
+               procedure FireWork;
+               procedure FireWorkBegin;
+               procedure FireWorkEnd;
+        procedure GetLastModified;
+       protected
                procedure Execute; override;
        public
                property Item: TDownloadItem read FItem write FItem;
@@ -106,11 +122,13 @@ type
 implementation
 
 uses
-       Y_TextConverter, MojuUtils, HTMLCreate;
+       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;
@@ -122,6 +140,7 @@ destructor TDownloadThread.Destroy;
 begin
        ClearHttpClient(FIndy);
        FIndy.Free;
+    FWorkData.FWorkCS.Free;
        inherited;
 end;
 
@@ -153,6 +172,7 @@ begin
        client.RecvBufferSize := Gikosys.Setting.RecvBufferSize;
        client.ProxyParams.BasicAuthentication := False;
        client.ReadTimeout := GikoSys.Setting.ReadTimeOut;
+    client.ConnectTimeout := GikoSys.Setting.ReadTimeOut;
        {$IFDEF DEBUG}
        Writeln('------------------------------------------------------------');
        {$ENDIF}
@@ -217,6 +237,8 @@ var
        lastContent             : string;
        logFile                         : TFileStream;
        adjustMargin    : Integer;
+    Host: String;
+    Sep: Integer;
 const
        ADJUST_MARGIN   = 16;
 begin
@@ -375,9 +397,9 @@ begin
 
                                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
@@ -488,6 +510,148 @@ begin
                                end;
 }
 
+                               if (Item.DownType = gdtThread) and (Item.ResponseCode = 302) then begin
+                                       {$IFDEF DEBUG}
+                                       Writeln('offlaw2.so\82Å\8eæ\93¾');
+                                       {$ENDIF}
+                                       ATitle := Item.ThreadItem.Title;
+                                       if ATitle = '' then
+                                               ATitle := '\81i\96¼\8fÌ\95s\96¾\81j';
+                                       FMsg := '\81\9adat.gz\82ª\91\8dÝ\82µ\82È\82¢\82½\82ßofflaw2.so\82ð\97\98\97p\82µ\82Ü\82· - [' + 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 := '\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';
+                                                       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 := '\83X\83\8c\82Í\91\8dÝ\82µ\82È\82¢\82æ\82¤\82Å\82·\81B' + 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\82Å\8eæ\93¾');
+                        {$ENDIF}
+                        ATitle := Item.ThreadItem.Title;
+                        if ATitle = '' then
+                            ATitle := '\81i\96¼\8fÌ\95s\96¾\81j';
+                        FMsg := '\81\9aofflow2.so\82É\91\8dÝ\82µ\82È\82¢\82½\82ßRokka\82ð\97\98\97p\82µ\82Ü\82· - [' + 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\8aO\95\94\94Â
+                               //********************
+//                             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('\8aO\95\94\94Â\89ß\8b\8e\83\8d\83O\8eæ\93¾');
+                                               {$ENDIF}
+                        ATitle := Item.ThreadItem.Title;
+                        if ATitle = '' then
+                            ATitle := '\81i\96¼\8fÌ\95s\96¾\81j';
+                        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 + ']';
+                        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\82Å\8eæ\93¾
                                //********************
@@ -597,7 +761,7 @@ begin
                                                        Synchronize(FireDownloadMsg);
                                        end;
                                end;
-
+*)
                                case Item.ResponseCode of
                                        200: Item.State := gdsComplete;
                                        206: Item.State := gdsDiffComplete;
@@ -734,13 +898,12 @@ begin
                        {$ENDIF}
                        FIndy.Get(URL, ResStream);
             Item.Content := GikoSys.GzipDecompress(ResStream, FIndy.Response.ContentEncoding);
-                       Item.LastModified := FIndy.Response.LastModified;
-                       //\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é
-//                     Item.ContentLength := FIndy.Response.ContentLength + AdjustLen;
                        Item.ContentLength := Length(Item.Content) + AdjustLen;
-                       //\96³\82¢\82Æ\8ev\82¤\82¯\82Ç\81B\81B\81B
-//                     if (FIndy.ResponseCode in [200, 206]) and (Item.Content = '') then
-//                             Result := False
+            // \92u\8a·\82·\82é
+            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
@@ -815,22 +978,72 @@ begin
        end;
 end;
 
-procedure TDownloadThread.WorkBegin(Sender: TObject; AWorkMode: TWorkMode; const AWorkCountMax: Integer);
+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;
+
+//\82±\82±\82©\82ç\90V\8bK\83\81\83\\83b\83h
+procedure TDownloadThread.FireWorkBegin;
 begin
-       if Assigned(OnWorkBegin) then
-               OnWorkBegin(Sender, AWorkMode, AWorkCountMax, FNumber, FDownloadTitle);
+       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;
@@ -889,6 +1102,70 @@ begin
        end;
 end;
 
+function TDownloadThread.ParseRokkaStatus(Content: string): TCgiStatus;
+var
+       StatusLine: string;
+       Idx: Integer;
+       Status: string;
+begin
+//     \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·
+//     \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·
+//     \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
+//     \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
+//     \81@\81@\81@\81@\81@\81@\81@\81@\81@\81@\81@Archive \81@\81@\89ß\8b\8e\83\8d\83O
+//     \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·
+//     \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
+//     \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½
+//     \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·
+//     \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·
+//     \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
+//     \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·
+//     \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ñ
+       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                   // \91½\95ª\82±\82ê\82Í\97\88\82È\82¢
+               Result.FErrText := '\8eæ\93¾\90¬\8c÷\81i\83\89\83C\83u\83X\83\8c\83b\83h\81j'
+        else if (Status = 'Pool') then
+               Result.FErrText := '\8eæ\93¾\90¬\8c÷\81idat\97\8e\82¿\83X\83\8c\83b\83h\81j'
+        else if (Status = 'Archive') then
+               Result.FErrText := '\8eæ\93¾\90¬\8c÷\81i\89ß\8b\8e\83\8d\83O\81j'
+        else    // ???
+               Result.FErrText := '\8eæ\93¾\90¬\8c÷';
+    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 := '\97v\8b\81\82³\82ê\82½dat\82ª\8c©\82Â\82©\82è\82Ü\82¹\82ñ\82Å\82µ\82½'
+        else if (Status = '8008135') then
+               Result.FErrText := '\83\8a\83N\83G\83X\83gURL\82ÌSERVER\82©BOARD\82ª\90³\82µ\82­\82È\82¢\82Å\82·'
+        else if (Status = '666') then
+               Result.FErrText := 'OPTIONS\82Ü\82½\82ÍQueryString\82ª\90³\82µ\82­\82È\82¢\82Å\82·'
+        else if (Status = '69') then
+               Result.FErrText := 'KAGI\82ª\95s\90³\81i\97L\8cø\8aú\8cÀ\90Ø\82ê\82»\82Ì\91¼\81j'
+        else if (Status = '20') then
+               Result.FErrText := '\83A\83N\83Z\83X\8aÔ\8au\82ª\92Z\82·\82¬\82Ü\82·'
+        else if (Status = '42') then
+               Result.FErrText := '\82»\82ÌHTTP\83\81\83\\83b\83h\82Í\8b\96\89Â\82³\82ê\82Ä\82¢\82Ü\82¹\82ñ'
+        else    // ???
+               Result.FErrText := '\8eæ\93¾\83G\83\89\81[[' + Status + ']';
+    end
+    else begin
+               Result.FStatus := gcsERR;
+               Result.FErrText := '\83X\83e\81[\83^\83X\89ð\90Í\8e¸\94s[' + StatusLine + ']';
+    end;
+       Result.FSize := 0;
+end;
+
 //\82P\8ds\96Ú\82ð\8fÁ\82µ\82Ä\81A\83R\83\93\83e\83\93\83c\83T\83C\83Y\82ð\90Ý\92è\82·\82é
 procedure TDownloadThread.DeleteStatusLine(Item: TDownloadItem);
 var
@@ -900,6 +1177,7 @@ begin
                //1\8ds\96Ú\82ð\8dí\8f\9c
                if SList.Count > 1 then
                        SList.Delete(0);
+        Item.Content := SList.Text;
                //\89ü\8ds\83R\81[\83h\82ðCRLF -> LF\82Æ\8dl\82¦\82Ä\81A\8ds\90\94\95ª\82¾\82¯\83}\83C\83i\83X
         Item.ContentLength := Length(SList.Text) - SList.Count;
        finally
@@ -980,9 +1258,9 @@ begin
 
                //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é
                if GikoSys.Setting.DatOchiSortIndex >= 0 then begin
-                       Sort.SortNoFlag := true;
-                       Sort.SortOrder := GikoSys.Setting.DatOchiSortOrder;
-                       Sort.SortIndex := GikoSys.Setting.DatOchiSortIndex;
+                       Sort.SetSortNoFlag(true);
+                       Sort.SetSortOrder(GikoSys.Setting.DatOchiSortOrder);
+                       Sort.SetSortIndex(GikoSys.Setting.DatOchiSortIndex);
                        //Sort.SortNonAcquiredCountFlag := GikoSys.Setting.NonAcquiredCount;
                        Board.CustomSort(ThreadItemSortProc);
                end;
@@ -1028,7 +1306,7 @@ begin
                                        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.Items[i].AgeSage                  := gasArch;
                                end;
                        end;
 
@@ -1083,11 +1361,12 @@ begin
                                        Board.Items[i].No := NumCount;
                                        Board.Items[i].AllResCount := Board.Items[i].Count;
                                        Board.Items[i].NewResCount := 0;
-                                       Board.Items[i].AgeSage := gasNone;
+                                       Board.Items[i].AgeSage := gasArch;
                                end;
                        end;
                        //\83\8a\83X\83g(subject.txt)\82ð\95Û\91
                        GikoSys.ForceDirectoriesEx(ExtractFilePath(Board.GetSubjectFileName));
+            Body.Text := MojuUtils.Sanitize(Body.Text);
                        Body.SaveToFile(Board.GetSubjectFileName);
                end;
        finally
@@ -1338,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(\8c\8e) 02:32:36'
+                       SetLength(LastRes, 23);
+                       Delete(LastRes, 11, 4);         // \97j\93ú\8dí\8f\9c
+
+            // \93ú\95t\8am\94F
+//            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.