1 library MachiBBSPlugIn;
5 \82Ü
\82¿BBS
\8f\88\97\9d\83\86\83j
\83b
\83g
9 Windows, SysUtils, Classes, Math, DateUtils,
11 PlugInMain in 'PlugInMain.pas',
12 ThreadItem in 'ThreadItem.pas',
13 BoardItem in 'BoardItem.pas',
14 FilePath in 'FilePath.pas',
15 MojuUtils in '..\..\MojuUtils.pas';
20 // =========================================================================
21 // TMachiBBSThreadItem
22 // =========================================================================
23 TMachiBBSThreadItem = class(TThreadItem)
25 FIsTemporary : Boolean;
29 constructor Create( inInstance : DWORD );
30 destructor Destroy; override;
33 function Download : TDownloadState;
34 function Write( inName : string; inMail : string; inMessage : string ) : TDownloadState;
35 function GetRes( inNo : Integer ) : string;
36 function GetDat( inNo : Integer ) : string;
37 function GetHeader( inOptionalHeader : string ) : string;
38 function GetFooter( inOptionalFooter : string ) : string;
39 function GetBoardURL : string;
41 procedure To2chDat( ioHTML : TStringList; inStartNo : Integer = 1 );
44 function ReadURL : string;
45 //property FilePath : string read FFilePath;
48 // =========================================================================
50 // =========================================================================
51 TMachiBBSBoardItem = class(TBoardItem)
53 FIsTemporary : Boolean;
57 constructor Create( inInstance : DWORD );
58 destructor Destroy; override;
61 function Download : TDownloadState;
62 function CreateThread( inSubject : string; inName : string; inMail : string; inMessage : string ) : TDownloadState;
63 function ToThreadURL( inFileName : string ) : string;
64 procedure EnumThread( inCallBack : TBoardItemEnumThreadCallBack );
66 function SubjectURL : string;
69 // =========================================================================
70 //
\83T
\83u
\83W
\83F
\83N
\83g
\83\8c\83R
\81[
\83h
71 // =========================================================================
79 LOG_DIR = 'MachiBBS\';
80 SUBJECT_NAME = 'subject.txt';
82 PLUGIN_NAME = 'MachiBBSPlugIn';
85 RELEASE_VERSION = 'beta';
86 REVISION_VERSION = 22;
88 // =========================================================================
90 // =========================================================================
92 // *************************************************************************
93 //
\83e
\83\93\83|
\83\89\83\8a\82È
\83p
\83X
\82Ì
\8eæ
\93¾
94 // *************************************************************************
95 function TemporaryFile : string;
97 tempPath : array [0..MAX_PATH] of char;
100 GetTempPath( SizeOf(tempPath), tempPath );
102 Result := tempPath + IntToStr( Random( $7fffffff ) );
103 until not FileExists( Result );
107 // *************************************************************************
108 //
\82Ü
\82¿BBS
\97p
\83\8d\83O
\83t
\83H
\83\8b\83_
\8eæ
\93¾
109 // *************************************************************************
110 function MyLogFolder : string;
116 if Length( folder ) = 0 then
119 Result := folder + LOG_DIR;
120 DisposeResultString(folder);
124 (*************************************************************************
125 *
\83f
\83B
\83\8c\83N
\83g
\83\8a\82ª
\91¶
\8dÝ
\82·
\82é
\82©
\83`
\83F
\83b
\83N
126 *************************************************************************)
127 function DirectoryExistsEx(const Name: string): Boolean;
131 Code := GetFileAttributes(PChar(Name));
132 Result := (Code <> -1) and (FILE_ATTRIBUTE_DIRECTORY and Code <> 0);
135 (*************************************************************************
136 *
\83f
\83B
\83\8c\83N
\83g
\83\8a\8dì
\90¬
\81i
\95¡
\90\94\8aK
\91w
\91Î
\89\9e\81j
137 *************************************************************************)
138 function ForceDirectoriesEx(Dir: string): Boolean;
141 if Length(Dir) = 0 then
142 raise Exception.Create('
\83t
\83H
\83\8b\83_
\82ª
\8dì
\90¬
\8fo
\97\88\82Ü
\82¹
\82ñ');
143 Dir := ExcludeTrailingPathDelimiter(Dir);
144 if (Length(Dir) < 3) or DirectoryExistsEx(Dir)
145 or (ExtractFilePath(Dir) = Dir) then Exit; // avoid 'xyz:\' problem.
146 Result := ForceDirectoriesEx(ExtractFilePath(Dir)) and CreateDir(Dir);
149 //
\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
150 procedure ExtractHttpFields(
151 const chrSep : TSysCharSet;
152 const chrWhite : TSysCharSet;
153 const strValue : string;
154 var strResult : TStringList;
155 unknownFlag : boolean = false
158 last, p, strLen : Integer;
161 strLen := Length( strValue );
168 if strValue[ p ] in chrSep then
170 strResult.Add( Copy( strValue, last, p - last ) );
179 strResult.Add( Copy( strValue, last, strLen - last + 1 ) );
183 \rfunction HttpEncode(
184 \r const strValue : string
192 kHexCode : array [0..15] of char = (
193 '0', '1', '2', '3', '4', '5', '6', '7',
194 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' );
197 strLen := Length( strValue );
203 case strValue[ i ] of
204 '0' .. '9', 'a' .. 'z', 'A' .. 'Z', '*', '-', '.', '@', '_':
206 strResult := strResult + strValue[ i ];
210 b := Integer( strValue[ i ] );
211 strResult := strResult + '%'
212 + kHexCode[ b div $10 ]
213 + kHexCode[ b mod $10 ];
227 // =========================================================================
229 // =========================================================================
231 // *************************************************************************
232 //
\83v
\83\89\83O
\83C
\83\93\82Ì
\83o
\81[
\83W
\83\87\83\93\82ð
\97v
\8b\81\82³
\82ê
\82½
233 // *************************************************************************
234 procedure OnVersionInfo(
235 var outAgent : PChar; //
\83o
\81[
\83W
\83\87\83\93\82ð
\88ê
\90Ø
\8aÜ
\82Ü
\82È
\82¢
\8f\83\90\88\82È
\96¼
\8fÌ
236 var outMajor : DWORD; //
\83\81\83W
\83\83\81[
\83o
\81[
\83W
\83\87\83\93
237 var outMinor : DWORD; //
\83}
\83C
\83i
\81[
\83o
\81[
\83W
\83\87\83\93
238 var outRelease : PChar; //
\83\8a\83\8a\81[
\83X
\92i
\8aK
\96¼
239 var outRevision : DWORD //
\83\8a\83r
\83W
\83\87\83\93\83i
\83\93\83o
\81[
244 outAgent := CreateResultString( PChar( PLUGIN_NAME ) );
245 outMajor := MAJOR_VERSION;
246 outMinor := MINOR_VERSION;
247 outRelease := CreateResultString( PChar( RELEASE_VERSION ) );
248 outRevision := REVISION_VERSION;
259 // *************************************************************************
260 //
\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©
261 // *************************************************************************
262 function OnAcceptURL(
263 inURL : PChar //
\94»
\92f
\82ð
\8bÂ
\82¢
\82Å
\82¢
\82é URL
264 ): TAcceptType; stdcall; // URL
\82Ì
\8eí
\97Þ
267 uriList : TStringList;
270 BBS_HOST = 'machi.to';
271 BBS_HOST2 = 'machibbs.com';
272 THREAD_MARK = '/bbs/read.pl';
273 THREAD_MARK2= '/bbs/read.cgi';
277 //
\83z
\83X
\83g
\96¼
\82ª machi.to
\82Å
\8fI
\82í
\82é
\8fê
\8d\87\82Í
\8eó
\82¯
\95t
\82¯
\82é
\82æ
\82¤
\82É
\82µ
\82Ä
\82¢
\82é
278 uri := TIdURI.Create( inURL );
279 uriList := TStringList.Create;
281 ExtractHttpFields( ['/'], [], uri.Path, uriList );
282 foundPos := AnsiPos( BBS_HOST, uri.Host );
283 if (foundPos > 0) and (Length( uri.Host ) - foundPos + 1 = Length( BBS_HOST )) then begin
284 foundPos := Pos( THREAD_MARK, inURL );
285 if (foundPos = 0) then begin
287 foundPos := Pos( THREAD_MARK2, inURL );
291 else if (uriList.Count > 1) and (uri.Path <> '/') then //
\8dÅ
\8cã
\82ª '/'
\82Å
\95Â
\82ß
\82ç
\82ê
\82Ä
\82é
\82È
\82ç 3
296 foundPos := AnsiPos( BBS_HOST2, uri.Host );
297 if (foundPos > 0) and (Length( uri.Host ) - foundPos + 1 = Length( BBS_HOST2 )) then begin
298 foundPos := Pos( THREAD_MARK, inURL );
299 if (foundPos = 0) then begin
301 foundPos := Pos( THREAD_MARK2, inURL );
305 else if (uriList.Count > 1) and (uri.Path <> '/') then //
\8dÅ
\8cã
\82ª '/'
\82Å
\95Â
\82ß
\82ç
\82ê
\82Ä
\82é
\82È
\82ç 3
311 Result := atNoAccept;
319 Result := atNoAccept;
324 // *************************************************************************
325 //
\8ew
\92è
\82µ
\82½ URL
\82ðBoard
\82ÌURL
\82É
\95Ï
\8a·
326 // *************************************************************************
327 procedure OnExtractBoardURL(
333 uriList : TStringList;
336 THREAD_MARK = '/bbs/read.pl';
337 THREAD_MARK2= '/bbs/read.cgi';
339 URL := string(inURL);
340 if AnsiPos(THREAD_MARK, URL) > 0 then begin
341 if Copy( inURL, Length( inURL ), 1 ) = '/' then
342 uri := TIdURI.Create( URL )
344 uri := TIdURI.Create( URL + '/' );
346 uriList := TStringList.Create;
350 Copy( uri.Params, AnsiPos( '?', uri.Params ) + 1, Length( uri.Params ) ),uriList );
351 // http://hokkaido.machi.to/bbs/read.pl?BBS=hokkaidou&KEY=1061764446
352 // http://hokkaido.machi.to/hokkaidou/
353 URL := uri.Protocol + '://' + uri.Host + '/' + uriList.Values[ 'BBS' ] + '/';
354 outURL := CreateResultString(URL);
359 end else if AnsiPos(THREAD_MARK2, URL) > 0 then begin
360 if Copy( inURL, Length( inURL ), 1 ) = '/' then
361 uri := TIdURI.Create( URL )
363 uri := TIdURI.Create( URL + '/' );
365 uriList := TStringList.Create;
367 // http://kanto.machi.to/bbs/read.cgi/kana/1215253035/l50
368 // http://kanto.machi.to/kana/
369 uriList.Delimiter := '/';
370 uriList.DelimitedText := uri.Path;
371 URL := uri.Protocol + '://' + uri.Host + '/';
372 if (uriList.Count >= 4) then begin
373 URL := URL + uriList[3] + '/';
375 outURL := CreateResultString(URL);
381 outURL := CreateResultString(URL);
387 // =========================================================================
388 // TMachiBBSThreadItem
389 // =========================================================================
391 // *************************************************************************
392 //
\83R
\83\93\83X
\83g
\83\89\83N
\83^
393 // *************************************************************************
394 constructor TMachiBBSThreadItem.Create(
399 uriList : TStringList;
405 OnDownload := Download;
409 OnGetHeader := GetHeader;
410 OnGetFooter := GetFooter;
411 OnGetBoardURL := GetBoardURL;
414 FIsTemporary := False;
416 URL := ReadURL + '&LAST=50';
418 uri := TIdURI.Create( URL );
419 uriList := TStringList.Create;
421 // http://hokkaido.machi.to/bbs/read.pl?BBS=hokkaidou&KEY=1061764446&LAST=50
424 Copy( uri.Params, AnsiPos( '?', uri.Params ) + 1, Length( uri.Params ) ), uriList );
425 FileName := uriList.Values[ 'KEY' ] + '.dat';
426 FilePath := MyLogFolder + uriList.Values[ 'BBS' ] + '\' + uriList.Values[ 'KEY' ] + '.dat';
427 IsLogFile := FileExists( FilePath );
435 // *************************************************************************
436 //
\83f
\83X
\83g
\83\89\83N
\83^
437 // *************************************************************************
438 destructor TMachiBBSThreadItem.Destroy;
443 //
\88ê
\8e\9e\83t
\83@
\83C
\83\8b\82Ì
\8fê
\8d\87\82Í
\8dí
\8f\9c\82·
\82é
445 DeleteFile( FilePath );
451 // *************************************************************************
452 //
\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½
453 // *************************************************************************
454 function TMachiBBSThreadItem.Download : TDownloadState;
458 downResult : TStringList;
459 content : TStringList;
460 responseCode : Longint;
461 logStream : TFileStream;
463 uriList : TStringList;
467 procedure downAndParse;
469 responseCode := InternalDownload( PChar( datURL ), modified, tmp, 0 );
472 if responseCode = 200 then begin
473 downResult := TStringList.Create;
475 downResult.Text := string( tmp );
477 //
\83^
\83C
\83g
\83\8b\82Ì
\8eæ
\93¾
478 foundPos := AnsiPos( '<title>', downResult.Text ) + Length( '<title>' );
482 AnsiPos( '</title>', downResult.Text ) - foundPos );
484 //
\83\8c\83X
\82Ì
\8aJ
\8en
\88Ê
\92u
485 foundPos := AnsiPos( '<dt', downResult.Text );
486 downResult.Text := Copy( downResult.Text, foundPos, Length( downResult.Text ) );
487 if foundPos > 0 then begin
488 //
\83\8c\83X
\82Ì
\8fI
\97¹
\88Ê
\92u
489 foundPos := AnsiPos( '<table', downResult.Text ) - 1;
491 downResult.Text := Copy( downResult.Text, 1, foundPos );
492 //
\82Ü
\82¿BBS
\82Í dat
\92¼
\93Ç
\82Ý
\82ª
\8fo
\97\88\82È
\82¢
\82µ
\81Acgi
\88È
\8aO
\82É
\8d·
\95ª
\93Ç
\82Ý
\8d\9e\82Ý
\82Ì
\95û
\96@
\82ª
\82 \82é
\82í
\82¯
\82Å
\82à
\96³
\82¢
\82Ì
\82Å
493 //
\91f
\82Ì
\82Ü
\82Ü
\82ð
\96³
\97\9d\82É
\95Û
\82Æ
\82¤
\82Æ
\82Í
\82¹
\82¸
\82É 2ch
\82Ì dat
\8c`
\8e®
\82É
\95Ï
\8a·
\82µ
\82½
\82à
\82Ì
\82ð
\95Û
\91¶
\82µ
\82Ä
\82µ
\82Ü
\82¤
494 To2chDat( downResult, Count + 1 );
495 content.Text := content.Text + downResult.Text;
501 Result := dsNotModify;
505 DisposeResultString( tmp );
512 uri := TIdURI.Create( URL );
513 uriList := TStringList.Create;
514 content := TStringList.Create;
518 Copy( uri.Params, AnsiPos( '?', uri.Params ) + 1, Length( uri.Params ) ), uriList );
519 FileName := uriList.Values[ 'KEY' ] + '.dat';
520 if MyLogFolder = '' then begin
521 //
\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¶
522 FilePath := TemporaryFile;
523 FIsTemporary := True;
525 FilePath := MyLogFolder + uriList.Values[ 'BBS' ] + '\' + uriList.Values[ 'KEY' ] + '.dat';
526 FIsTemporary := False;
529 //
\95Û
\91¶
\97p
\82Ì
\83f
\83B
\83\8c\83N
\83g
\83\8a\82ð
\8c@
\82é
530 ForceDirectoriesEx( Copy( FilePath, 1, LastDelimiter( '\', FilePath ) ) );
532 //
\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Í
533 // InternalDownload
\82É
\94C
\82¹
\82é
\82±
\82Æ
\82ª
\8fo
\97\88\82é
534 modified := LastModified;
538 uri.Protocol + '://' + uri.Host + '/bbs/read.cgi?' +
539 'BBS=' + uriList.Values[ 'BBS' ] + '&KEY=' + uriList.Values[ 'KEY' ] +
540 '&START=' + IntToStr( 1 )
542 //
\90V
\92\85\82Ì
\82Ý
544 uri.Protocol + '://' + uri.Host + '/bbs/read.cgi?' +
545 'BBS=' + uriList.Values[ 'BBS' ] + '&KEY=' + uriList.Values[ 'KEY' ] +
546 '&START=' + IntToStr( Count + 1 ) + '&NOFIRST=TRUE';
547 //
\83_
\83E
\83\93\83\8d\81[
\83h
550 if content.Count > 0 then begin
551 if Count <= 0 then begin
552 Result := dsComplete;
553 //
\90V
\8bK
\8f\91\82«
\8d\9e\82Ý
554 content[ 0 ] := content[ 0 ] + Title;
555 logStream := TFileStream.Create( FilePath, fmCreate or fmShareDenyWrite );
557 logStream.Position := logStream.Size;
558 logStream.Write( PChar( content.Text )^, Length( content.Text ) );
563 Count := content.Count;
565 if (content.Count > 1) or (Trim(content.Text) <> '') then begin
566 Result := dsDiffComplete;
568 logStream := TFileStream.Create( FilePath, fmOpenReadWrite or fmShareDenyWrite );
570 logStream.Position := logStream.Size;
571 logStream.Write( PChar( content.Text )^, Length( content.Text ) );
575 NewReceive := Count + 1;
576 Count := Count + content.Count;
578 Result := dsNotModify;
581 if (Result <> dsNotModify) then begin
582 // CGI
\82©
\82ç
\82Í
\90³
\82µ
\82¢
\93ú
\95t
\82ª
\93¾
\82ç
\82ê
\82È
\82¢
\82Ì
\82Å
\8c»
\8dÝ
\82É
\90Ý
\92è
584 NewResCount := content.Count;
587 Result := dsNotModify;
597 // *************************************************************************
598 //
\8f\91\82«
\8d\9e\82Ý
\82ð
\8ew
\8e¦
\82³
\82ê
\82½
599 // *************************************************************************
600 function TMachiBBSThreadItem.Write(
601 inName : string; //
\96¼
\91O(
\83n
\83\93\83h
\83\8b)
602 inMail : string; //
\83\81\81[
\83\8b\83A
\83h
\83\8c\83X
603 inMessage : string //
\96{
\95¶
604 ) : TDownloadState; //
\8f\91\82«
\8d\9e\82Ý
\82ª
\90¬
\8c÷
\82µ
\82½
\82©
\82Ç
\82¤
\82©
610 uriList : TStringList;
613 uri := TIdURI.Create( URL );
614 uriList := TStringList.Create;
618 Copy( uri.Params, AnsiPos( '?', uri.Params ) + 1, Length( uri.Params ) ), uriList );
620 postURL := uri.Protocol + '://' + uri.Host + '/bbs/write.cgi';
622 'NAME=' + HttpEncode( inName ) +
623 '&MAIL=' + HttpEncode( inMail ) +
624 '&MESSAGE=' + HttpEncode( inMessage ) +
625 '&BBS=' + uriList.Values[ 'BBS' ] +
626 '&KEY=' + uriList.Values[ 'KEY' ] +
627 '&TIME=' + IntToStr( DateTimeToUnix( Now ) ) +
628 '&submit=' + HttpEncode( '
\8f\91\82«
\8d\9e\82Þ' );
630 //
\93Æ
\8e©
\82É
\92Ê
\90M
\82µ
\82È
\82¢
\8fê
\8d\87\82Í InternalPost
\82É
\94C
\82¹
\82é
\82±
\82Æ
\82ª
\8fo
\97\88\82é
631 InternalPost( PChar( postURL ), PChar( postData ),PChar(URL), postResult );
632 DisposeResultString( postResult );
642 // *************************************************************************
643 //
\83\8c\83X
\94Ô
\8d\86 inNo
\82É
\91Î
\82·
\82é html
\82ð
\97v
\8b\81\82³
\82ê
\82½
644 // *************************************************************************
645 function TMachiBBSThreadItem.GetRes(
646 inNo : Integer //
\97v
\8b\81\82³
\82ê
\82½
\83\8c\83X
\94Ô
\8d\86
647 ) : string; //
\91Î
\89\9e\82·
\82é HTML
653 //
\93Æ
\8e©
\82É
\83t
\83B
\83\8b\83^
\83\8a\83\93\83O
\82ð
\8ds
\82í
\82È
\82¢
\8fê
\8d\87\82Í
654 // InternalAbon
\82¨
\82æ
\82Ñ Dat2HTML
\82É
\94C
\82¹
\82é
\82±
\82Æ
\82ª
\8fo
\97\88\82é
656 if (FDat = nil) or (inNo - 1 < 0 ) or (inNo - 1 >= FDat.Count) then begin
657 //
\83\8d\83O
\82É
\91¶
\8dÝ
\82µ
\82È
\82¢
\82Ì
\82Å
\82±
\82Ì
\82Ü
\82Ü
\8fI
\97¹
661 res := FDat[ inNo - 1 ];
662 tmp := InternalAbonForOne( PChar( res ), PChar(FilePath), inNo);
664 Result := Dat2HTML( string( tmp ), inNo );
666 DisposeResultString( tmp );
671 // *************************************************************************
672 //
\83\8c\83X
\94Ô
\8d\86 inNo
\82É
\91Î
\82·
\82é Dat
\82ð
\97v
\8b\81\82³
\82ê
\82½
673 // *************************************************************************
674 function TMachiBBSThreadItem.GetDat(
675 inNo : Integer //
\97v
\8b\81\82³
\82ê
\82½
\83\8c\83X
\94Ô
\8d\86
676 ) : string; //
\82Q
\82¿
\82á
\82ñ
\82Ë
\82é
\82ÌDat
\8c`
\8e®
682 //
\93Æ
\8e©
\82É
\83t
\83B
\83\8b\83^
\83\8a\83\93\83O
\82ð
\8ds
\82í
\82È
\82¢
\8fê
\8d\87\82Í
684 if (FDat = nil) or (inNo - 1 < 0 ) or (inNo - 1 >= FDat.Count) then begin
685 //
\83\8d\83O
\82É
\91¶
\8dÝ
\82µ
\82È
\82¢
\82Ì
\82Å
\82±
\82Ì
\82Ü
\82Ü
\8fI
\97¹
686 tmp := CreateResultString('');
688 DisposeResultString(tmp);
691 tmp := CreateResultString(FDat[ inNo - 1]);
693 Result := string(tmp);
695 DisposeResultString(tmp);
700 // *************************************************************************
701 //
\83X
\83\8c\83b
\83h
\82Ì
\83w
\83b
\83_ html
\82ð
\97v
\8b\81\82³
\82ê
\82½
702 // *************************************************************************
703 function TMachiBBSThreadItem.GetHeader(
704 inOptionalHeader : string
708 //
\93Æ
\8e©
\82É
\83t
\83B
\83\8b\83^
\83\8a\83\93\83O
\82ð
\8ds
\82í
\82È
\82¢
\8fê
\8d\87\82Í
709 // InternalHeader
\82É
\94C
\82¹
\82é
\82±
\82Æ
\82ª
\8fo
\97\88\82é
710 Result := InternalHeader(
711 '<meta http-equiv="Content-type" content="text/html; charset=Shift_JIS">' +
715 // GetRes
\82ð
\8cÄ
\82Î
\82ê
\82é
\82±
\82Æ
\82ª
\97\
\91z
\82³
\82ê
\82é
\82Ì
\82Å FDat
\82ð
\90¶
\90¬
\82µ
\82Ä
\82¨
\82
724 // *************************************************************************
725 //
\83X
\83\8c\83b
\83h
\82Ì
\83t
\83b
\83^ html
\82ð
\97v
\8b\81\82³
\82ê
\82½
726 // *************************************************************************
727 function TMachiBBSThreadItem.GetFooter(
728 inOptionalFooter : string
732 //
\93Æ
\8e©
\82É
\83t
\83B
\83\8b\83^
\83\8a\83\93\83O
\82ð
\8ds
\82í
\82È
\82¢
\8fê
\8d\87\82Í
733 // InternalFooter
\82É
\94C
\82¹
\82é
\82±
\82Æ
\82ª
\8fo
\97\88\82é
734 Result := InternalFooter( inOptionalFooter );
736 //
\82à
\82¤ GetRes
\82Í
\8cÄ
\82Î
\82ê
\82È
\82¢
\82Æ
\8ev
\82¤
\82Ì
\82Å FDat
\82ð
\8aJ
\95ú
\82µ
\82Ä
\82¨
\82
744 // *************************************************************************
745 //
\82±
\82Ì ThreadItem
\82ª
\91®
\82·
\82é
\94Â
\82Ì URL
\82ð
\97v
\8b\81\82³
\82ê
\82½
746 // *************************************************************************
747 function TMachiBBSThreadItem.GetBoardURL : string;
750 uriList : TStringList;
754 if Copy( URL, Length( URL ), 1 ) = '/' then
755 uri := TIdURI.Create( URL )
757 uri := TIdURI.Create( URL + '/' );
758 uriList := TStringList.Create;
762 Copy( uri.Params, AnsiPos( '?', uri.Params ) + 1, Length( uri.Params ) ), uriList );
763 FileName := uriList.Values[ 'KEY' ] + '.dat';
764 // http://hokkaido.machi.to/bbs/read.pl?BBS=hokkaidou&KEY=1061764446
765 // http://hokkaido.machi.to/hokkaidou/
766 tmp := CreateResultString(
767 uri.Protocol + '://' + uri.Host + '/' + uriList.Values[ 'BBS' ] + '/' );
768 Result := string(tmp);
770 DisposeResultString(tmp);
777 // *************************************************************************
778 //
\82Ü
\82¿BBS
\82Ì HTML
\82ð 2ch
\82Ì dat
\8c`
\8e®
\82É
779 // *************************************************************************
780 procedure TMachiBBSThreadItem.To2chDat(
781 ioHTML : TStringList;
782 inStartNo : Integer = 1
786 foundPos,foundPos2 : Integer;
791 MAIL_TAG = '<a href="mailto:';
794 //===== 2ch
\82Ì dat
\8c`
\8e®
\82É
\95Ï
\8a·
795 //
\83z
\83X
\83g
\96¼
\82Ì
\8cã
\82Å
\89ü
\8ds
\82³
\82ê
\82Ä
\82¢
\82½
\82è
\82·
\82é
\82Ì
\82Å
\89ü
\8ds
\82ð
\82·
\82×
\82Ä
\8eæ
\82è
\8f\9c\82
796 ioHTML.Text := CustomStringReplace( ioHTML.Text, #13#10, '');
797 //StringReplace( ioHTML.Text, #13#10, '', [rfReplaceAll] );
798 //
\91ã
\82í
\82è
\82É <dt>
\82ð
\8ds
\82Ì
\8bæ
\90Ø
\82è
\82É
\82·
\82é
799 ioHTML.Text := CustomStringReplace( ioHTML.Text, '<dt>', #10 );
800 //StringReplace( ioHTML.Text, '<dt>', #10, [rfReplaceAll] );
801 // <dt>
\82©
\82ç
\8en
\82Ü
\82Á
\82Ä
\82¢
\82é
\82Ì
\82Å
\8dÅ
\8f\89\82Í
\8bó
\82Ì
\82Í
\82¸
802 if Length( ioHTML[ 0 ] ) = 0 then
805 //
\8cy
\82
\82 \82Ú
\81[
\82ñ
\83`
\83F
\83b
\83N
806 //
\81¦
\91å
\8eG
\94c
\82¾
\82©
\82ç
\82¿
\82á
\82ñ
\82Æ
\8fo
\97\88\82Ä
\82È
\82¢
\82©
\82à
809 while i < ioHTML.Count do begin
810 foundPos := AnsiPos( ' ', ioHTML[ i ] );
811 if foundPos > 0 then begin
812 no := StrToInt( Copy( ioHTML[ i ], 1, foundPos - 1 ) );
813 if inStartNo < no then
814 ioHTML.Insert( i, '<><><><>' );
820 //
\82 \82Ú
\81[
\82ñ
\83`
\83F
\83b
\83N
\82Å
\96â
\91è
\82ª
\94
\90¶
\82µ
\82Ä
\82à
\90æ
\82Ö
\90i
\82ß
\82½
\82¢
\82Ì
\82Å
824 //
\83g
\83\8a\83b
\83v
\82Ì
\8cã
\82Ì '<b> </b>'
\82ð
\8bó
\82É
825 if AnsiPos('
\81\9f</b>', ioHTML.Text) <> 0 then begin
826 ioHTML.Text := CustomStringReplace( ioHTML.Text, '<b> </b></font>', '</b></font>', true );
827 ioHTML.Text := CustomStringReplace( ioHTML.Text, '<b> </B></a>', '</b></a>', true );
829 //ioHTML.Text := CustomStringReplace( ioHTML.Text, '<b> </b>', '', true );
830 //StringReplace( ioHTML.Text, '<b> </b>', '', [rfReplaceAll, rfIgnoreCase] );
831 // '<b>'
\82Í
\83\81\81[
\83\8b\82Æ
\96¼
\91O
\82Ì
\8bæ
\90Ø
\82è
832 ioHTML.Text := CustomStringReplace( ioHTML.Text, '<b>', '<>', true );
833 //StringReplace( ioHTML.Text, '<b>', '<>', [rfReplaceAll, rfIgnoreCase] );
834 //
\83\81\81[
\83\8b\82Æ
\96¼
\91O
\82É
\82Â
\82¢
\82Ä
\82
\82é
\95Â
\82¶
\83^
\83O
\82ð
\93\8a\8de
\93ú
\82Æ
\82Ì
\8bæ
\90Ø
\82è
\82É
835 ioHTML.Text := CustomStringReplace( ioHTML.Text, '</b></a>', '<>', true );
836 //StringReplace( ioHTML.Text, '</b></a>', '<>', [rfReplaceAll, rfIgnoreCase] );
837 ioHTML.Text := CustomStringReplace( ioHTML.Text, '</b>', '<>', true );
838 ioHTML.Text := CustomStringReplace( ioHTML.Text, '
\81\9f<>', '
\81\9f</b>', true );
839 //StringReplace( ioHTML.Text, '</b>', '<>', [rfReplaceAll, rfIgnoreCase] );
840 // '<dd>'
\82ð
\96{
\95¶
\82Æ
\82Ì
\8bæ
\90Ø
\82è
\82É
841 ioHTML.Text := CustomStringReplace( ioHTML.Text, '<dd>', '<>', true );
842 //StringReplace( ioHTML.Text, '<dd>', '<>', [rfReplaceAll, rfIgnoreCase] );
844 res := TStringList.Create;
846 bound := ioHTML.Count - 1;
847 for i := 0 to bound do begin
848 //
\83X
\83N
\83\8a\83v
\83g
\82ª
\8aÜ
\82Ü
\82ê
\82Ä
\82¢
\82½
\82ç
\8dí
\8f\9c\82·
\82é
\81i
\8dL
\8d\90\91Î
\8dô
\81j
849 res.Text := CustomStringReplace( ioHTML[ i ], '<>', #10 );
850 //StringReplace( ioHTML[ i ], '<>', #10, [rfReplaceAll] );
851 if res.Count >= 3 then begin // 3
\96¢
\96\9e\82Í
\82 \82è
\82¦
\82È
\82¢
\82Æ
\8ev
\82¤
\82¯
\82Ç
\88À
\91S
\82Ì
\82½
\82ß
852 foundPos := AnsiPos( MAIL_TAG, res[ 0 ] );
853 if foundPos > 0 then begin
854 //
\83\81\81[
\83\8b\83A
\83h
\83\8c\83X
\82ð
\94²
\82«
\8fo
\82·
855 foundPos := foundPos + Length( MAIL_TAG );
856 res[ 0 ] := Copy( res[ 0 ], foundPos, Length( res[ 0 ] ) );
857 strTmp := Copy( res[ 0 ], 1, AnsiPos( '">', res[ 0 ] ) - 1 );
858 //
\83\81\81[
\83\8b\82Æ
\96¼
\91O
\82ª
\8bt
\82È
\82Ì
\82Å
\82Ð
\82Á
\82
\82è
\95Ô
\82µ
\82Ä
\96ß
\82·
859 res[ 0 ] := res[ 1 ];
862 //
\83\81\81[
\83\8b\82Æ
\96¼
\91O
\82ª
\8bt
\82È
\82Ì
\82Å
\82Ð
\82Á
\82
\82è
\95Ô
\82·
863 res[ 0 ] := res[ 1 ];
866 res[ 2 ] := StringReplace( res[ 2 ], '[', 'IP:', [] );
867 res[ 2 ] := StringReplace( res[ 2 ], ']', '', [] );
869 if AnsiPos('</font>
\93\8a\8de
\93ú
\81F', res[ 2 ]) = 1 then begin
870 res[ 2 ] := StringReplace( res[ 2 ], '</font>
\93\8a\8de
\93ú
\81F', '', [] );
871 end else if AnsiPos('
\93\8a\8de
\93ú
\81F', res[ 2 ]) = 1 then begin
872 res[ 2 ] := StringReplace( res[ 2 ], '
\93\8a\8de
\93ú
\81F', '', [] );
875 ioHTML[ i ] := CustomStringReplace( res.Text, #13#10, '<>');
876 //
\8dL
\8d\90\83X
\83N
\83\8a\83v
\83g
\91Î
\8dô
877 foundPos := Pos( '<script', ioHTML[ i ] );
878 if foundPos > 0 then begin
879 foundPos2 := Pos( '</script>', ioHTML[ i ] );
880 if (foundPos2 > foundPos) then begin
881 ioHTML[ i ] := Copy(ioHTML[ i ], 1, foundPos-1) +
882 Copy(ioHTML[ i ], foundPos2 + 9, Length(ioHTML[ i ]));
892 // *************************************************************************
894 // *************************************************************************
895 procedure TMachiBBSThreadItem.LoadDat;
898 if FDat = nil then begin
899 if IsLogFile then begin
900 // dat
\82Ì
\93Ç
\82Ý
\8d\9e\82Ý
901 FDat := TStringList.Create;
902 FDat.LoadFromFile( FilePath );
908 // *************************************************************************
910 // *************************************************************************
911 procedure TMachiBBSThreadItem.FreeDat;
914 if FDat <> nil then begin
921 // *************************************************************************
922 //
\88À
\91S
\82È( '/'
\82Å
\8fI
\82í
\82é )
\93Ç
\82Ý
\8d\9e\82Ý
\82Ì URL
923 // *************************************************************************
924 function TMachiBBSThreadItem.ReadURL : string;
927 uriList : TStringList;
930 THREAD_MARK2= '/bbs/read.cgi';
933 foundPos := AnsiPos( '?', URL );
934 if foundPos > 0 then begin
935 uri := TIdURI.Create( URL );
936 uriList := TStringList.Create;
938 ExtractHttpFields( ['&'], [], Copy( URL, foundPos + 1, MaxInt ), uriList );
940 uri.Protocol + '://' + uri.Host + '/bbs/read.pl?' +
941 'BBS=' + uriList.Values[ 'BBS' ] + '&KEY=' + uriList.Values[ 'KEY' ];
948 foundPos := AnsiPos(THREAD_MARK2, URL);
949 if (foundPos > 0) then begin
950 uri := TIdURI.Create( URL );
951 uriList := TStringList.Create;
953 uriList.Delimiter := '/';
954 uriList.DelimitedText := uri.Path;
955 if (uriList.Count >= 5) then begin
957 uri.Protocol + '://' + uri.Host + '/bbs/read.pl?' +
958 'BBS=' + uriList[3] + '&KEY=' + uriList[4];
969 // *************************************************************************
970 // TThreadItem
\82ª
\90¶
\90¬
\82³
\82ê
\82½
\8fê
\8d\87\82Ì
\8f\88\92u(TMachiBBSThreadItem
\82ð
\90¶
\90¬
\82·
\82é)
971 // *************************************************************************
972 procedure ThreadItemOnCreateOfTMachiBBSThreadItem(
976 threadItem : TMachiBBSThreadItem;
979 threadItem := TMachiBBSThreadItem.Create( inInstance );
980 ThreadItemSetLong( inInstance, tipContext, DWORD( threadItem ) );
984 // *************************************************************************
985 // TThreadItem
\82ª
\94j
\8aü
\82³
\82ê
\82½
\8fê
\8d\87\82Ì
\8f\88\92u(TMachiBBSThreadItem
\82ð
\94j
\8aü
\82·
\82é)
986 // *************************************************************************
987 procedure ThreadItemOnDisposeOfTMachiBBSThreadItem(
991 threadItem : TMachiBBSThreadItem;
994 threadItem := TMachiBBSThreadItem( ThreadItemGetLong( inInstance, tipContext ) );
999 // =========================================================================
1000 // TMachiBBSBoardItem
1001 // =========================================================================
1003 // *************************************************************************
1004 //
\83R
\83\93\83X
\83g
\83\89\83N
\83^
1005 // *************************************************************************
1006 constructor TMachiBBSBoardItem.Create(
1011 uriList : TStringList;
1016 OnDownload := Download;
1017 OnCreateThread := CreateThread;
1018 OnEnumThread := EnumThread;
1019 OnFileName2ThreadURL := ToThreadURL;
1022 FIsTemporary := False;
1026 uri := TIdURI.Create( SubjectURL );
1027 uriList := TStringList.Create;
1029 ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
1030 // http://hokkaido.machi.to/hokkaidou/subject.txt
1031 FilePath := MyLogFolder + uriList[ 1 ] + '\' + uri.Document;
1032 IsLogFile := FileExists( FilePath );
1040 // *************************************************************************
1041 //
\83f
\83X
\83g
\83\89\83N
\83^
1042 // *************************************************************************
1043 destructor TMachiBBSBoardItem.Destroy;
1046 if FDat <> nil then begin
1054 //
\88ê
\8e\9e\83t
\83@
\83C
\83\8b\82Ì
\8fê
\8d\87\82Í
\8dí
\8f\9c\82·
\82é
1055 if FIsTemporary then
1056 DeleteFile( FilePath );
1062 // *************************************************************************
1063 //
\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½
1064 // *************************************************************************
1065 function TMachiBBSBoardItem.Download : TDownloadState;
1069 responseCode : Longint;
1071 uriList : TStringList;
1076 if FDat <> nil then begin
1083 FDat := TStringList.Create;
1084 uri := TIdURI.Create( SubjectURL );
1085 uriList := TStringList.Create;
1086 //
\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Í
1087 // InternalDownload
\82É
\94C
\82¹
\82é
\82±
\82Æ
\82ª
\8fo
\97\88\82é
1088 modified := LastModified;
1089 responseCode := InternalDownload( PChar( uri.URI ), modified, downResult );
1091 if responseCode = 200 then begin
1093 //
\83p
\83X
\82ð
\8eZ
\8fo
1094 ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
1095 if MyLogFolder = '' then begin
1096 //
\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¶
1097 FilePath := TemporaryFile;
1098 FIsTemporary := True;
1100 FilePath := MyLogFolder + uriList[ 1 ] + '\' + uri.Document;
1101 FIsTemporary := False
1104 //
\95Û
\91¶
\97p
\82Ì
\83f
\83B
\83\8c\83N
\83g
\83\8a\82ð
\8c@
\82é
1105 ForceDirectoriesEx( Copy( FilePath, 1, LastDelimiter( '\', FilePath ) ) );
1107 FDat.Text := string( downResult );
1109 FDat.SaveToFile( FilePath );
1113 LastModified := modified;
1119 Result := dsComplete;
1122 DisposeResultString( downResult );
1127 // *************************************************************************
1128 //
\83X
\83\8c\97§
\82Ä
\82ð
\8ew
\8e¦
\82³
\82ê
\82½
1129 // *************************************************************************
1130 function TMachiBBSBoardItem.CreateThread(
1131 inSubject : string; //
\83X
\83\8c\83^
\83C
1132 inName : string; //
\96¼
\91O(
\83n
\83\93\83h
\83\8b)
1133 inMail : string; //
\83\81\81[
\83\8b\83A
\83h
\83\8c\83X
1134 inMessage : string //
\96{
\95¶
1135 ) : TDownloadState; //
\8f\91\82«
\8d\9e\82Ý
\82ª
\90¬
\8c÷
\82µ
\82½
\82©
\82Ç
\82¤
\82©
1141 uriList : TStringList;
1144 uri := TIdURI.Create( URL );
1145 uriList := TStringList.Create;
1149 Copy( uri.Params, AnsiPos( '?', uri.Params ) + 1, Length( uri.Params ) ), uriList );
1151 postURL := uri.Protocol + '://' + uri.Host + '/bbs/write.cgi';
1153 'SUBJECT=' + HttpEncode( inSubject ) +
1154 '&NAME=' + HttpEncode( inName ) +
1155 '&MAIL=' + HttpEncode( inMail ) +
1156 '&MESSAGE=' + HttpEncode( inMessage ) +
1157 '&BBS=' + uriList[ 1 ] +
1158 '&TIME=' + IntToStr( DateTimeToUnix( Now ) ) +
1159 '&submit=' + HttpEncode( '
\90V
\8bK
\8f\91\82«
\8d\9e\82Ý' );
1161 //
\93Æ
\8e©
\82É
\92Ê
\90M
\82µ
\82È
\82¢
\8fê
\8d\87\82Í InternalPost
\82É
\94C
\82¹
\82é
\82±
\82Æ
\82ª
\8fo
\97\88\82é
1162 InternalPost( PChar( postURL ), PChar( postData ),PChar(URL), postResult );
1163 DisposeResultString( postResult );
1165 Result := dsComplete
1173 // *************************************************************************
1174 //
\83X
\83\8c\88ê
\97\97\82Ì URL
\82©
\82ç
\83X
\83\8c\83b
\83h
\82Ì URL
\82ð
\93±
\82«
\8fo
\82·
1175 // *************************************************************************
1176 function TMachiBBSBoardItem.ToThreadURL(
1177 inFileName : string //
\83X
\83\8c\83b
\83h
\83t
\83@
\83C
\83\8b\96¼
1178 ) : string; //
\83X
\83\8c\83b
\83h
\82Ì URL
1182 uriList : TStringList;
1186 found := AnsiPos( '.', inFileName );
1188 inFileName := Copy( inFileName, 1, found - 1 );
1190 uri := TIdURI.Create( SubjectURL );
1191 uriList := TStringList.Create;
1194 // http://hokkaido.machi.to/hokkaidou/
1195 // http://hokkaido.machi.to/bbs/read.pl?BBS=hokkaidou&KEY=1061764446&LAST=50
1196 ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
1197 threadURL := uri.Protocol + '://' + uri.Host + '/bbs/read.pl?' +
1198 'BBS=' + uriList[ 1 ] + '&KEY=' + inFileName + '&LAST=50';
1199 Result := threadURL;
1210 // *************************************************************************
1211 //
\82±
\82Ì
\94Â
\82É
\82¢
\82
\82Â
\82Ì
\83X
\83\8c\82ª
\82 \82é
\82©
\97v
\8b\81\82³
\82ê
\82½
1212 // *************************************************************************
1213 procedure TMachiBBSBoardItem.EnumThread(
1214 inCallBack : TBoardItemEnumThreadCallBack
1218 uriList : TStringList;
1222 if FDat = nil then begin
1223 FDat := TStringList.Create;
1225 uri := TIdURI.Create( SubjectURL );
1226 uriList := TStringList.Create;
1228 //
\83p
\83X
\82ð
\8eZ
\8fo
1229 ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
1230 // http://hokkaido.machi.to/hokkaidou/subject.txt
1231 FilePath := MyLogFolder + uriList[ 1 ] + '\' + uri.Document;
1232 if FileExists( FilePath ) then
1233 //
\93Ç
\82Ý
\8d\9e\82Ý
1234 FDat.LoadFromFile( FilePath );
1241 //
\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é
1242 inherited EnumThread( inCallBack, CustomStringReplace( FDat.Text, ',', '<>' ) );
1248 // *************************************************************************
1249 //
\83X
\83\8c\88ê
\97\97\82Ì URL
\82ð
\8b\81\82ß
\82é
1250 // *************************************************************************
1251 function TMachiBBSBoardItem.SubjectURL : string;
1254 uriList : TStringList;
1257 uri := TIdURI.Create( URL );
1258 uriList := TStringList.Create;
1260 if uri.Document <> SUBJECT_NAME then begin
1261 if Copy( URL, Length( URL ), 1 ) = '/' then
1262 Result := URL + SUBJECT_NAME
1264 Result := URL + '/' + SUBJECT_NAME;
1266 //
\82±
\82±
\82É
\82Í
\97\88\82È
\82¢
\82Æ
\8ev
\82¤
\82¯
\82Ç
1276 // *************************************************************************
1277 // TBoardItem
\82ª
\90¶
\90¬
\82³
\82ê
\82½
\8fê
\8d\87\82Ì
\8f\88\92u(TMachiBBSBoardItem
\82ð
\90¶
\90¬
\82·
\82é)
1278 // *************************************************************************
1279 procedure BoardItemOnCreateOfTMachiBBSBoardItem(
1283 boardItem : TMachiBBSBoardItem;
1286 boardItem := TMachiBBSBoardItem.Create( inInstance );
1287 BoardItemSetLong( inInstance, bipContext, DWORD( boardItem ) );
1291 // *************************************************************************
1292 // TBoardItem
\82ª
\94j
\8aü
\82³
\82ê
\82½
\8fê
\8d\87\82Ì
\8f\88\92u(TMachiBBSBoardItem
\82ð
\94j
\8aü
\82·
\82é)
1293 // *************************************************************************
1294 procedure BoardItemOnDisposeOfTMachiBBSBoardItem(
1298 boardItem : TMachiBBSBoardItem;
1301 boardItem := TMachiBBSBoardItem( BoardItemGetLong( inInstance, bipContext ) );
1308 // =========================================================================
1309 //
\83G
\83\93\83g
\83\8a\83|
\83C
\83\93\83g
1310 // =========================================================================
1312 ul_reason_for_call : DWORD
1318 case ul_reason_for_call of
1323 module := GetModuleHandle( nil );
1325 LoadInternalAPI( module );
1326 LoadInternalFilePathAPI( module );
1327 LoadInternalThreadItemAPI( module );
1328 LoadInternalBoardItemAPI( module );
1330 // =====
\83C
\83\93\83X
\83^
\83\93\83X
\82Ì
\8eæ
\82è
\88µ
\82¢
\82ð TThreadItem
\82©
\82ç TMachiBBSThreadItem
\82É
\95Ï
\8dX
\82·
\82é
1331 ThreadItemOnCreate := ThreadItemOnCreateOfTMachiBBSThreadItem;
1332 ThreadItemOnDispose := ThreadItemOnDisposeOfTMachiBBSThreadItem;
1333 // =====
\83C
\83\93\83X
\83^
\83\93\83X
\82Ì
\8eæ
\82è
\88µ
\82¢
\82ð TBoardItem
\82©
\82ç TMachiBBSBoardItem
\82É
\95Ï
\8dX
\82·
\82é
1334 BoardItemOnCreate := BoardItemOnCreateOfTMachiBBSBoardItem;
1335 BoardItemOnDispose := BoardItemOnDisposeOfTMachiBBSBoardItem;
1354 DllProc := @DLLEntry;
1355 DLLEntry( DLL_PROCESS_ATTACH );