OSDN Git Service

Be用plugin(試作品)
authorh677 <h677>
Thu, 28 Jul 2005 14:15:47 +0000 (14:15 +0000)
committerh677 <h677>
Thu, 28 Jul 2005 14:15:47 +0000 (14:15 +0000)
res/ExternalBoardPlugIn/BePlugIn.dpr [new file with mode: 0644]

diff --git a/res/ExternalBoardPlugIn/BePlugIn.dpr b/res/ExternalBoardPlugIn/BePlugIn.dpr
new file mode 100644 (file)
index 0000000..7efa3c8
--- /dev/null
@@ -0,0 +1,1578 @@
+library BePlugIn;
+
+{
+       BePlugIn
+       2\82¿\82á\82ñ\82Ë\82éBE\8f\88\97\9d\83\86\83j\83b\83g
+
+}
+
+uses
+  Windows,
+  SysUtils,
+  Classes,
+  Math,
+  DateUtils,
+  Dialogs,
+  IdURI,
+  PlugInMain in 'PlugInMain.pas',
+  ThreadItem in 'ThreadItem.pas',
+  BoardItem in 'BoardItem.pas',
+       FilePath in 'FilePath.pas',
+  Y_TextConverter in 'Y_TextConverter.pas',
+  MojuUtils in '..\..\MojuUtils.pas';
+
+{$R *.res}
+
+type
+       // =========================================================================
+       // TBeThreadItem
+       // =========================================================================
+       TBeThreadItem = class(TThreadItem)
+       private
+               FIsTemporary    : Boolean;
+               FDat                                    : TStringList;
+
+       public
+               constructor     Create( inInstance : DWORD );
+               destructor      Destroy; override;
+
+       private
+               function        Download : TDownloadState;
+               function        StorageDownload(AURL : string) : TDownloadState;
+               function        Write( inName : string; inMail : string; inMessage : string ) : TDownloadState;
+               function        GetRes( inNo : Integer ) : string;
+               function        GetDat( inNo : Integer ) : string;
+               function        GetHeader( inOptionalHeader : string ) : string;
+               function        GetFooter( inOptionalFooter : string ) : string;
+               function        GetBoardURL : string;
+               procedure       ArrangeDownloadData( start: Integer;var Data: TStringList);
+               procedure       LoadDat;
+               procedure       FreeDat;
+               function        BrowsableURL : string;
+               function        ReadURL : string;
+               function        WriteURL : string;
+       end;
+
+       // =========================================================================
+       // TBeBoardItem
+       // =========================================================================
+       TBeBoardItem = class(TBoardItem)
+       private
+               FIsTemporary    : Boolean;
+               FDat                                    : TStringList;
+
+       public
+               constructor     Create( inInstance : DWORD );
+               destructor      Destroy; override;
+
+       private
+               function        Download : TDownloadState;
+               function        CreateThread( inSubject : string; inName : string; inMail : string; inMessage : string ) : TDownloadState;
+               function        ToThreadURL( inFileName : string ) : string;
+               procedure       EnumThread( inCallBack : TBoardItemEnumThreadCallBack );
+
+               function        SubjectURL : string;
+       end;
+
+const
+       LOG_DIR                                         = 'Be\';
+       SUBJECT_NAME                    = 'subject.txt';
+
+       PLUGIN_NAME                             = 'Be';
+       MAJOR_VERSION                   = 1;
+       MINOR_VERSION                   = 1;
+       RELEASE_VERSION         = 'alpha';
+       REVISION_VERSION        = 1;
+
+//var
+//     SyncronizeMenu          : HMENU;
+
+// =========================================================================
+// \8eG\97p\8aÖ\90\94
+// =========================================================================
+
+// *************************************************************************
+// \83e\83\93\83|\83\89\83\8a\82È\83p\83X\82Ì\8eæ\93¾
+// *************************************************************************
+function TemporaryFile : string;
+var
+       tempPath : array [0..MAX_PATH] of       char;
+begin
+
+       GetTempPath( SizeOf(tempPath), tempPath );
+       repeat
+               Result := tempPath + IntToStr( Random( $7fffffff ) );
+       until not FileExists( Result );
+
+end;
+
+// *************************************************************************
+// Be\83\8d\83O\83t\83H\83\8b\83_\8eæ\93¾
+// *************************************************************************
+function MyLogFolder : string;
+var
+       folder : PChar;
+begin
+
+       folder := LogFolder;
+       if Length( folder ) = 0 then
+               Result := ''
+       else
+               Result := folder + LOG_DIR;
+    DisposeResultString(folder);
+
+end;
+
+(*************************************************************************
+ *\83f\83B\83\8c\83N\83g\83\8a\82ª\91\8dÝ\82·\82é\82©\83`\83F\83b\83N
+ *************************************************************************)
+function DirectoryExistsEx(const Name: string): Boolean;
+var
+       Code: Integer;
+begin
+       Code := GetFileAttributes(PChar(Name));
+       Result := (Code <> -1) and (FILE_ATTRIBUTE_DIRECTORY and Code <> 0);
+end;
+
+(*************************************************************************
+ *\83f\83B\83\8c\83N\83g\83\8a\8dì\90¬\81i\95¡\90\94\8aK\91w\91Î\89\9e\81j
+ *************************************************************************)
+function ForceDirectoriesEx(Dir: string): Boolean;
+begin
+       Result := True;
+       if Length(Dir) = 0 then
+               raise Exception.Create('\83t\83H\83\8b\83_\82ª\8dì\90¬\8fo\97\88\82Ü\82¹\82ñ');
+       Dir := ExcludeTrailingPathDelimiter(Dir);
+       if (Length(Dir) < 3) or DirectoryExistsEx(Dir)
+               or (ExtractFilePath(Dir) = Dir) then Exit; // avoid 'xyz:\' problem.
+       Result := ForceDirectoriesEx(ExtractFilePath(Dir)) and CreateDir(Dir);
+end;
+
+// \82Æ\82è\82 \82¦\82¸\82Ì\91ã\97p\95i\82È\82Ì\82Å chrWhite \82ð\8dl\97\82µ\82Ä\82¢\82È\82¢\82±\82Æ\82É\92\8d\88Ó\81I\81I\81I
+procedure ExtractHttpFields(
+       const chrSep : TSysCharSet;
+       const chrWhite : TSysCharSet;
+       const strValue : string;
+       var strResult : TStringList;
+       unknownFlag : boolean = false
+);
+var
+       last, p, strLen : Integer;
+begin
+
+       strLen := Length( strValue );
+       p := 1;
+       last := 1;
+
+       while p <= strLen do
+       begin
+
+               if strValue[ p ] in chrSep then
+               begin
+                       strResult.Add( Copy( strValue, last, p - last ) );
+                       last := p + 1;
+               end;
+
+               p := p + 1;
+
+       end;
+
+       if last <> p then
+               strResult.Add( Copy( strValue, last, strLen - last + 1 ) );
+
+end;
+
+\rfunction HttpEncode(
+\r      const strValue : string
+) : string;
+var
+       i : Integer;
+       strLen : Integer;
+       strResult : string;
+       b : Integer;
+const
+       kHexCode : array [0..15] of char = (
+                               '0', '1', '2', '3', '4', '5', '6', '7',
+                               '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' );
+begin
+
+       strLen := Length( strValue );
+       i := 1;
+
+       while i <= strLen do
+       begin
+
+               case strValue[ i ] of
+               '0' .. '9', 'a' .. 'z', 'A' .. 'Z', '*', '-', '.', '@', '_':
+                       begin
+                               strResult := strResult + strValue[ i ];
+                       end;
+               else
+                       begin
+                               b := Integer( strValue[ i ] );
+                               strResult := strResult + '%'
+                                                               + kHexCode[ b div $10 ]
+                                                               + kHexCode[ b mod $10 ];
+                       end;
+               end;
+
+               i := i + 1;
+
+       end;
+
+       Result := strResult;
+
+end;
+
+
+
+// =========================================================================
+// PlugIn
+// =========================================================================
+
+// *************************************************************************
+// \83v\83\89\83O\83C\83\93\82ª(\90³\82µ\82­)\83\8d\81[\83h\82³\82ê\82½
+// *************************************************************************
+procedure OnLoad(
+       inInstance : DWORD                              // \83v\83\89\83O\83C\83\93\82Ì\83C\83\93\83X\83^\83\93\83X
+); stdcall;
+begin
+end;
+
+// *************************************************************************
+// \83v\83\89\83O\83C\83\93\82Ì\83o\81[\83W\83\87\83\93\82ð\97v\8b\81\82³\82ê\82½
+// *************************************************************************
+procedure OnVersionInfo(
+       var outAgent            : PChar;        // \83o\81[\83W\83\87\83\93\82ð\88ê\90Ø\8aÜ\82Ü\82È\82¢\8f\83\90\88\82È\96¼\8fÌ
+       var outMajor            : DWORD;        // \83\81\83W\83\83\81[\83o\81[\83W\83\87\83\93
+       var outMinor            : DWORD;        // \83}\83C\83i\81[\83o\81[\83W\83\87\83\93
+       var outRelease  : PChar;        // \83\8a\83\8a\81[\83X\92i\8aK\96¼
+       var outRevision : DWORD         // \83\8a\83r\83W\83\87\83\93\83i\83\93\83o\81[
+); stdcall;
+begin
+
+       try
+               outAgent                := CreateResultString( PChar( PLUGIN_NAME ) );
+               outMajor                := MAJOR_VERSION;
+               outMinor                := MINOR_VERSION;
+               outRelease      := CreateResultString( PChar( RELEASE_VERSION ) );
+               outRevision     := REVISION_VERSION;
+       except
+               outAgent                := nil;
+               outMajor                := 0;
+               outMinor                := 0;
+               outRelease      := nil;
+               outRevision     := 0;
+       end;
+
+end;
+
+// *************************************************************************
+// \8ew\92è\82µ\82½ URL \82ð\82±\82Ì\83v\83\89\83O\83C\83\93\82Å\8eó\82¯\95t\82¯\82é\82©\82Ç\82¤\82©
+// *************************************************************************
+function OnAcceptURL(
+       inURL                   : PChar                         // \94»\92f\82ð\8bÂ\82¢\82Å\82¢\82é URL
+): TAcceptType; stdcall;       // URL \82Ì\8eí\97Þ
+var
+       uri                             : TIdURI;
+       uriList         : TStringList;
+       foundPos        : Integer;
+//     i                       : Integer;
+const
+       BBS_HOST                = 'be.2ch.net';
+       THREAD_MARK     = '/test/read.cgi';
+begin
+
+       try
+               // \83z\83X\83g\96¼\82ª be.2ch.net \82Å\8fI\82í\82é\8fê\8d\87\82Í\8eó\82¯\95t\82¯\82é\82æ\82¤\82É\82µ\82Ä\82¢\82é
+               uri                     := TIdURI.Create( inURL );
+               uriList := TStringList.Create;
+               try
+                       ExtractHttpFields( ['/'], [], uri.Path, uriList );
+                       if (BBS_HOST = uri.Host ) then begin
+                               foundPos := AnsiPos( THREAD_MARK, inURL );
+
+                               if foundPos > 0 then
+                                       Result := atThread
+                               //else if (uriList.Count > 2) and (AnsiPos('.html', uri.Document) > 0) then
+                               //      Result := atThread
+                               else if uriList.Count > 2 then  // \8dÅ\8cã\82ª '/' \82Å\95Â\82ß\82ç\82ê\82Ä\82é\82È\82ç 4
+                                       Result := atBoard
+                               else
+                                       Result := atBBS;
+
+                       end else begin
+                               Result := atNoAccept;
+                       end;
+
+               finally
+                       uri.Free;
+                       uriList.Free;
+               end;
+       except
+               Result := atNoAccept;
+       end;
+
+end;
+
+// =========================================================================
+// TBeThreadItem
+// =========================================================================
+
+// *************************************************************************
+// \83R\83\93\83X\83g\83\89\83N\83^
+// *************************************************************************
+constructor TBeThreadItem.Create(
+       inInstance      : DWORD
+);
+var
+       uri                                     : TIdURI;
+       uriList                 : TStringList;
+begin
+
+       inherited;
+
+       OnDownload              := Download;
+       OnWrite                         := Write;
+       OnGetRes                        := GetRes;
+       OnGetDat                        := GetDat;
+       OnGetHeader             := GetHeader;
+       OnGetFooter             := GetFooter;
+       OnGetBoardURL   := GetBoardURL;
+
+       FilePath                        := '';
+       FIsTemporary    := False;
+       FDat                                    := nil;
+       URL                                             := BrowsableURL;
+
+       uri                     := TIdURI.Create( ReadURL );
+       uriList := TStringList.Create;
+       try
+               ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
+               if uriList[ 5 ] = 'l50' then begin
+                       FileName        := uriList[ 4 ] + '.dat';
+                       FilePath        := MyLogFolder + uriList[ 2 ] + '\' + uriList[ 3 ] + '\' + uriList[ 4 ] + '.dat';
+                       IsLogFile       := FileExists( FilePath );
+               end else begin
+                       FileName        := uriList[ 5 ] + '.dat';
+                       FilePath        := MyLogFolder + uriList[ 3 ] + '\' + uriList[ 4 ] + '\' + uriList[ 5 ] + '.dat';
+                       IsLogFile       := FileExists( FilePath );
+               end;
+       finally
+               uri.Free;
+               uriList.Free;
+       end;
+
+end;
+
+// *************************************************************************
+// \83f\83X\83g\83\89\83N\83^
+// *************************************************************************
+destructor TBeThreadItem.Destroy;
+begin
+
+       FreeDat;
+
+       // \88ê\8e\9e\83t\83@\83C\83\8b\82Ì\8fê\8d\87\82Í\8dí\8f\9c\82·\82é
+       if FIsTemporary then
+               DeleteFile( FilePath );
+
+       inherited;
+
+end;
+
+// *************************************************************************
+// \8ew\92è\82µ\82½ URL \82Ì\83X\83\8c\83b\83h\82Ì\83_\83E\83\93\83\8d\81[\83h\82ð\8ew\8e¦\82³\82ê\82½
+// *************************************************************************
+function TBeThreadItem.Download : TDownloadState;
+var
+       modified                        : Double;
+       tmp                                             : PChar;
+       downResult              : TStringList;
+       responseCode    : Longint;
+       logStream                       : TFileStream;
+       uri                                             : TIdURI;
+       uriList                         : TStringList;
+       datURL, tmpURL                          : string;
+       tmpText: string;
+begin
+
+       Result := dsError;
+
+       uri := TIdURI.Create( ReadURL );
+       uriList := TStringList.Create;
+       try
+               ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
+               FileName := uriList[ 5 ] + '.dat';
+               // http://jbbs.livedoor.com/bbs/rawmode.cgi/game/1578/1067968274/l100
+               // protocol://host/1/2/3/4/5/uriList.Count - 1
+               if MyLogFolder = '' then begin
+                       // \82Ç\82±\82É\95Û\91\82µ\82Ä\82¢\82¢\82Ì\82©\95ª\82©\82ç\82È\82¢\82Ì\82Å\88ê\8e\9e\83t\83@\83C\83\8b\82É\95Û\91
+                       FilePath                        := TemporaryFile;
+                       FIsTemporary    := True;
+               end else begin
+                       FilePath                        := MyLogFolder + uriList[ 3 ] + '\' + uriList[ 4 ] + '\' + uriList[ 5 ] + '.dat';
+                       FIsTemporary    := False;
+               end;
+       finally
+               uri.Free;
+               uriList.Free;
+       end;
+
+       // \95Û\91\97p\82Ì\83f\83B\83\8c\83N\83g\83\8a\82ð\8c@\82é
+       ForceDirectoriesEx( Copy( FilePath, 1, LastDelimiter( '\', FilePath ) ) );
+
+       // \93Æ\8e©\82É\83_\83E\83\93\83\8d\81[\83h\82â\83t\83B\83\8b\83^\83\8a\83\93\83O\82ð\8ds\82í\82È\82¢\8fê\8d\87\82Í
+       // InternalDownload \82É\94C\82¹\82é\82±\82Æ\82ª\8fo\97\88\82é
+       modified        := LastModified;
+       datURL          := ReadURL + IntToStr( Count + 1 ) + '-'; // \90V\92\85\82Ì\82Ý
+       responseCode := InternalDownload( PChar( datURL ), modified, tmp, 0 );
+
+       try
+               if (responseCode = 200) or (responseCode = 206) then begin
+                       downResult := TStringList.Create;
+                       try
+                                                               tmpText := CustomStringReplace( string( tmp ), '¡÷¡®', ',' );
+                               downResult.Text := EUCtoSJIS( tmpText );
+                                                               ArrangeDownloadData(Count, downResult);
+                               if downResult.Count > 0 then begin
+                                       if FileExists( FilePath ) then
+                                               logStream := TFileStream.Create( FilePath, fmOpenReadWrite or fmShareDenyWrite )
+                                       else
+                                               logStream := TFileStream.Create( FilePath, fmCreate or fmShareDenyWrite );
+                                       try
+                                               logStream.Position      := logStream.Size;
+                                               logStream.Write( PChar( downResult.Text )^, Length( downResult.Text ) );
+                                       finally
+                                               logStream.Free;
+                                       end;
+
+                                       if Count = 0 then
+                                                                                       // \90V\8bK
+                                               Result := dsComplete
+                                       else
+                                               // \92Ç\8bL
+                                               Result := dsDiffComplete;
+
+                                                                               Size                                    := Size + Length( downResult.Text );
+                                       // CGI \82©\82ç\82Í\90³\82µ\82¢\93ú\95t\82ª\93¾\82ç\82ê\82È\82¢\82Ì\82Å\8c»\8dÝ\82É\90Ý\92è
+                                       LastModified    := Now;
+
+
+
+                                       NewReceive              := Count + 1;
+                                       Count                                   := Count + downResult.Count;
+                                       NewResCount             := downResult.Count;
+
+
+
+                               end else begin
+                                       Result := dsNotModify;
+                               end;
+                       finally
+                               downResult.Free;
+                       end;
+               end else if responseCode = 302 then begin
+                       //http://jbbs.shitaraba.com/bbs/read.cgi/game/3477/1077473358/
+                       //http://jbbs.shitaraba.com/game/bbs/read.cgi?BBS=3477&KEY=1077473358
+                       //http://jbbs.shitaraba.com/game/3477/storage/1077473358.html
+                       //\89ß\8b\8e\83\8d\83O
+                       //tmpURL := URL;
+                       if Assigned( InternalPrint ) then
+                               InternalPrint( '\89ß\8b\8e\83\8d\83O\91q\8cÉ\93ü\82è' );
+                       uri := TIdURI.Create( ReadURL );
+                       uriList := TStringList.Create;
+                       try
+                               ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
+                               tmpURL := uri.Protocol + '://' + uri.Host +
+                                               '/' + uriList[3] + '/' + uriList[4] + '/storage/' + uriList[ 5 ] + '.html';
+                       finally
+                               uriList.Free;
+                               uri.Free;
+                       end;
+                       Result := StorageDownload(tmpURL);
+               end else if responseCode = 304 then begin
+                       Result := dsNotModify;
+               end;
+       finally
+               DisposeResultString( tmp );
+       end;
+
+end;
+// *************************************************************************
+// download\82µ\82Ä\82«\82½Dat\82Ì\82 \82Ú\81[\82ñ\82³\82ê\82½\95ª\82ð\95â\8f[\82µ\82Ä\81A
+// \83\8c\83X\90\94\82Æ\88ê\92v\82·\82é\82æ\82¤\82É\82·\82é
+// *************************************************************************
+procedure      TBeThreadItem.ArrangeDownloadData(
+       start: Integer; // \90V\8bK\81F\82O\81@\92Ç\8bL\81F\91O\89ñ\82Ü\82Å\82Ì\8eæ\93¾\90\94
+               var Data: TStringList   //Dat\82Ì\83f\81[\83^
+);
+var
+       i: Integer;
+               n: Integer;
+               tmp: string;
+begin
+       i := start;
+               while i < Data.count + start do begin
+                       try
+                                       tmp := Copy(Data[i - start], 1 , AnsiPos('<>', Data[ i - start ] )-1 );
+                                               try
+                                                       n := StrToInt(tmp);
+                                                               if n > i + 1 then begin
+                                                                       Data.Insert(i - start, Format('%d<><><><><><>', [i+1]));
+                                                               end;
+                                                               Inc(i);
+                                               except
+                                                       Inc(i);
+                       end;
+                               except
+
+                               end;
+               end;
+
+end;
+// *************************************************************************
+// \89ß\8b\8e\83\8d\83O\97pDownload\8aÖ\90\94
+// *************************************************************************
+function       TBeThreadItem.StorageDownload(
+       AURL : string
+) : TDownloadState;
+var
+       modified                        : Double;
+       tmp                                             : PChar;
+    uri : TIdURI;
+       uriList : TStringList;
+       downResult              : TStringList;
+       responseCode    : Longint;
+       logStream                       : TFileStream;
+       tmpText, tmpLine, tmpTitle: string;
+       tmpHTML: TStringList;
+
+       i, j, tS, tE: Integer;
+       tmpDatToken : array[0..6] of string;
+begin
+
+       Result := dsError;
+       uri := TIdURI.Create( ReadURL );
+       uriList := TStringList.Create;
+       try
+               ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
+               FileName := uriList[ 5 ] + '.dat';
+               // http://jbbs.livedoor.com/bbs/rawmode.cgi/game/1578/1067968274/l100
+               // protocol://host/1/2/3/4/5/uriList.Count - 1
+               if MyLogFolder = '' then begin
+                       // \82Ç\82±\82É\95Û\91\82µ\82Ä\82¢\82¢\82Ì\82©\95ª\82©\82ç\82È\82¢\82Ì\82Å\88ê\8e\9e\83t\83@\83C\83\8b\82É\95Û\91
+                       FilePath                        := TemporaryFile;
+                       FIsTemporary    := True;
+               end else begin
+                       FilePath                        := MyLogFolder + uriList[ 3 ] + '\' + uriList[ 4 ] + '\' + uriList[ 5 ] + '.dat';
+                       FIsTemporary    := False;
+               end;
+       finally
+               uri.Free;
+               uriList.Free;
+       end;
+
+       // \95Û\91\97p\82Ì\83f\83B\83\8c\83N\83g\83\8a\82ð\8c@\82é
+       ForceDirectoriesEx( Copy( FilePath, 1, LastDelimiter( '\', FilePath ) ) );
+
+
+
+       // \93Æ\8e©\82É\83_\83E\83\93\83\8d\81[\83h\82â\83t\83B\83\8b\83^\83\8a\83\93\83O\82ð\8ds\82í\82È\82¢\8fê\8d\87\82Í
+       // InternalDownload \82É\94C\82¹\82é\82±\82Æ\82ª\8fo\97\88\82é
+       modified        := LastModified;
+
+       responseCode := InternalDownload( PChar( AURL ), modified, tmp, 0 );
+
+       try
+               if (responseCode = 200) or (responseCode = 206) then begin
+                       downResult := TStringList.Create;
+                       try
+                               tmpText := CustomStringReplace( string( tmp ), '¡÷¡®', ',' );
+
+
+
+                               //**\82±\82±\82ÅHTML\83t\83@\83C\83\8b\82ð\82µ\82½\82ç\82ÎJBBS\82Ìdat\8c`\8e®\82É\95Ï\8a·\82·\82é
+                               tmpHTML := TStringList.Create;
+
+                               try
+                                       tmpHTML.Text := EUCtoSJIS( tmpText );
+                                       //Title\82Ì\8eæ\93¾
+                                       for i := 0 to tmpHTML.Count - 1 do begin
+                                               tmpLine := AnsiLowerCase(tmpHTML[i]);
+                                               tS := AnsiPos('<title>', tmpLine);
+                                               tE := AnsiPos('</title>', tmpLine);
+
+                                               if tS > 0 then begin
+                                                       if tE - tS  = 1 then begin
+                                                               tmpTitle := '';
+                                                       end else begin
+                                                               tmpTitle := Copy(tmpHTML[i], ts + 7, Length(tmpHTML[i]));
+                                                               tmpLine := AnsiLowerCase(tmpTitle);
+                                                               tE := AnsiPos('</title>', tmpLine);
+
+                                                               if tE > 0 then begin
+                                                                       tmpTitle := Copy(tmpTitle, 1, tE - 1);
+                                                               end else begin
+                                                                       j := i + 1;
+                                                                       tmpLine := AnsiLowerCase(tmpHTML[j]);
+                                                                       tE := AnsiPos('</title>', tmpLine);
+                                                                       tmpTitle := tmpTitle  + tmpHTML[j];
+                                                                       while( tE = 0 ) do begin
+                                                                               j := i + 1;
+                                                                               if j = tmpHTML.Count then break;
+                                                                               tmpLine := AnsiLowerCase(tmpHTML[j]);
+                                                                               tE := AnsiPos('</title>', tmpLine);
+                                                                               tmpTitle := tmpTitle  + tmpHTML[j];
+                                                                       end;
+                                                                       if tE = 0 then tmpTitle := ''
+                                                                       else begin
+                                                                               tmpLine := AnsiLowerCase(tmpTitle);
+                                                                               tE := AnsiPos('</title>', tmpLine);
+                                                                               tmpTitle := Copy(tmpTitle, 1, tE - 1);
+                                                                       end;
+                                                               end;
+                                                       end;
+                                               end;
+                                       end;
+                                       //Title := tmpTitle;
+                                       //tS := 0; tE := 0;
+                                       //\96{\95\82Ì\8eæ\93¾ <DL>\82Ì\8e\9f\82Ì\8ds\82©\82ç</DL>\82Ì\91O\82Ì\8ds\82Ü\82Å
+                                       for i := tmpHTML.Count - 1 downto 0 do begin
+                                               tmpLine := AnsiLowerCase(tmpHTML[i]);
+                                               tE := AnsiPos('</dl>', tmpLine);
+                                               if tE > 0 then begin
+                            tmpHTML[i] := COpy(tmpHTML[i], 1, tE -1);
+                                                       break;
+                                               end;
+                                               tmpHTML.Delete(i);
+                                       end;
+                                       j := 0;
+                                       for i := 0 to tmpHTML.Count - 1 do begin
+                                               tmpLine := AnsiLowerCase(tmpHTML[i]);
+                                               tS := AnsiPos('<dl>', tmpLine);
+                                               if tS > 0 then begin
+                                                       j := i + 1;
+                                                       break;
+                                               end;
+                                       end;
+                                       for i := j downto 0 do
+                                               tmpHTML.Delete(i);
+
+                                       //<DD><DT>\82»\82ê\82¼\82ê\88ê\8ds\82É\95Ï\8a·\82·\82é
+                                       for i := tmpHTML.Count - 1 downto 1 do begin
+                                               tmpLine := AnsiLowerCase(tmpHTML[i]);
+                                               if (AnsiPos('<dd>', tmpLine) = 0) and (AnsiPos('<dt>', tmpLine) = 0) then begin
+                                                       tmpLine := CustomStringReplace(tmpHTML[i-1], #13#10, '') +
+                                                                                       CustomStringReplace(tmpHTML[i], #13#10, '');
+                                                       tmpHTML.Insert(i-1, tmpLine);
+                                                       tmpHTML.Delete(i + 1);
+                                                       tmpHTML.Delete(i);
+                                               end;
+                                       end;
+                                       //\8fã\82Ü\82Å\82Ì\8f\88\97\9d\82Å\88È\89º\82Ì\82æ\82¤\82È\8c`\82É\82È\82Á\82Ä\82é
+                                       //<dt><a name="958">958 </a> \96¼\91O\81F<font color="#008800"><b> \96¼\82à\96³\82«\8cR\8et </b></font> \93\8a\8de\93ú\81F 2004/06/30(\90\85) 15:17 [ r1FsjJhA ]<br><dd>\81`\81`
+                                       //<dt><a name="951">951 </a> \96¼\91O\81F<a href="mailto:sage"><b> \96¼\82à\96³\82«\8cR\8et </B></a> \93\8a\8de\93ú\81F 2004/06/30(\90\85) 12:31 [ .oGr0rtc ]<br><dd>\81`\81`
+                                       //\8fã\82Ì\82æ\82¤\82È\82Ì\82ð\89º\82Ì\82æ\82¤\82Èdat\82Ì\8c`\8e®\82É\95Ï\8a·\82·\82é
+                                       //\83\8c\83X\94Ô\8d\86<><font color=#FF0000>HN</font><>\83\81\83\8b\97\93<>\93ú\95t\8e\9e\8d\8f<>\96{\95¶<>\83^\83C\83g\83\8b\81i\82P\82Ì\82Ý\81j<>ID
+                                       //2<>\96¼\82à\96³\82«\8cR\8et<>sage<>2004/06/22(\89Î) 09:05<>\82Q\82°\82Æ\81[<><>26bmLAzg
+                                       for i := 0 to tmpHTML.Count - 1 do begin
+                                               tmpDatToken[0] := ''; tmpDatToken[1] := ''; tmpDatToken[2] := '';
+                                               tmpDatToken[3] := ''; tmpDatToken[4] := ''; tmpDatToken[6] := '';
+                                               //==\82Ü\82¸\82Í\96{\95\82ð\8eæ\93¾==//
+                                               tmpLine := AnsiLowerCase(tmpHTML[i]);
+                                               tS := AnsiPos('<dd>', tmpLine);
+                                               if tS > 0 then begin
+                                                       tmpDatToken[4] := Copy(tmpHTML[i], tS + 4, Length(tmpHTML[i]));
+                                                       tmpHTML[i] := Copy(tmpHTML[i], 1, tS -1);
+                                               end else
+                                                       tmpDatToken[4] := '';
+                                               //====================//
+                                               //==\83\8c\83X\94Ô\8d\86\8eæ\93¾==//
+                                               tmpLine := AnsiLowerCase(tmpHTML[i]);
+                                               tS := AnsiPos('">', tmpLine);
+                                               tE := AnsiPos('</a>', tmpLine);
+                                               if tE > tS then begin
+                                                       tmpDatToken[0] := Copy(tmpHTML[i], tS + 2, tE - (tS + 2) - 1);
+                                                       tmpDatToken[0] := Trim(tmpDatToken[0]);
+                                                       tmpHTML[i] := Copy(tmpHTML[i], tE + 4, Length(tmpHTML[i]));
+                                               end else
+                                                       tmpDatToken[0] := IntToStr(i);
+                                               tS := AnsiPos('<', tmpHTML[i]);
+                                               if tS > 0 then begin
+                                                       tmpHTML[i] := Copy(tmpHTML[i], tS, Length(tmpHTML[i]));
+                                               end;
+                                               //====================//
+                                               //==\83\81\83\8b\97\93\8eæ\93¾==//
+                                               tmpLine := AnsiLowerCase(tmpHTML[i]);
+                                               tS := AnsiPos('<a href="mailto:', tmpLine);
+                                               if tS > 0 then begin //\83\81\83\8b\97\93\83A\83\8a
+                                                       tE := AnsiPos('">', tmpLine);
+                                                       tmpDatToken[2] := Copy(tmpHTML[i], tS + 16, tE - (tS + 16));
+                                                       tmpHTML[i] := Copy(tmpHTML[i], tE + 5, Length(tmpHTML[i]));
+                            tmpHTML[i] := CustomStringReplace(tmpHTML[i], '</a>', '', true);
+                                               end else begin  //\83\81\83\8b\97\93\96³\82µ
+                                                       tmpDatToken[2] := '';
+                                               end;
+                                               //====================//
+                                               //==HN\8eæ\93¾==//
+                                               tmpLine := AnsiLowerCase(tmpHTML[i]);
+                                               tE := AnsiPos('\93\8a\8de\93ú\81F', tmpLine);
+                                               if tE > 0 then begin
+                                                       tmpDatToken[1] := Trim(Copy(tmpHTML[i], 1, tE - 1 ));
+                                                       tmpDatToken[1] := CustomStringReplace(tmpDatToken[1], '<b>', '', true);
+                                                       tmpDatToken[1] := CustomStringReplace(tmpDatToken[1], '</b>', '', true);
+                                                       tmpHTML[i] := Copy(tmpHTML[i], tE + 8, Length(tmpHTML[i]));
+                                               end else begin
+                                                       tmpDatToken[1] := '';
+                                               end;
+                                               //====================//
+                                               //==\93ú\95t\8e\9e\8d\8f\82Ì\8eæ\93¾==//
+                                               tmpLine := AnsiLowerCase(tmpHTML[i]);
+                                               tE := AnsiPos('[', tmpLine);
+                                               if tE > 0 then begin
+                                                       tmpDatToken[3] := Trim(Copy(tmpHTML[i], 1, tE - 1 ));
+                                                       tmpHTML[i] := Copy(tmpHTML[i], tE + 1, Length(tmpHTML[i]));
+                                               end else begin
+                                                       tmpDatToken[3] := '';
+                                               end;
+                                               //====================//
+                                               //==ID\82Ì\8eæ\93¾==//
+                                               tmpLine := AnsiLowerCase(tmpHTML[i]);
+                                               tE := AnsiPos(']', tmpLine);
+                                               if tE > 0 then begin
+                                                       tmpDatToken[6] := Trim(Copy(tmpHTML[i], 1, tE - 1 ));
+                                               end else begin
+                                                       tmpDatToken[6] := '';
+                                               end;
+                                               //====================//
+                                               tS := StrToIntDef(tmpDatToken[0], -1);
+                                               if  tS = 1      then
+                                                       tmpLine := tmpDatToken[0] + '<>' + tmpDatToken[1] + '<>' + tmpDatToken[2] + '<>' +
+                                                                       tmpDatToken[3] + '<>' + tmpDatToken[4] + '<>' + tmpTitle + '<>' + tmpDatToken[6]
+                                               else
+                                                       tmpLine := tmpDatToken[0] + '<>' + tmpDatToken[1] + '<>' +tmpDatToken[2] + '<>' +
+                                                                       tmpDatToken[3] + '<>' + tmpDatToken[4] + '<><>' + tmpDatToken[6];
+                                               tmpHTML[i] := tmpLine;
+                                       end;
+
+
+
+
+                                       downResult.Text := tmpHTML.Text;
+                               finally
+                                       tmpHTML.free;
+                               end;
+
+                               ArrangeDownloadData(Count, downResult);
+
+                               if downResult.Count > 0 then begin
+                                       if FileExists( FilePath ) then
+                                               DeleteFile(FilePath);
+
+                                       logStream := TFileStream.Create( FilePath, fmCreate or fmShareDenyWrite );
+                                       try
+                                               logStream.Position      := 0;
+                                               logStream.Write( PChar( downResult.Text )^, Length( downResult.Text ) );
+                                       finally
+                                               logStream.Free;
+                                       end;
+
+                                       // \90V\8bK
+                                       Result := dsComplete;
+
+                                       Size    := Length( downResult.Text );
+                                       // CGI \82©\82ç\82Í\90³\82µ\82¢\93ú\95t\82ª\93¾\82ç\82ê\82È\82¢\82Ì\82Å\8c»\8dÝ\82É\90Ý\92è
+                                       LastModified    := Now;
+
+
+
+                                       NewReceive              := 1;
+                                       Count                                   := downResult.Count;
+                                       NewResCount             := downResult.Count;
+                                       //http://jbbs.livedoor.com/bbs/read.cgi/game/1578/1086710948/l100
+                                       //http://jbbs.livedoor.com/game/1578/storage/1086710948.html
+                                       //URL := 'http://jbbs.livedoor.com/bbs/read.cgi' +
+                                       //              CustomStringReplace(Path, '/storage', '')
+                                       //              + FileName;
+                                       DownloadHost := 'storage';
+                               end else begin
+                                       Result := dsNotModify;
+                               end;
+                       finally
+                               downResult.Free;
+                       end;
+               end else if responseCode = 304 then begin
+                       Result := dsNotModify;
+               end;
+       finally
+               DisposeResultString( tmp );
+       end;
+
+end;
+
+// *************************************************************************
+// \8f\91\82«\8d\9e\82Ý\82ð\8ew\8e¦\82³\82ê\82½
+// *************************************************************************
+function       TBeThreadItem.Write(
+       inName                          : string;       // \96¼\91O(\83n\83\93\83h\83\8b)
+       inMail                          : string;       // \83\81\81[\83\8b\83A\83h\83\8c\83X
+       inMessage                       : string        // \96{\95
+) : TDownloadState;                            // \8f\91\82«\8d\9e\82Ý\82ª\90¬\8c÷\82µ\82½\82©\82Ç\82¤\82©
+var
+       postData                        : string;
+       postResult              : PChar;
+       uri                                             : TIdURI;
+       uriList                         : TStringList;
+       responseCode    : Integer;
+begin
+
+       uri                     := TIdURI.Create( URL );
+       uriList := TStringList.Create;
+       try
+               ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
+
+               // http://jbbs.livedoor.com/bbs/read.cgi/game/1578/1067968274/l100
+               postData        :=
+                       'NAME='                 + HttpEncode( SJIStoEUC( inName ) ) +
+                       '&MAIL='                + HttpEncode( SJIStoEUC( inMail ) ) +
+                       '&MESSAGE='     + HttpEncode( SJIStoEUC( inMessage ) ) +
+                       '&BBS='                 + uriList[ 4 ] +
+                       '&KEY='                 + uriList[ 5 ] +
+                       '&DIR='                 + uriList[ 3 ] +
+                       '&TIME='                + IntToStr( DateTimeToUnix( Now ) ) +
+                       '&submit='      + HttpEncode( SJIStoEUC( '\8f\91\82«\8d\9e\82Þ' ) );
+
+               // \93Æ\8e©\82É\92Ê\90M\82µ\82È\82¢\8fê\8d\87\82Í InternalPost \82É\94C\82¹\82é\82±\82Æ\82ª\8fo\97\88\82é
+               responseCode := InternalPost( PChar( WriteURL ), PChar( postData ), postResult );
+               try
+                       if (responseCode = 200) or
+                               ((responseCode = 302) and (Length( Trim( postResult ) ) = 0)) then begin
+                               Result := dsComplete
+                       end else begin
+                               Result := dsError;
+                               if Assigned( InternalPrint ) then
+                                       InternalPrint( postResult );
+                       end;
+               finally
+                       DisposeResultString( postResult );
+               end;
+       finally
+               uri.Free;
+               uriList.Free;
+       end;
+
+end;
+
+// *************************************************************************
+// \83\8c\83X\94Ô\8d\86 inNo \82É\91Î\82·\82é html \82ð\97v\8b\81\82³\82ê\82½
+// *************************************************************************
+function TBeThreadItem.GetRes(
+       inNo            : Integer               // \97v\8b\81\82³\82ê\82½\83\8c\83X\94Ô\8d\86
+) : string;                                            // \91Î\89\9e\82·\82é HTML
+var
+       res                     : string;
+       tmp                     : PChar;
+begin
+
+       // \93Æ\8e©\82É\83t\83B\83\8b\83^\83\8a\83\93\83O\82ð\8ds\82í\82È\82¢\8fê\8d\87\82Í
+       // InternalAbon \82¨\82æ\82Ñ Dat2HTML \82É\94C\82¹\82é\82±\82Æ\82ª\8fo\97\88\82é
+               {
+       LoadDat;
+       if FDat = nil then begin
+               // \83\8d\83O\82É\91\8dÝ\82µ\82È\82¢\82Ì\82Å\82±\82Ì\82Ü\82Ü\8fI\97¹
+               Result := '';
+               Exit;
+       end;
+       res := Copy( FDat[ inNo - 1 ], AnsiPos( '<>', FDat[ inNo - 1 ] ) + 2, MaxInt );
+               }
+       res := GetDat( inNo );
+       if res = '' then begin
+               Result := '';
+               Exit;
+       end else begin
+               tmp := InternalAbonForOne( PChar( res ), PChar( FilePath ),inNo );
+               try
+                       Result := Dat2HTML( string( tmp ), inNo );
+               finally
+                       DisposeResultString( tmp );
+               end;
+       end;
+
+end;
+
+// *************************************************************************
+// \83\8c\83X\94Ô\8d\86 inNo \82É\91Î\82·\82é Dat \82ð\97v\8b\81\82³\82ê\82½
+// *************************************************************************
+function TBeThreadItem.GetDat(
+       inNo            : Integer               // \97v\8b\81\82³\82ê\82½\83\8c\83X\94Ô\8d\86
+) : string;                                            // \82Q\82¿\82á\82ñ\82Ë\82é\82ÌDat\8c`\8e®
+var
+       res                     : string;
+       tmp                     : array[1..5] of string;
+       i                       : Integer;
+       pTmp            : PChar;
+begin
+       pTmp := nil;
+       // \93Æ\8e©\82É\83t\83B\83\8b\83^\83\8a\83\93\83O\82ð\8ds\82í\82È\82¢\8fê\8d\87\82Í
+       // InternalAbon \82¨\82æ\82Ñ Dat2HTML \82É\94C\82¹\82é\82±\82Æ\82ª\8fo\97\88\82é
+       LoadDat;
+       if (FDat = nil) or (inNo - 1 < 0 ) or (inNo - 1 >= FDat.Count) then begin
+               // \83\8d\83O\82É\91\8dÝ\82µ\82È\82¢\82Ì\82Å\82±\82Ì\82Ü\82Ü\8fI\97¹
+               Result := '';
+               Exit;
+       end;
+       try
+               res := Copy( FDat[ inNo - 1 ], AnsiPos( '<>', FDat[ inNo - 1 ] ) + 2, MaxInt );
+               //\96\96\94ö\82ÉID\82ª\95\\8e¦\82³\82ê\82Ä\82¢\82é\82Ì\82Å\82»\82ê\82ð\93\8a\8de\93ú\82Ì\82Æ\82±\82ë\82É\93ü\82ê\82é
+               // \96¼\91O<>\83\81\81[\83\8b<>\93ú\95t<>\96{\95¶<>\83X\83\8c\83^\83C<>ID
+               for i := 0 to 4 do begin
+                       tmp[ i + 1 ] := Copy( res, 1, AnsiPos('<>', res) - 1 );
+                       Delete( res, 1, AnsiPos('<>', res) + 1 );
+               end;
+               // \96¼\91O<>\83\81\81[\83\8b<>\93ú\95tID<>\96{\95¶<>\83X\83\8c\83^\83C
+               pTmp := CreateResultString(tmp[1] + '<>' + tmp[2] + '<>' + tmp[3] + ' ' + res + '<>'+ tmp[4] + '<>' +tmp[5]);
+               Result := string(pTmp);
+       finally
+               DisposeResultString(pTmp);
+       end;
+
+end;
+
+// *************************************************************************
+// \83X\83\8c\83b\83h\82Ì\83w\83b\83_ html \82ð\97v\8b\81\82³\82ê\82½
+// *************************************************************************
+function TBeThreadItem.GetHeader(
+       inOptionalHeader        : string
+) : string;
+begin
+
+       // \93Æ\8e©\82É\83t\83B\83\8b\83^\83\8a\83\93\83O\82ð\8ds\82í\82È\82¢\8fê\8d\87\82Í
+       // InternalHeader \82É\94C\82¹\82é\82±\82Æ\82ª\8fo\97\88\82é
+       Result := InternalHeader(
+               '<meta http-equiv="Content-type" content="text/html; charset=Shift_JIS">' +
+               inOptionalHeader );
+
+
+       // GetRes \82ð\8cÄ\82Î\82ê\82é\82±\82Æ\82ª\97\\91z\82³\82ê\82é\82Ì\82Å FDat \82ð\90\90¬\82µ\82Ä\82¨\82­
+       try
+               FreeDat;
+               LoadDat;
+       except
+       end;
+
+end;
+
+// *************************************************************************
+// \83X\83\8c\83b\83h\82Ì\83t\83b\83^ html \82ð\97v\8b\81\82³\82ê\82½
+// *************************************************************************
+function TBeThreadItem.GetFooter(
+       inOptionalFooter : string
+) : string;
+begin
+
+       // \93Æ\8e©\82É\83t\83B\83\8b\83^\83\8a\83\93\83O\82ð\8ds\82í\82È\82¢\8fê\8d\87\82Í
+       // InternalFooter \82É\94C\82¹\82é\82±\82Æ\82ª\8fo\97\88\82é
+       Result := InternalFooter( inOptionalFooter );
+
+       // \82à\82¤ GetRes \82Í\8cÄ\82Î\82ê\82È\82¢\82Æ\8ev\82¤\82Ì\82Å FDat \82ð\8aJ\95ú\82µ\82Ä\82¨\82­
+       try
+               FreeDat;
+       except
+       end;
+
+end;
+
+// *************************************************************************
+// \82±\82Ì ThreadItem \82ª\91®\82·\82é\94Â\82Ì URL \82ð\97v\8b\81\82³\82ê\82½
+// *************************************************************************
+function       TBeThreadItem.GetBoardURL : string;
+var
+       uri                                             : TIdURI;
+       uriList                         : TStringList;
+       tmphost:        String;
+const
+       BBS_HOST                = 'be.2ch.net';
+begin
+
+       uri                     := TIdURI.Create( ReadURL );
+       uriList := TStringList.Create;
+       try
+               ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
+               FileName := uriList[ 4 ] + '.dat';
+               Result          := CreateResultString(
+                       uri.Protocol + '://' + uri.host + '/' + uriList[ 3 ] + '/' );
+       finally
+               uri.Free;
+               uriList.Free;
+       end;
+
+end;
+
+// *************************************************************************
+// FDat \82Ì\90\90¬
+// *************************************************************************
+procedure      TBeThreadItem.LoadDat;
+begin
+
+       if FDat = nil then begin
+               if IsLogFile then begin
+                       // dat \82Ì\93Ç\82Ý\8d\9e\82Ý
+                       FDat := TStringList.Create;
+                       FDat.LoadFromFile( FilePath );
+               end;
+       end;
+
+end;
+
+// *************************************************************************
+// FDat \82Ì\8aJ\95ú
+// *************************************************************************
+procedure      TBeThreadItem.FreeDat;
+begin
+
+       if FDat <> nil then begin
+               FDat.Free;
+               FDat := nil;
+       end;
+
+end;
+
+// *************************************************************************
+// \88À\91S\82È\83u\83\89\83E\83U\95\\8e¦\97p\82Ì URL
+// *************************************************************************
+function       TBeThreadItem.BrowsableURL : string;
+var
+       uri                             : TIdURI;
+       uriList         : TStringList;
+       foundPos        : Integer;
+       dir, tmphost            : string;
+const
+    THREAD_MARK        = '/test/read.cgi';
+       BBS_HOST                = 'be.2ch.net';
+begin
+    if Copy( URL, Length( URL ), 1 ) = '/' then
+        uri := TIdURI.Create( URL )
+    else
+        uri := TIdURI.Create( URL + '/' );
+
+    uriList := TStringList.Create;
+    try
+        ExtractHttpFields( ['/'], [], uri.Path, uriList );
+
+        if( AnsiPos(THREAD_MARK, URL) > 0) and (uriList.Count > 4) then begin
+            Result :=
+                uri.Protocol + '://' + uri.host + THREAD_MARK + '/' +
+                uriList[ 3 ] + '/' + uriList[ 4 ] + '/l50';
+
+        end else if AnsiPos(THREAD_MARK, URL) = 0 then begin
+            {
+            //\83R\83R\82Å\89ß\8b\8e\83\8d\83O\82©\82Ç\82¤\82©\83`\83F\83b\83N\81H
+            if(AnsiPos('.html/', uri.Path) > 0) then begin
+                Result := uri.Protocol + '://' + url.host + THREAD_MARK +
+                    CustomStringReplace(CustomStringReplace(uri.Path, '/storage', ''), '.html/', '/') + 'l100';
+            end else
+            }
+            Result := URL;
+        end;
+    finally
+        uri.Free;
+        uriList.Free;
+    end;
+
+end;
+
+// *************************************************************************
+// \88À\91S\82È( '/' \82Å\8fI\82í\82é )\93Ç\82Ý\8d\9e\82Ý\82Ì URL
+// *************************************************************************
+function       TBeThreadItem.ReadURL : string;
+var
+       uri                             : TIdURI;
+       uriList         : TStringList;
+       foundPos        : Integer;
+       dir, tmphost                    : string;
+const
+    THREAD_MARK        = '/test/read.cgi';
+    BBS_HOST           = 'be.2ch.net';
+begin
+
+    if Copy( URL, Length( URL ), 1 ) = '/' then
+        uri := TIdURI.Create( URL )
+    else
+        uri := TIdURI.Create( URL + '/' );
+    uriList := TStringList.Create;
+    try
+        ExtractHttpFields( ['/'], [], uri.Path, uriList );
+
+        if( AnsiPos(THREAD_MARK, URL) > 0) and (uriList.Count > 4) then begin
+            Result :=
+                uri.Protocol + '://' + uri.Host + THREAD_MARK +
+                uriList[ 3 ] + '/' + uriList[ 4 ] + '/';
+        end;
+    finally
+        uri.Free;
+        uriList.Free;
+    end;
+end;
+
+// *************************************************************************
+// \88À\91S\82È( '/' \82Å\8fI\82í\82é )\8f\91\82«\8d\9e\82Ý\82Ì URL
+// *************************************************************************
+function       TBeThreadItem.WriteURL : string;
+var
+       uri                     : TIdURI;
+       uriList : TStringList;
+begin
+
+       if Copy( URL, Length( URL ), 1 ) = '/' then
+               uri := TIdURI.Create( URL )
+       else
+               uri := TIdURI.Create( URL + '/' );
+       uriList := TStringList.Create;
+       try
+               ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
+               // http://jbbs.livedoor.com/bbs/read.cgi/game/1578/1067968274/l100
+               Result          :=
+                       uri.Protocol + '://' + uri.Host + '/bbs/write.cgi/' +
+                       uriList[ 3 ] + '/' + uriList[ 4 ] + '/' + uriList[ 5 ] + '/';
+       finally
+               uri.Free;
+               uriList.Free;
+       end;
+
+end;
+
+// *************************************************************************
+// TThreadItem \82ª\90\90¬\82³\82ê\82½\8fê\8d\87\82Ì\8f\88\92u(TBeThreadItem \82ð\90\90¬\82·\82é)
+// *************************************************************************
+procedure ThreadItemOnCreateOfTBeThreadItem(
+       inInstance : DWORD
+);
+var
+       threadItem : TBeThreadItem;
+begin
+
+       threadItem := TBeThreadItem.Create( inInstance );
+       ThreadItemSetLong( inInstance, tipContext, DWORD( threadItem ) );
+
+end;
+
+// *************************************************************************
+// TThreadItem \82ª\94j\8aü\82³\82ê\82½\8fê\8d\87\82Ì\8f\88\92u(TBeThreadItem \82ð\94j\8aü\82·\82é)
+// *************************************************************************
+procedure ThreadItemOnDisposeOfTBeThreadItem(
+       inInstance : DWORD
+);
+var
+       threadItem : TBeThreadItem;
+begin
+
+       threadItem := TBeThreadItem( ThreadItemGetLong( inInstance, tipContext ) );
+       threadItem.Free;
+
+end;
+
+// =========================================================================
+// TBeBoardItem
+// =========================================================================
+
+// *************************************************************************
+// \83R\83\93\83X\83g\83\89\83N\83^
+// *************************************************************************
+constructor TBeBoardItem.Create(
+       inInstance      : DWORD
+);
+var
+       uri                                     : TIdURI;
+       uriList                 : TStringList;
+const
+       BBS_HOST                = 'be.2ch.net';
+begin
+
+       inherited;
+
+       OnDownload                                              := Download;
+       OnCreateThread                          := CreateThread;
+       OnEnumThread                                    := EnumThread;
+       OnFileName2ThreadURL    := ToThreadURL;
+
+       FilePath                        := '';
+       FIsTemporary    := False;
+       FDat                                    := nil;
+
+       uri                     := TIdURI.Create( SubjectURL );
+       uriList := TStringList.Create;
+       try
+               URL := uri.Protocol + '://' + uri.Host + uri.Path;
+
+               ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
+               // http://jbbs.livedoor.com/game/1000/subject.txt
+               FilePath        := MyLogFolder + uriList[ 1 ] + '\' + uriList[ 2 ] + '\' + uri.Document;
+               IsLogFile       := FileExists( FilePath );
+       finally
+               uri.Free;
+               uriList.Free;
+       end;
+
+end;
+// *************************************************************************
+// \83f\83X\83g\83\89\83N\83^
+// *************************************************************************
+destructor TBeBoardItem.Destroy;
+begin
+
+       if FDat <> nil then begin
+               try
+                       FDat.Free;
+                       FDat := nil;
+               except
+               end;
+       end;
+
+       // \88ê\8e\9e\83t\83@\83C\83\8b\82Ì\8fê\8d\87\82Í\8dí\8f\9c\82·\82é
+       if FIsTemporary then
+               DeleteFile( FilePath );
+
+       inherited;
+
+end;
+
+// *************************************************************************
+// \8ew\92è\82µ\82½\83X\83\8c\88ê\97\97\82Ì\83_\83E\83\93\83\8d\81[\83h\82ð\97v\8b\81\82³\82ê\82½
+// *************************************************************************
+function TBeBoardItem.Download : TDownloadState;
+var
+       modified                        : Double;
+       downResult              : PChar;
+       responseCode    : Longint;
+       uri                                             : TIdURI;
+       uriList                         : TStringList;
+       i                                                       : Integer;
+               tmpText : String;
+begin
+
+       Result := dsError;
+
+       if FDat <> nil then begin
+               try
+                       FDat.Free;
+                       FDat := nil;
+               except
+               end;
+       end;
+       FDat            := TStringList.Create;
+       uri                     := TIdURI.Create( SubjectURL );
+       uriList := TStringList.Create;
+       // \93Æ\8e©\82É\83_\83E\83\93\83\8d\81[\83h\82â\83t\83B\83\8b\83^\83\8a\83\93\83O\82ð\8ds\82í\82È\82¢\8fê\8d\87\82Í
+       // InternalDownload \82É\94C\82¹\82é\82±\82Æ\82ª\8fo\97\88\82é
+       modified                        := LastModified;
+       responseCode    := InternalDownload( PChar( uri.URI ), modified, downResult );
+       try
+               if responseCode = 200 then begin
+                       try
+                               // \83p\83X\82ð\8eZ\8fo
+                               ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
+                               if MyLogFolder = '' then begin
+                                       // \82Ç\82±\82É\95Û\91\82µ\82Ä\82¢\82¢\82Ì\82©\95ª\82©\82ç\82È\82¢\82Ì\82Å\88ê\8e\9e\83t\83@\83C\83\8b\82É\95Û\91
+                                       FilePath                        := TemporaryFile;
+                                       FIsTemporary    := True;
+                               end else begin
+                                       FilePath                        := MyLogFolder + uriList[ 1 ] + '\' + uriList[ 2 ] + '\' + uri.Document;
+                                       FIsTemporary    := False
+                               end;
+
+                               // \95Û\91\97p\82Ì\83f\83B\83\8c\83N\83g\83\8a\82ð\8c@\82é
+                               ForceDirectoriesEx( Copy( FilePath, 1, LastDelimiter( '\', FilePath ) ) );
+
+                               // EUC \82ð Shift_JIS \82É
+                tmpText := CustomStringReplace( string( downResult ), '¡÷¡®', ',');
+                               FDat.Text := EUCtoSJIS( tmpText );
+                               // \95Û\91
+                               FDat.SaveToFile( FilePath );
+
+                               IsLogFile                       := True;
+                               RoundDate                       := Now;
+                               LastModified    := modified;
+                               LastGetTime             := Now;
+                       finally
+                               uri.Free;
+                               uriList.Free;
+                       end;
+                       Result := dsComplete;
+               end;
+       finally
+               DisposeResultString( downResult );
+       end;
+
+end;
+
+// *************************************************************************
+// \83X\83\8c\97§\82Ä\82ð\8ew\8e¦\82³\82ê\82½
+// *************************************************************************
+function       TBeBoardItem.CreateThread(
+       inSubject                       : string;       // \83X\83\8c\83^\83C
+       inName                          : string;       // \96¼\91O(\83n\83\93\83h\83\8b)
+       inMail                          : string;       // \83\81\81[\83\8b\83A\83h\83\8c\83X
+       inMessage                       : string        // \96{\95
+) : TDownloadState;                            // \8f\91\82«\8d\9e\82Ý\82ª\90¬\8c÷\82µ\82½\82©\82Ç\82¤\82©
+var
+       postURL                         : string;
+       postData                        : string;
+       postResult              : PChar;
+       uri                                             : TIdURI;
+       uriList                         : TStringList;
+       responseCode    : Integer;
+begin
+
+       uri                     := TIdURI.Create( URL );
+       uriList := TStringList.Create;
+       try
+               ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
+
+               postURL         :=
+                       uri.Protocol + '://' + uri.Host + '/bbs.cgi';
+        postData :=
+        'subject=&'
+        + 'FROM=' + HttpEncode(SJIStoEUC(inName)) + '&'
+        + 'mail=' + HttpEncode(SJIStoEUC(inMail)) + '&'
+        + 'MESSAGE=' + HttpEncode(SJIStoEUC(inMessage)) + '&'
+        + 'bbs=' + uriList[4] + '&'
+        + 'time=' + IntToStr(DateTimeToUnix( Now )) + '&'
+        + 'subject=' + HttpEncode(SJIStoEUC(inSubject)) + '&'
+        + 'submit=' + HttpEncode(SJIStoEUC('\91S\90Ó\94C\82ð\95\89\82¤\82±\82Æ\82ð\8f³\91ø\82µ\82Ä\8f\91\82«\8d\9e\82Þ')) + #13#10;
+               //s := s + 'subject=' + HttpEncode(TitleEdit.Text) + '&';
+               //s := s + 'submit=' + HttpEncode('\91S\90Ó\94C\82ð\95\89\82¤\82±\82Æ\82ð\8f³\91ø\82µ\82Ä\8f\91\82«\8d\9e\82Þ') + #13#10;
+
+               {postData       :=
+                       'SUBJECT='      + HttpEncode( SJIStoEUC( inSubject ) ) +
+                       '&NAME='                + HttpEncode( SJIStoEUC( inName ) ) +
+                       '&MAIL='                + HttpEncode( SJIStoEUC( inMail ) ) +
+                       '&MESSAGE='     + HttpEncode( SJIStoEUC( inMessage ) ) +
+                       '&BBS='                 + uriList[ 4 ] +
+                       '&TIME='                + IntToStr( DateTimeToUnix( Now ) ) +
+                       '&submit='      + HttpEncode( SJIStoEUC( '\90V\8bK\8f\91\82«\8d\9e\82Ý' ) );
+        }
+{
+       s := s + 'subject=&'
+                                + 'FROM=' + HttpEncode(NameComboBox.Text) + '&'
+                                + 'mail=' + HttpEncode(MailComboBox.Text) + '&'
+                                + 'MESSAGE=' + HttpEncode(body) + '&'
+                                + 'bbs=' + Board.BBSID + '&'
+                                + 'time=' + IntToStr(SendTime) + '&';
+       if FThreadItem = nil then begin
+               s := s + 'subject=' + HttpEncode(TitleEdit.Text) + '&';
+               s := s + 'submit=' + HttpEncode('\91S\90Ó\94C\82ð\95\89\82¤\82±\82Æ\82ð\8f³\91ø\82µ\82Ä\8f\91\82«\8d\9e\82Þ') + #13#10;
+       end else begin
+               s := s + 'key=' + ChangeFileExt(FThreadItem.FileName, '') + '&';
+               s := s + 'submit=' + HttpEncode('\8f\91\82«\8d\9e\82Þ') + #13#10;
+       end;
+
+}
+               // \93Æ\8e©\82É\92Ê\90M\82µ\82È\82¢\8fê\8d\87\82Í InternalPost \82É\94C\82¹\82é\82±\82Æ\82ª\8fo\97\88\82é
+               responseCode := InternalPost( PChar( postURL ), PChar( postData ), postResult );
+               try
+                       if (responseCode = 200) or
+                               ((responseCode = 302) and (Length( Trim( postResult ) ) = 0)) then begin
+                               Result := dsComplete
+                       end else begin
+                               Result := dsError;
+                               if Assigned( InternalPrint ) then
+                                       InternalPrint( postResult );
+                       end;
+               finally
+                       DisposeResultString( postResult );
+               end;
+       finally
+               uri.Free;
+               uriList.Free;
+       end;
+
+end;
+
+// *************************************************************************
+// \83X\83\8c\88ê\97\97\82Ì URL \82©\82ç\83X\83\8c\83b\83h\82Ì URL \82ð\93±\82«\8fo\82·
+// *************************************************************************
+function TBeBoardItem.ToThreadURL(
+       inFileName      : string        // \83X\83\8c\83b\83h\83t\83@\83C\83\8b\96¼
+) : string;                                                    // \83X\83\8c\83b\83h\82Ì URL
+var
+       threadURL               : string;
+       uri                                     : TIdURI;
+       uriList                 : TStringList;
+       found                           : Integer;
+begin
+
+       found := AnsiPos( '.', inFileName );
+       if found > 0 then
+               inFileName := Copy( inFileName, 1, found - 1 );
+
+       uri                     := TIdURI.Create( SubjectURL );
+       uriList := TStringList.Create;
+       try
+               try
+                       ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
+                       threadURL       := uri.Protocol + '://' + uri.Host + '/test/read.cgi/' +
+                               uriList[ 1 ] + '/' + inFileName + '/l50';
+                       Result          := threadURL;
+               finally
+                       uri.Free;
+                       uriList.Free;
+               end;
+       except
+               Result := '';
+       end;
+
+end;
+
+// *************************************************************************
+// \82±\82Ì\94Â\82É\82¢\82­\82Â\82Ì\83X\83\8c\82ª\82 \82é\82©\97v\8b\81\82³\82ê\82½
+// *************************************************************************
+procedure      TBeBoardItem.EnumThread(
+       inCallBack      : TBoardItemEnumThreadCallBack
+);
+var
+       uri                                     : TIdURI;
+       uriList                 : TStringList;
+begin
+
+       try
+               if FDat = nil then begin
+                       FDat            := TStringList.Create;
+                       uri                     := TIdURI.Create( SubjectURL );
+                       uriList := TStringList.Create;
+                       try
+                               // \83p\83X\82ð\8eZ\8fo
+                               ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
+                               // http://jbbs.livedoor.com/game/1000/subject.txt
+                               FilePath        := MyLogFolder + uriList[ 1 ] + '\' + uriList[ 2 ] + '\' + uri.Document;
+                               if FileExists( FilePath ) then
+                                       // \93Ç\82Ý\8d\9e\82Ý
+                                       FDat.LoadFromFile( FilePath );
+                       finally
+                               uri.Free;
+                               uriList.Free;
+                       end;
+               end;
+
+               // \93Æ\8e©\82É\83t\83B\83\8b\83^\83\8a\83\93\83O\82ð\8ds\82í\82È\82¢\8fê\8d\87\82Í EnumThread \82É\94C\82¹\82é\82±\82Æ\82ª\8fo\97\88\82é
+               inherited EnumThread( inCallBack, CustomStringReplace( FDat.Text, ',', '<>' ) );
+       except
+       end;
+
+end;
+
+// *************************************************************************
+// \83X\83\8c\88ê\97\97\82Ì URL \82ð\8b\81\82ß\82é
+// *************************************************************************
+function       TBeBoardItem.SubjectURL : string;
+var
+       uri                     : TIdURI;
+       uriList : TStringList;
+begin
+
+       uri                     := TIdURI.Create( URL );
+       uriList := TStringList.Create;
+       try
+               if uri.Document <> SUBJECT_NAME then begin
+                       if Copy( URL, Length( URL ), 1 ) = '/' then
+                               Result := URL + SUBJECT_NAME
+                       else
+                               Result := URL + '/' + SUBJECT_NAME;
+               end else begin
+                       // \82±\82±\82É\82Í\97\88\82È\82¢\82Æ\8ev\82¤\82¯\82Ç
+                       Result := URL;
+               end;
+       finally
+               uri.Free;
+               uriList.Free;
+       end;
+
+end;
+
+// *************************************************************************
+// TBoardItem \82ª\90\90¬\82³\82ê\82½\8fê\8d\87\82Ì\8f\88\92u(TBeBoardItem \82ð\90\90¬\82·\82é)
+// *************************************************************************
+procedure BoardItemOnCreateOfTBeBoardItem(
+       inInstance : DWORD
+);
+var
+       boardItem : TBeBoardItem;
+begin
+
+       boardItem := TBeBoardItem.Create( inInstance );
+       BoardItemSetLong( inInstance, bipContext, DWORD( boardItem ) );
+
+end;
+
+// *************************************************************************
+// TBoardItem \82ª\94j\8aü\82³\82ê\82½\8fê\8d\87\82Ì\8f\88\92u(TBeBoardItem \82ð\94j\8aü\82·\82é)
+// *************************************************************************
+procedure BoardItemOnDisposeOfTBeBoardItem(
+       inInstance : DWORD
+);
+var
+       boardItem : TBeBoardItem;
+begin
+
+       boardItem := TBeBoardItem( BoardItemGetLong( inInstance, bipContext ) );
+       boardItem.Free;
+
+end;
+
+
+
+// =========================================================================
+// \83G\83\93\83g\83\8a\83|\83C\83\93\83g
+// =========================================================================
+procedure DLLEntry(
+       ul_reason_for_call : DWORD
+);
+var
+       module : HMODULE;
+begin
+
+       case ul_reason_for_call of
+               DLL_PROCESS_ATTACH:
+               begin
+                       Randomize;
+
+                       module := GetModuleHandle( nil );
+
+                       LoadInternalAPI( module );
+                       LoadInternalFilePathAPI( module );
+                       LoadInternalThreadItemAPI( module );
+                       LoadInternalBoardItemAPI( module );
+
+                       // ===== \83C\83\93\83X\83^\83\93\83X\82Ì\8eæ\82è\88µ\82¢\82ð TThreadItem \82©\82ç TBeThreadItem \82É\95Ï\8dX\82·\82é
+                       ThreadItemOnCreate      := ThreadItemOnCreateOfTBeThreadItem;
+                       ThreadItemOnDispose     := ThreadItemOnDisposeOfTBeThreadItem;
+                       // ===== \83C\83\93\83X\83^\83\93\83X\82Ì\8eæ\82è\88µ\82¢\82ð TBoardItem \82©\82ç TBeBoardItem \82É\95Ï\8dX\82·\82é
+                       BoardItemOnCreate               := BoardItemOnCreateOfTBeBoardItem;
+                       BoardItemOnDispose      := BoardItemOnDisposeOfTBeBoardItem;
+               end;
+               //DLL_PROCESS_DETACH:
+               //begin
+               //      RemovePlugInMenu( SyncronizeMenu );
+               //end;
+               DLL_THREAD_ATTACH:
+                       ;
+               DLL_THREAD_DETACH:
+                       ;
+       end;
+
+end;
+
+exports
+       OnLoad,
+       OnVersionInfo,
+       OnAcceptURL;
+
+begin
+
+       try
+               DllProc := @DLLEntry;
+               DLLEntry( DLL_PROCESS_ATTACH );
+       except end;
+
+end.