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 );
42 procedure To2chDat2( var ioDat: TStringList );
45 function ReadURL : string;
46 //property FilePath : string read FFilePath;
49 // =========================================================================
51 // =========================================================================
52 TMachiBBSBoardItem = class(TBoardItem)
54 FIsTemporary : Boolean;
58 constructor Create( inInstance : DWORD );
59 destructor Destroy; override;
62 function Download : TDownloadState;
63 function CreateThread( inSubject : string; inName : string; inMail : string; inMessage : string ) : TDownloadState;
64 function ToThreadURL( inFileName : string ) : string;
65 procedure EnumThread( inCallBack : TBoardItemEnumThreadCallBack );
67 function SubjectURL : string;
68 function SubjectURL2 : string;
69 procedure ChangeSubjectFormat(var dat: TStringList);
72 // =========================================================================
73 //
\83T
\83u
\83W
\83F
\83N
\83g
\83\8c\83R
\81[
\83h
74 // =========================================================================
82 LOG_DIR = 'MachiBBS\';
83 SUBJECT_NAME = 'subject.txt';
85 PLUGIN_NAME = 'MachiBBSPlugIn';
88 RELEASE_VERSION = 'beta';
89 REVISION_VERSION = 25;
91 // =========================================================================
93 // =========================================================================
95 // *************************************************************************
96 //
\83e
\83\93\83|
\83\89\83\8a\82È
\83p
\83X
\82Ì
\8eæ
\93¾
97 // *************************************************************************
98 function TemporaryFile : string;
100 tempPath : array [0..MAX_PATH] of char;
103 GetTempPath( SizeOf(tempPath), tempPath );
105 Result := tempPath + IntToStr( Random( $7fffffff ) );
106 until not FileExists( Result );
110 // *************************************************************************
111 //
\82Ü
\82¿BBS
\97p
\83\8d\83O
\83t
\83H
\83\8b\83_
\8eæ
\93¾
112 // *************************************************************************
113 function MyLogFolder : string;
119 if Length( folder ) = 0 then
122 Result := folder + LOG_DIR;
123 DisposeResultString(folder);
127 (*************************************************************************
128 *
\83f
\83B
\83\8c\83N
\83g
\83\8a\82ª
\91¶
\8dÝ
\82·
\82é
\82©
\83`
\83F
\83b
\83N
129 *************************************************************************)
130 function DirectoryExistsEx(const Name: string): Boolean;
134 Code := GetFileAttributes(PChar(Name));
135 Result := (Code <> -1) and (FILE_ATTRIBUTE_DIRECTORY and Code <> 0);
138 (*************************************************************************
139 *
\83f
\83B
\83\8c\83N
\83g
\83\8a\8dì
\90¬
\81i
\95¡
\90\94\8aK
\91w
\91Î
\89\9e\81j
140 *************************************************************************)
141 function ForceDirectoriesEx(Dir: string): Boolean;
144 if Length(Dir) = 0 then
145 raise Exception.Create('
\83t
\83H
\83\8b\83_
\82ª
\8dì
\90¬
\8fo
\97\88\82Ü
\82¹
\82ñ');
146 Dir := ExcludeTrailingPathDelimiter(Dir);
147 if (Length(Dir) < 3) or DirectoryExistsEx(Dir)
148 or (ExtractFilePath(Dir) = Dir) then Exit; // avoid 'xyz:\' problem.
149 Result := ForceDirectoriesEx(ExtractFilePath(Dir)) and CreateDir(Dir);
152 //
\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
153 procedure ExtractHttpFields(
154 const chrSep : TSysCharSet;
155 const chrWhite : TSysCharSet;
156 const strValue : string;
157 var strResult : TStringList;
158 unknownFlag : boolean = false
161 last, p, strLen : Integer;
164 strLen := Length( strValue );
171 if strValue[ p ] in chrSep then
173 strResult.Add( Copy( strValue, last, p - last ) );
182 strResult.Add( Copy( strValue, last, strLen - last + 1 ) );
186 \rfunction HttpEncode(
187 \r const strValue : string
195 kHexCode : array [0..15] of char = (
196 '0', '1', '2', '3', '4', '5', '6', '7',
197 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' );
200 strLen := Length( strValue );
206 case strValue[ i ] of
207 '0' .. '9', 'a' .. 'z', 'A' .. 'Z', '*', '-', '.', '@', '_':
209 strResult := strResult + strValue[ i ];
213 b := Integer( strValue[ i ] );
214 strResult := strResult + '%'
215 + kHexCode[ b div $10 ]
216 + kHexCode[ b mod $10 ];
230 // =========================================================================
232 // =========================================================================
234 // *************************************************************************
235 //
\83v
\83\89\83O
\83C
\83\93\82Ì
\83o
\81[
\83W
\83\87\83\93\82ð
\97v
\8b\81\82³
\82ê
\82½
236 // *************************************************************************
237 procedure OnVersionInfo(
238 var outAgent : PChar; //
\83o
\81[
\83W
\83\87\83\93\82ð
\88ê
\90Ø
\8aÜ
\82Ü
\82È
\82¢
\8f\83\90\88\82È
\96¼
\8fÌ
239 var outMajor : DWORD; //
\83\81\83W
\83\83\81[
\83o
\81[
\83W
\83\87\83\93
240 var outMinor : DWORD; //
\83}
\83C
\83i
\81[
\83o
\81[
\83W
\83\87\83\93
241 var outRelease : PChar; //
\83\8a\83\8a\81[
\83X
\92i
\8aK
\96¼
242 var outRevision : DWORD //
\83\8a\83r
\83W
\83\87\83\93\83i
\83\93\83o
\81[
247 outAgent := CreateResultString( PChar( PLUGIN_NAME ) );
248 outMajor := MAJOR_VERSION;
249 outMinor := MINOR_VERSION;
250 outRelease := CreateResultString( PChar( RELEASE_VERSION ) );
251 outRevision := REVISION_VERSION;
262 // *************************************************************************
263 //
\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©
264 // *************************************************************************
265 function OnAcceptURL(
266 inURL : PChar //
\94»
\92f
\82ð
\8bÂ
\82¢
\82Å
\82¢
\82é URL
267 ): TAcceptType; stdcall; // URL
\82Ì
\8eí
\97Þ
270 uriList : TStringList;
273 BBS_HOST = 'machi.to';
274 BBS_HOST2 = 'machibbs.com';
275 THREAD_MARK = '/bbs/read.pl';
276 THREAD_MARK2= '/bbs/read.cgi';
279 //
\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é
280 uri := TIdURI.Create( inURL );
281 uriList := TStringList.Create;
283 ExtractHttpFields( ['/'], [], uri.Path, uriList );
284 foundPos := AnsiPos( BBS_HOST, uri.Host );
285 if (foundPos > 0) and (Length( uri.Host ) - foundPos + 1 = Length( BBS_HOST )) then begin
286 foundPos := Pos( THREAD_MARK, inURL );
287 if (foundPos = 0) then begin
289 foundPos := Pos( THREAD_MARK2, inURL );
293 else if (uriList.Count > 1) and (uri.Path <> '/') then //
\8dÅ
\8cã
\82ª '/'
\82Å
\95Â
\82ß
\82ç
\82ê
\82Ä
\82é
\82È
\82ç 3
298 foundPos := AnsiPos( BBS_HOST2, uri.Host );
299 if (foundPos > 0) and (Length( uri.Host ) - foundPos + 1 = Length( BBS_HOST2 )) then begin
300 foundPos := Pos( THREAD_MARK, inURL );
301 if (foundPos = 0) then begin
303 foundPos := Pos( THREAD_MARK2, inURL );
307 else if (uriList.Count > 1) and (uri.Path <> '/') then //
\8dÅ
\8cã
\82ª '/'
\82Å
\95Â
\82ß
\82ç
\82ê
\82Ä
\82é
\82È
\82ç 3
313 Result := atNoAccept;
321 Result := atNoAccept;
326 // *************************************************************************
327 //
\8ew
\92è
\82µ
\82½ URL
\82ðBoard
\82ÌURL
\82É
\95Ï
\8a·
328 // *************************************************************************
329 procedure OnExtractBoardURL(
335 uriList : TStringList;
338 THREAD_MARK = '/bbs/read.pl';
339 THREAD_MARK2= '/bbs/read.cgi';
341 URL := string(inURL);
342 if AnsiPos(THREAD_MARK, URL) > 0 then begin
343 if Copy( inURL, Length( inURL ), 1 ) = '/' then
344 uri := TIdURI.Create( URL )
346 uri := TIdURI.Create( URL + '/' );
348 uriList := TStringList.Create;
352 Copy( uri.Params, AnsiPos( '?', uri.Params ) + 1, Length( uri.Params ) ),uriList );
353 // http://hokkaido.machi.to/bbs/read.pl?BBS=hokkaidou&KEY=1061764446
354 // http://hokkaido.machi.to/hokkaidou/
355 URL := uri.Protocol + '://' + uri.Host + '/' + uriList.Values[ 'BBS' ] + '/';
356 outURL := CreateResultString(URL);
361 end else if AnsiPos(THREAD_MARK2, URL) > 0 then begin
362 if Copy( inURL, Length( inURL ), 1 ) = '/' then
363 uri := TIdURI.Create( URL )
365 uri := TIdURI.Create( URL + '/' );
367 uriList := TStringList.Create;
369 // http://kanto.machi.to/bbs/read.cgi/kana/1215253035/l50
370 // http://kanto.machi.to/kana/
371 uriList.Delimiter := '/';
372 uriList.DelimitedText := uri.Path;
373 URL := uri.Protocol + '://' + uri.Host + '/';
374 if (uriList.Count >= 4) then begin
375 URL := URL + uriList[3] + '/';
377 outURL := CreateResultString(URL);
383 outURL := CreateResultString(URL);
389 // =========================================================================
390 // TMachiBBSThreadItem
391 // =========================================================================
393 // *************************************************************************
394 //
\83R
\83\93\83X
\83g
\83\89\83N
\83^
395 // *************************************************************************
396 constructor TMachiBBSThreadItem.Create(
401 uriList : TStringList;
407 OnDownload := Download;
411 OnGetHeader := GetHeader;
412 OnGetFooter := GetFooter;
413 OnGetBoardURL := GetBoardURL;
416 FIsTemporary := False;
418 URL := ReadURL + '&LAST=50';
420 uri := TIdURI.Create( URL );
421 uriList := TStringList.Create;
423 // http://hokkaido.machi.to/bbs/read.pl?BBS=hokkaidou&KEY=1061764446&LAST=50
426 Copy( uri.Params, AnsiPos( '?', uri.Params ) + 1, Length( uri.Params ) ), uriList );
427 FileName := uriList.Values[ 'KEY' ] + '.dat';
428 FilePath := MyLogFolder + uriList.Values[ 'BBS' ] + '\' + uriList.Values[ 'KEY' ] + '.dat';
429 IsLogFile := FileExists( FilePath );
437 // *************************************************************************
438 //
\83f
\83X
\83g
\83\89\83N
\83^
439 // *************************************************************************
440 destructor TMachiBBSThreadItem.Destroy;
445 //
\88ê
\8e\9e\83t
\83@
\83C
\83\8b\82Ì
\8fê
\8d\87\82Í
\8dí
\8f\9c\82·
\82é
447 DeleteFile( FilePath );
453 // *************************************************************************
454 //
\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½
455 // *************************************************************************
456 function TMachiBBSThreadItem.Download : TDownloadState;
458 RES_ERROR: String = '<ERROR>';
462 // downResult : TStringList;
463 content : TStringList;
464 responseCode : Longint;
465 logStream : TFileStream;
467 uriList : TStringList;
469 // foundPos : Integer;
471 procedure downAndParse;
473 responseCode := InternalDownload( PChar( datURL ), modified, tmp, 0 );
476 if responseCode = 200 then begin
477 // API
\82Å
\82Ídat
\8c`
\8e®
\82Å
\95Ô
\82Á
\82Ä
\82
\82é
478 content.Text := string( tmp );
479 if (content.Count > 0) and (Pos(RES_ERROR, content.Strings[0]) <> 1) then
480 To2chDat2( content ); //
\8c`
\8e®
\95Ï
\8a·
481 (*
\8b\8c\8ed
\97l
\81iHTML
\82Å
\8eó
\90M
\82µdat
\82É
\95Ï
\8a·
\82·
\82é
\81j
482 downResult := TStringList.Create;
484 downResult.Text := string( tmp );
486 //
\83^
\83C
\83g
\83\8b\82Ì
\8eæ
\93¾
487 foundPos := AnsiPos( '<title>', downResult.Text ) + Length( '<title>' );
491 AnsiPos( '</title>', downResult.Text ) - foundPos );
493 //
\83\8c\83X
\82Ì
\8aJ
\8en
\88Ê
\92u
494 foundPos := AnsiPos( '<dt', downResult.Text );
495 downResult.Text := Copy( downResult.Text, foundPos, Length( downResult.Text ) );
496 if foundPos > 0 then begin
497 //
\83\8c\83X
\82Ì
\8fI
\97¹
\88Ê
\92u
498 foundPos := AnsiPos( '<table', downResult.Text ) - 1;
500 downResult.Text := Copy( downResult.Text, 1, foundPos );
501 //
\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Å
502 //
\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¤
503 To2chDat( downResult, Count + 1 );
504 content.Text := content.Text + downResult.Text;
511 Result := dsNotModify;
515 DisposeResultString( tmp );
522 uri := TIdURI.Create( URL );
523 uriList := TStringList.Create;
524 content := TStringList.Create;
528 Copy( uri.Params, AnsiPos( '?', uri.Params ) + 1, Length( uri.Params ) ), uriList );
529 FileName := uriList.Values[ 'KEY' ] + '.dat';
530 if MyLogFolder = '' then begin
531 //
\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¶
532 FilePath := TemporaryFile;
533 FIsTemporary := True;
535 FilePath := MyLogFolder + uriList.Values[ 'BBS' ] + '\' + uriList.Values[ 'KEY' ] + '.dat';
536 FIsTemporary := False;
539 //
\95Û
\91¶
\97p
\82Ì
\83f
\83B
\83\8c\83N
\83g
\83\8a\82ð
\8c@
\82é
540 ForceDirectoriesEx( Copy( FilePath, 1, LastDelimiter( '\', FilePath ) ) );
542 //
\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Í
543 // InternalDownload
\82É
\94C
\82¹
\82é
\82±
\82Æ
\82ª
\8fo
\97\88\82é
544 modified := LastModified;
546 datURL := uri.Protocol + '://' + uri.Host + '/bbs/offlaw.cgi/2/' +
547 uriList.Values[ 'BBS' ] + '/' + uriList.Values[ 'KEY' ] + '/';
549 datURL := datURL + IntToStr( Count + 1 ) + '-'; //
\90V
\92\85\82Ì
\82Ý
\8eæ
\93¾
554 uri.Protocol + '://' + uri.Host + '/bbs/read.cgi?' +
555 'BBS=' + uriList.Values[ 'BBS' ] + '&KEY=' + uriList.Values[ 'KEY' ] +
556 '&START=' + IntToStr( 1 )
558 //
\90V
\92\85\82Ì
\82Ý
560 uri.Protocol + '://' + uri.Host + '/bbs/read.cgi?' +
561 'BBS=' + uriList.Values[ 'BBS' ] + '&KEY=' + uriList.Values[ 'KEY' ] +
562 '&START=' + IntToStr( Count + 1 ) + '&NOFIRST=TRUE';
564 //
\83_
\83E
\83\93\83\8d\81[
\83h
567 if content.Count > 0 then begin
568 if (Pos(RES_ERROR, content.Strings[0]) <> 1) then begin
569 if Count <= 0 then begin
570 Result := dsComplete;
571 //
\90V
\8bK
\8f\91\82«
\8d\9e\82Ý
572 content[ 0 ] := content[ 0 ] + Title;
573 logStream := TFileStream.Create( FilePath, fmCreate or fmShareDenyWrite );
575 logStream.Position := logStream.Size;
576 logStream.Write( PChar( content.Text )^, Length( content.Text ) );
581 Count := content.Count;
583 if (content.Count > 1) or (Trim(content.Text) <> '') then begin
584 Result := dsDiffComplete;
586 logStream := TFileStream.Create( FilePath, fmOpenReadWrite or fmShareDenyWrite );
588 logStream.Position := logStream.Size;
589 logStream.Write( PChar( content.Text )^, Length( content.Text ) );
593 NewReceive := Count + 1;
594 Count := Count + content.Count;
596 Result := dsNotModify;
599 if (Result <> dsNotModify) then begin
600 // CGI
\82©
\82ç
\82Í
\90³
\82µ
\82¢
\93ú
\95t
\82ª
\93¾
\82ç
\82ê
\82È
\82¢
\82Ì
\82Å
\8c»
\8dÝ
\82É
\90Ý
\92è
602 NewResCount := content.Count;
606 Result := dsNotModify;
616 // *************************************************************************
617 //
\8f\91\82«
\8d\9e\82Ý
\82ð
\8ew
\8e¦
\82³
\82ê
\82½
618 // *************************************************************************
619 function TMachiBBSThreadItem.Write(
620 inName : string; //
\96¼
\91O(
\83n
\83\93\83h
\83\8b)
621 inMail : string; //
\83\81\81[
\83\8b\83A
\83h
\83\8c\83X
622 inMessage : string //
\96{
\95¶
623 ) : TDownloadState; //
\8f\91\82«
\8d\9e\82Ý
\82ª
\90¬
\8c÷
\82µ
\82½
\82©
\82Ç
\82¤
\82©
629 uriList : TStringList;
632 uri := TIdURI.Create( URL );
633 uriList := TStringList.Create;
637 Copy( uri.Params, AnsiPos( '?', uri.Params ) + 1, Length( uri.Params ) ), uriList );
639 postURL := uri.Protocol + '://' + uri.Host + '/bbs/write.cgi';
641 'NAME=' + HttpEncode( inName ) +
642 '&MAIL=' + HttpEncode( inMail ) +
643 '&MESSAGE=' + HttpEncode( inMessage ) +
644 '&BBS=' + uriList.Values[ 'BBS' ] +
645 '&KEY=' + uriList.Values[ 'KEY' ] +
646 '&TIME=' + IntToStr( DateTimeToUnix( Now ) ) +
647 '&submit=' + HttpEncode( '
\8f\91\82«
\8d\9e\82Þ' );
649 //
\93Æ
\8e©
\82É
\92Ê
\90M
\82µ
\82È
\82¢
\8fê
\8d\87\82Í InternalPost
\82É
\94C
\82¹
\82é
\82±
\82Æ
\82ª
\8fo
\97\88\82é
650 InternalPost( PChar( postURL ), PChar( postData ),PChar(URL), postResult );
651 DisposeResultString( postResult );
661 // *************************************************************************
662 //
\83\8c\83X
\94Ô
\8d\86 inNo
\82É
\91Î
\82·
\82é html
\82ð
\97v
\8b\81\82³
\82ê
\82½
663 // *************************************************************************
664 function TMachiBBSThreadItem.GetRes(
665 inNo : Integer //
\97v
\8b\81\82³
\82ê
\82½
\83\8c\83X
\94Ô
\8d\86
666 ) : string; //
\91Î
\89\9e\82·
\82é HTML
672 //
\93Æ
\8e©
\82É
\83t
\83B
\83\8b\83^
\83\8a\83\93\83O
\82ð
\8ds
\82í
\82È
\82¢
\8fê
\8d\87\82Í
673 // InternalAbon
\82¨
\82æ
\82Ñ Dat2HTML
\82É
\94C
\82¹
\82é
\82±
\82Æ
\82ª
\8fo
\97\88\82é
675 if (FDat = nil) or (inNo - 1 < 0 ) or (inNo - 1 >= FDat.Count) then begin
676 //
\83\8d\83O
\82É
\91¶
\8dÝ
\82µ
\82È
\82¢
\82Ì
\82Å
\82±
\82Ì
\82Ü
\82Ü
\8fI
\97¹
680 res := FDat[ inNo - 1 ];
681 tmp := InternalAbonForOne( PChar( res ), PChar(FilePath), inNo);
683 Result := Dat2HTML( string( tmp ), inNo );
685 DisposeResultString( tmp );
690 // *************************************************************************
691 //
\83\8c\83X
\94Ô
\8d\86 inNo
\82É
\91Î
\82·
\82é Dat
\82ð
\97v
\8b\81\82³
\82ê
\82½
692 // *************************************************************************
693 function TMachiBBSThreadItem.GetDat(
694 inNo : Integer //
\97v
\8b\81\82³
\82ê
\82½
\83\8c\83X
\94Ô
\8d\86
695 ) : string; //
\82Q
\82¿
\82á
\82ñ
\82Ë
\82é
\82ÌDat
\8c`
\8e®
701 //
\93Æ
\8e©
\82É
\83t
\83B
\83\8b\83^
\83\8a\83\93\83O
\82ð
\8ds
\82í
\82È
\82¢
\8fê
\8d\87\82Í
703 if (FDat = nil) or (inNo - 1 < 0 ) or (inNo - 1 >= FDat.Count) then begin
704 //
\83\8d\83O
\82É
\91¶
\8dÝ
\82µ
\82È
\82¢
\82Ì
\82Å
\82±
\82Ì
\82Ü
\82Ü
\8fI
\97¹
705 tmp := CreateResultString('');
707 DisposeResultString(tmp);
710 tmp := CreateResultString(FDat[ inNo - 1]);
712 Result := string(tmp);
714 DisposeResultString(tmp);
719 // *************************************************************************
720 //
\83X
\83\8c\83b
\83h
\82Ì
\83w
\83b
\83_ html
\82ð
\97v
\8b\81\82³
\82ê
\82½
721 // *************************************************************************
722 function TMachiBBSThreadItem.GetHeader(
723 inOptionalHeader : string
727 //
\93Æ
\8e©
\82É
\83t
\83B
\83\8b\83^
\83\8a\83\93\83O
\82ð
\8ds
\82í
\82È
\82¢
\8fê
\8d\87\82Í
728 // InternalHeader
\82É
\94C
\82¹
\82é
\82±
\82Æ
\82ª
\8fo
\97\88\82é
729 Result := InternalHeader(
730 '<meta http-equiv="Content-type" content="text/html; charset=Shift_JIS">' +
734 // GetRes
\82ð
\8cÄ
\82Î
\82ê
\82é
\82±
\82Æ
\82ª
\97\
\91z
\82³
\82ê
\82é
\82Ì
\82Å FDat
\82ð
\90¶
\90¬
\82µ
\82Ä
\82¨
\82
743 // *************************************************************************
744 //
\83X
\83\8c\83b
\83h
\82Ì
\83t
\83b
\83^ html
\82ð
\97v
\8b\81\82³
\82ê
\82½
745 // *************************************************************************
746 function TMachiBBSThreadItem.GetFooter(
747 inOptionalFooter : string
751 //
\93Æ
\8e©
\82É
\83t
\83B
\83\8b\83^
\83\8a\83\93\83O
\82ð
\8ds
\82í
\82È
\82¢
\8fê
\8d\87\82Í
752 // InternalFooter
\82É
\94C
\82¹
\82é
\82±
\82Æ
\82ª
\8fo
\97\88\82é
753 Result := InternalFooter( inOptionalFooter );
755 //
\82à
\82¤ GetRes
\82Í
\8cÄ
\82Î
\82ê
\82È
\82¢
\82Æ
\8ev
\82¤
\82Ì
\82Å FDat
\82ð
\8aJ
\95ú
\82µ
\82Ä
\82¨
\82
763 // *************************************************************************
764 //
\82±
\82Ì ThreadItem
\82ª
\91®
\82·
\82é
\94Â
\82Ì URL
\82ð
\97v
\8b\81\82³
\82ê
\82½
765 // *************************************************************************
766 function TMachiBBSThreadItem.GetBoardURL : string;
769 uriList : TStringList;
773 if Copy( URL, Length( URL ), 1 ) = '/' then
774 uri := TIdURI.Create( URL )
776 uri := TIdURI.Create( URL + '/' );
777 uriList := TStringList.Create;
781 Copy( uri.Params, AnsiPos( '?', uri.Params ) + 1, Length( uri.Params ) ), uriList );
782 FileName := uriList.Values[ 'KEY' ] + '.dat';
783 // http://hokkaido.machi.to/bbs/read.pl?BBS=hokkaidou&KEY=1061764446
784 // http://hokkaido.machi.to/hokkaidou/
785 tmp := CreateResultString(
786 uri.Protocol + '://' + uri.Host + '/' + uriList.Values[ 'BBS' ] + '/' );
787 Result := string(tmp);
789 DisposeResultString(tmp);
797 // *************************************************************************
798 //
\82Ü
\82¿BBS
\82Ì HTML
\82ð 2ch
\82Ì dat
\8c`
\8e®
\82É
799 // *************************************************************************
800 procedure TMachiBBSThreadItem.To2chDat(
801 ioHTML : TStringList;
802 inStartNo : Integer = 1
806 foundPos,foundPos2 : Integer;
811 MAIL_TAG = '<a href="mailto:';
814 //===== 2ch
\82Ì dat
\8c`
\8e®
\82É
\95Ï
\8a·
815 //
\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
816 ioHTML.Text := CustomStringReplace( ioHTML.Text, #13#10, '');
817 //StringReplace( ioHTML.Text, #13#10, '', [rfReplaceAll] );
818 //
\91ã
\82í
\82è
\82É <dt>
\82ð
\8ds
\82Ì
\8bæ
\90Ø
\82è
\82É
\82·
\82é
819 ioHTML.Text := CustomStringReplace( ioHTML.Text, '<dt>', #10 );
820 //StringReplace( ioHTML.Text, '<dt>', #10, [rfReplaceAll] );
821 // <dt>
\82©
\82ç
\8en
\82Ü
\82Á
\82Ä
\82¢
\82é
\82Ì
\82Å
\8dÅ
\8f\89\82Í
\8bó
\82Ì
\82Í
\82¸
822 if Length( ioHTML[ 0 ] ) = 0 then
825 //
\8cy
\82
\82 \82Ú
\81[
\82ñ
\83`
\83F
\83b
\83N
826 //
\81¦
\91å
\8eG
\94c
\82¾
\82©
\82ç
\82¿
\82á
\82ñ
\82Æ
\8fo
\97\88\82Ä
\82È
\82¢
\82©
\82à
829 while i < ioHTML.Count do begin
830 foundPos := AnsiPos( ' ', ioHTML[ i ] );
831 if foundPos > 0 then begin
832 no := StrToInt( Copy( ioHTML[ i ], 1, foundPos - 1 ) );
833 if inStartNo < no then
834 ioHTML.Insert( i, '<><><><>' );
840 //
\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Å
844 //
\83g
\83\8a\83b
\83v
\82Ì
\8cã
\82Ì '<b> </b>'
\82ð
\8bó
\82É
845 if AnsiPos('
\81\9f</b>', ioHTML.Text) <> 0 then begin
846 ioHTML.Text := CustomStringReplace( ioHTML.Text, '<b> </b></font>', '</b></font>', true );
847 ioHTML.Text := CustomStringReplace( ioHTML.Text, '<b> </B></a>', '</b></a>', true );
849 //ioHTML.Text := CustomStringReplace( ioHTML.Text, '<b> </b>', '', true );
850 //StringReplace( ioHTML.Text, '<b> </b>', '', [rfReplaceAll, rfIgnoreCase] );
851 // '<b>'
\82Í
\83\81\81[
\83\8b\82Æ
\96¼
\91O
\82Ì
\8bæ
\90Ø
\82è
852 ioHTML.Text := CustomStringReplace( ioHTML.Text, '<b>', '<>', true );
853 //StringReplace( ioHTML.Text, '<b>', '<>', [rfReplaceAll, rfIgnoreCase] );
854 //
\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É
855 ioHTML.Text := CustomStringReplace( ioHTML.Text, '</b></a>', '<>', true );
856 //StringReplace( ioHTML.Text, '</b></a>', '<>', [rfReplaceAll, rfIgnoreCase] );
857 ioHTML.Text := CustomStringReplace( ioHTML.Text, '</b>', '<>', true );
858 ioHTML.Text := CustomStringReplace( ioHTML.Text, '
\81\9f<>', '
\81\9f</b>', true );
859 //StringReplace( ioHTML.Text, '</b>', '<>', [rfReplaceAll, rfIgnoreCase] );
860 // '<dd>'
\82ð
\96{
\95¶
\82Æ
\82Ì
\8bæ
\90Ø
\82è
\82É
861 ioHTML.Text := CustomStringReplace( ioHTML.Text, '<dd>', '<>', true );
862 //StringReplace( ioHTML.Text, '<dd>', '<>', [rfReplaceAll, rfIgnoreCase] );
864 res := TStringList.Create;
866 bound := ioHTML.Count - 1;
867 for i := 0 to bound do begin
868 //
\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
869 res.Text := CustomStringReplace( ioHTML[ i ], '<>', #10 );
870 //StringReplace( ioHTML[ i ], '<>', #10, [rfReplaceAll] );
871 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ß
872 foundPos := AnsiPos( MAIL_TAG, res[ 0 ] );
873 if foundPos > 0 then begin
874 //
\83\81\81[
\83\8b\83A
\83h
\83\8c\83X
\82ð
\94²
\82«
\8fo
\82·
875 foundPos := foundPos + Length( MAIL_TAG );
876 res[ 0 ] := Copy( res[ 0 ], foundPos, Length( res[ 0 ] ) );
877 strTmp := Copy( res[ 0 ], 1, AnsiPos( '">', res[ 0 ] ) - 1 );
878 //
\83\81\81[
\83\8b\82Æ
\96¼
\91O
\82ª
\8bt
\82È
\82Ì
\82Å
\82Ð
\82Á
\82
\82è
\95Ô
\82µ
\82Ä
\96ß
\82·
879 res[ 0 ] := res[ 1 ];
882 //
\83\81\81[
\83\8b\82Æ
\96¼
\91O
\82ª
\8bt
\82È
\82Ì
\82Å
\82Ð
\82Á
\82
\82è
\95Ô
\82·
883 res[ 0 ] := res[ 1 ];
886 res[ 2 ] := StringReplace( res[ 2 ], '[', 'IP:', [] );
887 res[ 2 ] := StringReplace( res[ 2 ], ']', '', [] );
889 if AnsiPos('</font>
\93\8a\8de
\93ú
\81F', res[ 2 ]) = 1 then begin
890 res[ 2 ] := StringReplace( res[ 2 ], '</font>
\93\8a\8de
\93ú
\81F', '', [] );
891 end else if AnsiPos('
\93\8a\8de
\93ú
\81F', res[ 2 ]) = 1 then begin
892 res[ 2 ] := StringReplace( res[ 2 ], '
\93\8a\8de
\93ú
\81F', '', [] );
895 ioHTML[ i ] := CustomStringReplace( res.Text, #13#10, '<>');
896 //
\8dL
\8d\90\83X
\83N
\83\8a\83v
\83g
\91Î
\8dô
897 foundPos := Pos( '<script', ioHTML[ i ] );
898 if foundPos > 0 then begin
899 foundPos2 := Pos( '</script>', ioHTML[ i ] );
900 if (foundPos2 > foundPos) then begin
901 ioHTML[ i ] := Copy(ioHTML[ i ], 1, foundPos-1) +
902 Copy(ioHTML[ i ], foundPos2 + 9, Length(ioHTML[ i ]));
913 // *************************************************************************
914 //
\82Ü
\82¿BBS
\82Ì dat
\82ð 2ch
\82Ì dat
\8c`
\8e®
\82É
915 // *************************************************************************
916 procedure TMachiBBSThreadItem.To2chDat2( var ioDat: TStringList );
918 SEP_TAG: String = '<>';
919 ITEM_NUM: Integer = 7;
920 IDX_HOST: Integer = 6;
922 IDX_ADDST: Integer = 1;
923 IDX_ADDED: Integer = 5;
927 ResLine: TStringList;
935 DstTmp := TStringList.Create;
936 ResLine := TStringList.Create;
938 No := Count + 1; //
\8ds
\94Ô
\8d\86\81i
\83\8c\83X
\94Ô
\8d\86\81j
939 for i := 0 to ioDat.Count - 1 do begin
940 //
\82P
\8ds
\82ð
\8d\80\96Ú
\95Ê
\82É
\90Ø
\82è
\95ª
\82¯
\82é
942 TmpLine := ioDat.Strings[i];
943 while (True) do begin
944 Sep := Pos(SEP_TAG, TmpLine);
945 if (Sep > 0) then begin
946 ResLine.Add(Copy(TmpLine, 1, Sep - 1));
947 Delete(TmpLine, 1, Sep + 1);
949 ResLine.Add(TmpLine);
953 while (ResLine.Count < ITEM_NUM) do
954 ResLine.Add(''); //
\95s
\91«
\8d\80\96Ú
\90\94\82¾
\82¯
\92Ç
\89Á
956 //
\83z
\83X
\83g
\96¼
\82ðID
\82Ì
\8cã
\82ë
\82É
\92Ç
\89Á
957 ResLine.Strings[IDX_ID] := ResLine.Strings[IDX_ID] + ' <font size=1>IP: ' + ResLine.Strings[IDX_HOST] + ' </font>';
959 //
\95K
\97v
\8d\80\96Ú
\82¾
\82¯
\8dÄ
\8c\8b\8d\87
960 for j := IDX_ADDST to IDX_ADDED do begin
961 if (j = IDX_ADDST) then
962 TmpLine := ResLine.Strings[j]
964 TmpLine := TmpLine + SEP_TAG + ResLine.Strings[j];
967 GetNo := StrToIntDef(ResLine.Strings[IDX_NO], 0);
968 while (GetNo > No) do begin
978 ioDat.Assign(DstTmp);
985 // *************************************************************************
987 // *************************************************************************
988 procedure TMachiBBSThreadItem.LoadDat;
991 if FDat = nil then begin
992 if IsLogFile then begin
993 // dat
\82Ì
\93Ç
\82Ý
\8d\9e\82Ý
994 FDat := TStringList.Create;
995 FDat.LoadFromFile( FilePath );
1001 // *************************************************************************
1002 // FDat
\82Ì
\8aJ
\95ú
1003 // *************************************************************************
1004 procedure TMachiBBSThreadItem.FreeDat;
1007 if FDat <> nil then begin
1014 // *************************************************************************
1015 //
\88À
\91S
\82È( '/'
\82Å
\8fI
\82í
\82é )
\93Ç
\82Ý
\8d\9e\82Ý
\82Ì URL
1016 // *************************************************************************
1017 function TMachiBBSThreadItem.ReadURL : string;
1020 uriList : TStringList;
1023 THREAD_MARK2= '/bbs/read.cgi';
1026 foundPos := AnsiPos( '?', URL );
1027 if foundPos > 0 then begin
1028 uri := TIdURI.Create( URL );
1029 uriList := TStringList.Create;
1031 ExtractHttpFields( ['&'], [], Copy( URL, foundPos + 1, MaxInt ), uriList );
1033 uri.Protocol + '://' + uri.Host + '/bbs/read.pl?' +
1034 'BBS=' + uriList.Values[ 'BBS' ] + '&KEY=' + uriList.Values[ 'KEY' ];
1041 foundPos := AnsiPos(THREAD_MARK2, URL);
1042 if (foundPos > 0) then begin
1043 uri := TIdURI.Create( URL );
1044 uriList := TStringList.Create;
1046 uriList.Delimiter := '/';
1047 uriList.DelimitedText := uri.Path;
1048 if (uriList.Count >= 5) then begin
1050 uri.Protocol + '://' + uri.Host + '/bbs/read.pl?' +
1051 'BBS=' + uriList[3] + '&KEY=' + uriList[4];
1062 // *************************************************************************
1063 // TThreadItem
\82ª
\90¶
\90¬
\82³
\82ê
\82½
\8fê
\8d\87\82Ì
\8f\88\92u(TMachiBBSThreadItem
\82ð
\90¶
\90¬
\82·
\82é)
1064 // *************************************************************************
1065 procedure ThreadItemOnCreateOfTMachiBBSThreadItem(
1069 threadItem : TMachiBBSThreadItem;
1072 threadItem := TMachiBBSThreadItem.Create( inInstance );
1073 ThreadItemSetLong( inInstance, tipContext, DWORD( threadItem ) );
1077 // *************************************************************************
1078 // TThreadItem
\82ª
\94j
\8aü
\82³
\82ê
\82½
\8fê
\8d\87\82Ì
\8f\88\92u(TMachiBBSThreadItem
\82ð
\94j
\8aü
\82·
\82é)
1079 // *************************************************************************
1080 procedure ThreadItemOnDisposeOfTMachiBBSThreadItem(
1084 threadItem : TMachiBBSThreadItem;
1087 threadItem := TMachiBBSThreadItem( ThreadItemGetLong( inInstance, tipContext ) );
1092 // =========================================================================
1093 // TMachiBBSBoardItem
1094 // =========================================================================
1096 // *************************************************************************
1097 //
\83R
\83\93\83X
\83g
\83\89\83N
\83^
1098 // *************************************************************************
1099 constructor TMachiBBSBoardItem.Create(
1104 uriList : TStringList;
1109 OnDownload := Download;
1110 OnCreateThread := CreateThread;
1111 OnEnumThread := EnumThread;
1112 OnFileName2ThreadURL := ToThreadURL;
1115 FIsTemporary := False;
1119 uri := TIdURI.Create( SubjectURL );
1120 uriList := TStringList.Create;
1122 ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
1123 // http://hokkaido.machi.to/hokkaidou/subject.txt
1124 FilePath := MyLogFolder + uriList[ 1 ] + '\' + uri.Document;
1125 IsLogFile := FileExists( FilePath );
1133 // *************************************************************************
1134 //
\83f
\83X
\83g
\83\89\83N
\83^
1135 // *************************************************************************
1136 destructor TMachiBBSBoardItem.Destroy;
1139 if FDat <> nil then begin
1147 //
\88ê
\8e\9e\83t
\83@
\83C
\83\8b\82Ì
\8fê
\8d\87\82Í
\8dí
\8f\9c\82·
\82é
1148 if FIsTemporary then
1149 DeleteFile( FilePath );
1155 // *************************************************************************
1156 //
\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½
1157 // *************************************************************************
1158 function TMachiBBSBoardItem.Download : TDownloadState;
1162 responseCode : Longint;
1164 uriList : TStringList;
1170 if FDat <> nil then begin
1177 FDat := TStringList.Create;
1178 uri := TIdURI.Create( SubjectURL );
1179 uriList := TStringList.Create;
1180 //
\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Í
1181 // InternalDownload
\82É
\94C
\82¹
\82é
\82±
\82Æ
\82ª
\8fo
\97\88\82é
1182 modified := LastModified;
1183 dlURL := SubjectURL2;
1184 // responseCode := InternalDownload( PChar( uri.URI ), modified, downResult );
1185 responseCode := InternalDownload( PChar( dlURL ), modified, downResult );
1187 if responseCode = 200 then begin
1189 //
\83p
\83X
\82ð
\8eZ
\8fo
1190 ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
1191 if MyLogFolder = '' then begin
1192 //
\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¶
1193 FilePath := TemporaryFile;
1194 FIsTemporary := True;
1196 FilePath := MyLogFolder + uriList[ 1 ] + '\' + uri.Document;
1197 FIsTemporary := False
1200 //
\95Û
\91¶
\97p
\82Ì
\83f
\83B
\83\8c\83N
\83g
\83\8a\82ð
\8c@
\82é
1201 ForceDirectoriesEx( Copy( FilePath, 1, LastDelimiter( '\', FilePath ) ) );
1203 FDat.Text := string( downResult );
1204 //
\8c`
\8e®
\95Ï
\8a·(Ver.2->Ver.1)
1205 ChangeSubjectFormat(FDat);
1207 FDat.SaveToFile( FilePath );
1211 LastModified := modified;
1217 Result := dsComplete;
1220 DisposeResultString( downResult );
1225 procedure TMachiBBSBoardItem.ChangeSubjectFormat(var dat: TStringList);
1231 for i := 0 to dat.Count - 1 do begin
1232 tmp := dat.Strings[i];
1233 sep := Pos('<>', tmp);
1234 if (sep > 0) then begin
1235 Delete(tmp, 1, sep + 1);
1236 sep := Pos('<>', tmp);
1237 if (sep > 0) then begin
1238 Delete(tmp, sep, 2);
1239 Insert('.cgi,', tmp, sep);
1240 dat.Strings[i] := tmp;
1247 // *************************************************************************
1248 //
\83X
\83\8c\97§
\82Ä
\82ð
\8ew
\8e¦
\82³
\82ê
\82½
1249 // *************************************************************************
1250 function TMachiBBSBoardItem.CreateThread(
1251 inSubject : string; //
\83X
\83\8c\83^
\83C
1252 inName : string; //
\96¼
\91O(
\83n
\83\93\83h
\83\8b)
1253 inMail : string; //
\83\81\81[
\83\8b\83A
\83h
\83\8c\83X
1254 inMessage : string //
\96{
\95¶
1255 ) : TDownloadState; //
\8f\91\82«
\8d\9e\82Ý
\82ª
\90¬
\8c÷
\82µ
\82½
\82©
\82Ç
\82¤
\82©
1261 uriList : TStringList;
1264 uri := TIdURI.Create( URL );
1265 uriList := TStringList.Create;
1269 Copy( uri.Params, AnsiPos( '?', uri.Params ) + 1, Length( uri.Params ) ), uriList );
1271 postURL := uri.Protocol + '://' + uri.Host + '/bbs/write.cgi';
1273 'SUBJECT=' + HttpEncode( inSubject ) +
1274 '&NAME=' + HttpEncode( inName ) +
1275 '&MAIL=' + HttpEncode( inMail ) +
1276 '&MESSAGE=' + HttpEncode( inMessage ) +
1277 '&BBS=' + uriList[ 1 ] +
1278 '&TIME=' + IntToStr( DateTimeToUnix( Now ) ) +
1279 '&submit=' + HttpEncode( '
\90V
\8bK
\8f\91\82«
\8d\9e\82Ý' );
1281 //
\93Æ
\8e©
\82É
\92Ê
\90M
\82µ
\82È
\82¢
\8fê
\8d\87\82Í InternalPost
\82É
\94C
\82¹
\82é
\82±
\82Æ
\82ª
\8fo
\97\88\82é
1282 InternalPost( PChar( postURL ), PChar( postData ),PChar(URL), postResult );
1283 DisposeResultString( postResult );
1285 Result := dsComplete
1293 // *************************************************************************
1294 //
\83X
\83\8c\88ê
\97\97\82Ì URL
\82©
\82ç
\83X
\83\8c\83b
\83h
\82Ì URL
\82ð
\93±
\82«
\8fo
\82·
1295 // *************************************************************************
1296 function TMachiBBSBoardItem.ToThreadURL(
1297 inFileName : string //
\83X
\83\8c\83b
\83h
\83t
\83@
\83C
\83\8b\96¼
1298 ) : string; //
\83X
\83\8c\83b
\83h
\82Ì URL
1302 uriList : TStringList;
1306 found := AnsiPos( '.', inFileName );
1308 inFileName := Copy( inFileName, 1, found - 1 );
1310 uri := TIdURI.Create( SubjectURL );
1311 uriList := TStringList.Create;
1314 // http://hokkaido.machi.to/hokkaidou/
1315 // http://hokkaido.machi.to/bbs/read.pl?BBS=hokkaidou&KEY=1061764446&LAST=50
1316 ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
1317 threadURL := uri.Protocol + '://' + uri.Host + '/bbs/read.pl?' +
1318 'BBS=' + uriList[ 1 ] + '&KEY=' + inFileName + '&LAST=50';
1319 Result := threadURL;
1330 // *************************************************************************
1331 //
\82±
\82Ì
\94Â
\82É
\82¢
\82
\82Â
\82Ì
\83X
\83\8c\82ª
\82 \82é
\82©
\97v
\8b\81\82³
\82ê
\82½
1332 // *************************************************************************
1333 procedure TMachiBBSBoardItem.EnumThread(
1334 inCallBack : TBoardItemEnumThreadCallBack
1338 uriList : TStringList;
1342 if FDat = nil then begin
1343 FDat := TStringList.Create;
1345 uri := TIdURI.Create( SubjectURL );
1346 uriList := TStringList.Create;
1348 //
\83p
\83X
\82ð
\8eZ
\8fo
1349 ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
1350 // http://hokkaido.machi.to/hokkaidou/subject.txt
1351 FilePath := MyLogFolder + uriList[ 1 ] + '\' + uri.Document;
1352 if FileExists( FilePath ) then
1353 //
\93Ç
\82Ý
\8d\9e\82Ý
1354 FDat.LoadFromFile( FilePath );
1361 //
\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é
1362 inherited EnumThread( inCallBack, CustomStringReplace( FDat.Text, ',', '<>' ) );
1368 // *************************************************************************
1369 //
\83X
\83\8c\88ê
\97\97\82Ì URL
\82ð
\8b\81\82ß
\82é
1370 // *************************************************************************
1371 function TMachiBBSBoardItem.SubjectURL : string;
1374 uriList : TStringList;
1377 uri := TIdURI.Create( URL );
1378 uriList := TStringList.Create;
1380 if uri.Document <> SUBJECT_NAME then begin
1381 if Copy( URL, Length( URL ), 1 ) = '/' then
1382 Result := URL + SUBJECT_NAME
1384 Result := URL + '/' + SUBJECT_NAME;
1386 //
\82±
\82±
\82É
\82Í
\97\88\82È
\82¢
\82Æ
\8ev
\82¤
\82¯
\82Ç
1396 // *************************************************************************
1397 //
\83X
\83\8c\88ê
\97\97\82Ì URL
\82ð
\8b\81\82ß
\82é(Ver2)
1398 // *************************************************************************
1399 function TMachiBBSBoardItem.SubjectURL2 : string;
1404 uri := TIdURI.Create( URL );
1406 Result := uri.Protocol + '://' + uri.Host + '/bbs/offlaw.cgi/2' + uri.Path;
1412 // *************************************************************************
1413 // TBoardItem
\82ª
\90¶
\90¬
\82³
\82ê
\82½
\8fê
\8d\87\82Ì
\8f\88\92u(TMachiBBSBoardItem
\82ð
\90¶
\90¬
\82·
\82é)
1414 // *************************************************************************
1415 procedure BoardItemOnCreateOfTMachiBBSBoardItem(
1419 boardItem : TMachiBBSBoardItem;
1422 boardItem := TMachiBBSBoardItem.Create( inInstance );
1423 BoardItemSetLong( inInstance, bipContext, DWORD( boardItem ) );
1427 // *************************************************************************
1428 // TBoardItem
\82ª
\94j
\8aü
\82³
\82ê
\82½
\8fê
\8d\87\82Ì
\8f\88\92u(TMachiBBSBoardItem
\82ð
\94j
\8aü
\82·
\82é)
1429 // *************************************************************************
1430 procedure BoardItemOnDisposeOfTMachiBBSBoardItem(
1434 boardItem : TMachiBBSBoardItem;
1437 boardItem := TMachiBBSBoardItem( BoardItemGetLong( inInstance, bipContext ) );
1444 // =========================================================================
1445 //
\83G
\83\93\83g
\83\8a\83|
\83C
\83\93\83g
1446 // =========================================================================
1448 ul_reason_for_call : DWORD
1454 case ul_reason_for_call of
1459 module := GetModuleHandle( nil );
1461 LoadInternalAPI( module );
1462 LoadInternalFilePathAPI( module );
1463 LoadInternalThreadItemAPI( module );
1464 LoadInternalBoardItemAPI( module );
1466 // =====
\83C
\83\93\83X
\83^
\83\93\83X
\82Ì
\8eæ
\82è
\88µ
\82¢
\82ð TThreadItem
\82©
\82ç TMachiBBSThreadItem
\82É
\95Ï
\8dX
\82·
\82é
1467 ThreadItemOnCreate := ThreadItemOnCreateOfTMachiBBSThreadItem;
1468 ThreadItemOnDispose := ThreadItemOnDisposeOfTMachiBBSThreadItem;
1469 // =====
\83C
\83\93\83X
\83^
\83\93\83X
\82Ì
\8eæ
\82è
\88µ
\82¢
\82ð TBoardItem
\82©
\82ç TMachiBBSBoardItem
\82É
\95Ï
\8dX
\82·
\82é
1470 BoardItemOnCreate := BoardItemOnCreateOfTMachiBBSBoardItem;
1471 BoardItemOnDispose := BoardItemOnDisposeOfTMachiBBSBoardItem;
1490 DllProc := @DLLEntry;
1491 DLLEntry( DLL_PROCESS_ATTACH );