--- /dev/null
+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.