1 library ShitarabaJBBSPlugIn;
5 \82µ
\82½
\82ç
\82Î
\8f\88\97\9d\83\86\83j
\83b
\83g
6 $Id: ShitarabaJBBSPlugIn.dpr,v 1.20 2004/03/19 15:19:00 yoffy Exp $
10 Windows, SysUtils, Classes, Math, DateUtils, Dialogs,
12 PlugInMain in 'PlugInMain.pas',
13 ThreadItem in 'ThreadItem.pas',
14 BoardItem in 'BoardItem.pas',
15 FilePath in 'FilePath.pas',
16 Y_TextConverter in 'Y_TextConverter.pas',
17 MojuUtils in '..\..\MojuUtils.pas';
22 // =========================================================================
23 // TShitarabaThreadItem
24 // =========================================================================
25 TShitarabaThreadItem = class(TThreadItem)
27 FIsTemporary : Boolean;
31 constructor Create( inInstance : DWORD );
32 destructor Destroy; override;
35 function Download : TDownloadState;
36 function Write( inName : string; inMail : string; inMessage : string ) : TDownloadState;
37 function GetRes( inNo : Integer ) : string;
38 function GetDat( inNo : Integer ) : string;
39 function GetHeader( inOptionalHeader : string ) : string;
40 function GetFooter( inOptionalFooter : string ) : string;
41 function GetBoardURL : string;
42 procedure ArrangeDownloadData( start: Integer;var Data: TStringList);
45 function BrowsableURL : string;
46 function ReadURL : string;
47 function WriteURL : string;
50 // =========================================================================
51 // TShitarabaBoardItem
52 // =========================================================================
53 TShitarabaBoardItem = class(TBoardItem)
55 FIsTemporary : Boolean;
59 constructor Create( inInstance : DWORD );
60 destructor Destroy; override;
63 function Download : TDownloadState;
64 function CreateThread( inSubject : string; inName : string; inMail : string; inMessage : string ) : TDownloadState;
65 function ToThreadURL( inFileName : string ) : string;
66 procedure EnumThread( inCallBack : TBoardItemEnumThreadCallBack );
68 function SubjectURL : string;
72 LOG_DIR = 'ShitarabaJBBS\';
73 SUBJECT_NAME = 'subject.txt';
75 PLUGIN_NAME = 'ShitarabaJBBS';
78 RELEASE_VERSION = 'alpha';
81 SYNCRONIZE_MENU_CAPTION = '
\82µ
\82½
\82ç
\82ÎJBBS
\94Â
\8dX
\90V';
84 SyncronizeMenu : HMENU;
86 // =========================================================================
88 // =========================================================================
90 // *************************************************************************
91 //
\83e
\83\93\83|
\83\89\83\8a\82È
\83p
\83X
\82Ì
\8eæ
\93¾
92 // *************************************************************************
93 function TemporaryFile : string;
95 tempPath : array [0..MAX_PATH] of char;
98 GetTempPath( SizeOf(tempPath), tempPath );
100 Result := tempPath + IntToStr( Random( $7fffffff ) );
101 until not FileExists( Result );
105 // *************************************************************************
106 //
\82µ
\82½
\82ç
\82Î
\97p
\83\8d\83O
\83t
\83H
\83\8b\83_
\8eæ
\93¾
107 // *************************************************************************
108 function MyLogFolder : string;
114 if Length( folder ) = 0 then
117 Result := folder + LOG_DIR;
121 (*************************************************************************
122 *
\83f
\83B
\83\8c\83N
\83g
\83\8a\82ª
\91¶
\8dÝ
\82·
\82é
\82©
\83`
\83F
\83b
\83N
123 *************************************************************************)
124 function DirectoryExistsEx(const Name: string): Boolean;
128 Code := GetFileAttributes(PChar(Name));
129 Result := (Code <> -1) and (FILE_ATTRIBUTE_DIRECTORY and Code <> 0);
132 (*************************************************************************
133 *
\83f
\83B
\83\8c\83N
\83g
\83\8a\8dì
\90¬
\81i
\95¡
\90\94\8aK
\91w
\91Î
\89\9e\81j
134 *************************************************************************)
135 function ForceDirectoriesEx(Dir: string): Boolean;
138 if Length(Dir) = 0 then
139 raise Exception.Create('
\83t
\83H
\83\8b\83_
\82ª
\8dì
\90¬
\8fo
\97\88\82Ü
\82¹
\82ñ');
140 Dir := ExcludeTrailingPathDelimiter(Dir);
141 if (Length(Dir) < 3) or DirectoryExistsEx(Dir)
142 or (ExtractFilePath(Dir) = Dir) then Exit; // avoid 'xyz:\' problem.
143 Result := ForceDirectoriesEx(ExtractFilePath(Dir)) and CreateDir(Dir);
146 //
\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
147 procedure ExtractHttpFields(
148 const chrSep : TSysCharSet;
149 const chrWhite : TSysCharSet;
150 const strValue : string;
151 var strResult : TStringList;
152 unknownFlag : boolean = false
155 last, p, strLen : Integer;
158 strLen := Length( strValue );
165 if strValue[ p ] in chrSep then
167 strResult.Add( Copy( strValue, last, p - last ) );
176 strResult.Add( Copy( strValue, last, strLen - last + 1 ) );
180 \rfunction HttpEncode(
181 \r const strValue : string
189 kHexCode : array [0..15] of char = (
190 '0', '1', '2', '3', '4', '5', '6', '7',
191 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' );
194 strLen := Length( strValue );
200 case strValue[ i ] of
201 '0' .. '9', 'a' .. 'z', 'A' .. 'Z', '*', '-', '.', '@', '_':
203 strResult := strResult + strValue[ i ];
207 b := Integer( strValue[ i ] );
208 strResult := strResult + '%'
209 + kHexCode[ b div $10 ]
210 + kHexCode[ b mod $10 ];
224 // =========================================================================
226 // =========================================================================
228 // *************************************************************************
229 //
\83v
\83\89\83O
\83C
\83\93\82ª(
\90³
\82µ
\82)
\83\8d\81[
\83h
\82³
\82ê
\82½
230 // *************************************************************************
232 inInstance : DWORD //
\83v
\83\89\83O
\83C
\83\93\82Ì
\83C
\83\93\83X
\83^
\83\93\83X
236 //
\83v
\83\89\83O
\83C
\83\93\83\81\83j
\83\85\81[
\82É
\92Ç
\89Á
237 SyncronizeMenu := AddPlugInMenu( inInstance, SYNCRONIZE_MENU_CAPTION );
241 // *************************************************************************
242 //
\83v
\83\89\83O
\83C
\83\93\82Ì
\83o
\81[
\83W
\83\87\83\93\82ð
\97v
\8b\81\82³
\82ê
\82½
243 // *************************************************************************
244 procedure OnVersionInfo(
245 var outAgent : PChar; //
\83o
\81[
\83W
\83\87\83\93\82ð
\88ê
\90Ø
\8aÜ
\82Ü
\82È
\82¢
\8f\83\90\88\82È
\96¼
\8fÌ
246 var outMajor : DWORD; //
\83\81\83W
\83\83\81[
\83o
\81[
\83W
\83\87\83\93
247 var outMinor : DWORD; //
\83}
\83C
\83i
\81[
\83o
\81[
\83W
\83\87\83\93
248 var outRelease : PChar; //
\83\8a\83\8a\81[
\83X
\92i
\8aK
\96¼
249 var outRevision : DWORD //
\83\8a\83r
\83W
\83\87\83\93\83i
\83\93\83o
\81[
254 outAgent := CreateResultString( PChar( PLUGIN_NAME ) );
255 outMajor := MAJOR_VERSION;
256 outMinor := MINOR_VERSION;
257 outRelease := CreateResultString( PChar( RELEASE_VERSION ) );
258 outRevision := REVISION_VERSION;
269 // *************************************************************************
270 //
\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©
271 // *************************************************************************
272 function OnAcceptURL(
273 inURL : PChar //
\94»
\92f
\82ð
\8bÂ
\82¢
\82Å
\82¢
\82é URL
274 ): TAcceptType; stdcall; // URL
\82Ì
\8eí
\97Þ
277 uriList : TStringList;
280 BBS_HOST = 'jbbs.shitaraba.com';
281 THREAD_MARK = '/bbs/read.cgi';
285 //
\83z
\83X
\83g
\96¼
\82ª jbbs.shitaraba.com
\82Å
\8fI
\82í
\82é
\8fê
\8d\87\82Í
\8eó
\82¯
\95t
\82¯
\82é
\82æ
\82¤
\82É
\82µ
\82Ä
\82¢
\82é
286 uri := TIdURI.Create( inURL );
287 uriList := TStringList.Create;
289 ExtractHttpFields( ['/'], [], uri.Path, uriList );
290 foundPos := AnsiPos( BBS_HOST, uri.Host );
291 if (foundPos > 0) and (Length( uri.Host ) - foundPos + 1 = Length( BBS_HOST )) then begin
292 foundPos := ANsiPos( THREAD_MARK, inURL );
295 else if uriList.Count > 2 then //
\8dÅ
\8cã
\82ª '/'
\82Å
\95Â
\82ß
\82ç
\82ê
\82Ä
\82é
\82È
\82ç 4
300 Result := atNoAccept;
307 Result := atNoAccept;
312 // *************************************************************************
313 //
\82µ
\82½
\82ç
\82ÎJBBS
\94Â
\8dX
\90V
314 // *************************************************************************
315 procedure OnBoardSyncronizeMenu(
316 inHandle : HMENU //
\83\81\83j
\83\85\81[
\83n
\83\93\83h
\83\8b
336 saveText : TStringList;
337 responseCode : Longint;
343 CATEGORY_INPUT = '
\83J
\83e
\83S
\83\8a\82ð
\93ü
\97Í
\82µ
\82Ä
\82
\82¾
\82³
\82¢';
344 KEYWORD_INPUT = '
\8c\9f\8dõ
\82·
\82é
\94Â
\96¼
\82ð
\93ü
\97Í
\82µ
\82Ä
\82
\82¾
\82³
\82¢';
345 SAVEPATH_SELECT = '
\95Û
\91¶
\82·
\82é
\83t
\83@
\83C
\83\8b\96¼
\82ð
\93ü
\97Í
\82µ
\82Ä
\82
\82¾
\82³
\82¢';
346 BBS_HOST = 'http://jbbs.shitaraba.com/';
351 category := 'computer';
352 success := InputQuery( SYNCRONIZE_MENU_CAPTION, CATEGORY_INPUT, category );
355 keyword := InputBox( SYNCRONIZE_MENU_CAPTION, KEYWORD_INPUT, '' );
359 VersionInfo( agent, major, minor, release, revision );
361 initdir := PreferencesFolder;
362 filter := '
\82·
\82Ä
\82×
\82Ì
\83t
\83@
\83C
\83\8b (*.*)|*.*';
363 if agent = 'gikoNavi' then begin
364 if DirectoryExists( initdir + 'Board\' ) then
365 initdir := initdir + 'Board\';
366 filter := '
\94Â
\83t
\83@
\83C
\83\8b (*.txt)|*.txt';
369 DisposeResultString( agent );
370 DisposeResultString( release );
373 success := PromptForFileName( savepath, filter, 'txt', SYNCRONIZE_MENU_CAPTION, initdir, True );
377 InternalPrint( '
\94Â
\8fî
\95ñ
\82ð
\8eæ
\93¾
\92\86\82Å
\82·' );
380 'http://jbbs.shitaraba.com/bbs/left_menu.cgi?CATEGORY=' + category +
381 '&WORD=' + HttpEncode( SJIStoEUC( keyword ) );
383 responseCode := InternalDownload( PChar( url ), modified, tmp );
385 if (responseCode = 200) or (responseCode = 206) then begin
386 saveText := TStringList.Create;
387 saveText.Add( '[' + keyword + ']' );
388 downResult := EUCtoSJIS( tmp );
389 found := AnsiPos( '<a ', downResult );
390 while found > 0 do begin
391 downResult := Copy( downResult, found + 3, MaxInt ); // 3 = Length( '<a ' )
392 found := AnsiPos( 'href=', downResult );
396 if downResult[ found + 5 ] = '"' then begin // 5 = Length( 'href=' )
397 downResult := Copy( downResult, found + 6, MaxInt ); // 6 = Length( 'href="' )
398 found := AnsiPos( '"', downResult );
400 downResult := Copy( downResult, found + 5, MaxInt ); // 5 = Length( 'href=' )
401 found := AnsiPos( ' ', downResult );
402 found2 := AnsiPos( '>', downResult );
403 if (found = 0) or (found2 = 0) then
404 found := Max( found, found2 )
406 found := Min( found, found2 );
408 board := Copy( downResult, 1, found - 1 );
409 downResult := Copy( downResult, found, MaxInt );
411 if board = BBS_HOST then
413 if AnsiPos( '../', board ) = 1 then
414 board := BBS_HOST + Copy( board, 1 + 3, MaxInt ); // 3 = Length( '../' )
416 found := AnsiPos( '>', downResult );
419 downResult := Copy( downResult, found + 1, MaxInt ); // 1 = Length( '>' )
421 found := AnsiPos( '</a>', downResult );
424 board := Copy( downResult, 1, found - 1 ) + '=' + board;
425 downResult := Copy( downResult, found + 4, MaxInt ); // 4 = Length( '</a>' )
427 saveText.Add( board );
429 found := AnsiPos( '<a ', downResult );
431 saveText.SaveToFile( savepath );
434 InternalPrint( PChar( '
\94Â
\8fî
\95ñ
\82Ì
\8eæ
\93¾
\82É
\8e¸
\94s
\82µ
\82Ü
\82µ
\82½(' + IntToStr( responseCode ) + ')' ) );
437 DisposeResultString( tmp );
439 InternalPrint( '
\94Â
\8fî
\95ñ
\82ð
\8eæ
\93¾
\8a®
\97¹' );
441 InternalPrint( '
\94Â
\8fî
\95ñ
\82Ì
\8eæ
\93¾
\82É
\8e¸
\94s
\82µ
\82Ü
\82µ
\82½' );
446 //
\83\81\83j
\83\85\81[
\83n
\83\93\83h
\83\89
447 procedure OnPlugInMenu(
448 inHandle : HMENU //
\83\81\83j
\83\85\81[
\83n
\83\93\83h
\83\8b
452 if inHandle = SyncronizeMenu then
453 OnBoardSyncronizeMenu( inHandle );
457 // =========================================================================
458 // TShitarabaThreadItem
459 // =========================================================================
461 // *************************************************************************
462 //
\83R
\83\93\83X
\83g
\83\89\83N
\83^
463 // *************************************************************************
464 constructor TShitarabaThreadItem.Create(
469 uriList : TStringList;
474 OnDownload := Download;
478 OnGetHeader := GetHeader;
479 OnGetFooter := GetFooter;
480 OnGetBoardURL := GetBoardURL;
483 FIsTemporary := False;
487 uri := TIdURI.Create( ReadURL );
488 uriList := TStringList.Create;
490 ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
491 FileName := uriList[ 5 ] + '.dat';
492 FilePath := MyLogFolder + uriList[ 3 ] + '\' + uriList[ 4 ] + '\' + uriList[ 5 ] + '.dat';
493 IsLogFile := FileExists( FilePath );
501 // *************************************************************************
502 //
\83f
\83X
\83g
\83\89\83N
\83^
503 // *************************************************************************
504 destructor TShitarabaThreadItem.Destroy;
509 //
\88ê
\8e\9e\83t
\83@
\83C
\83\8b\82Ì
\8fê
\8d\87\82Í
\8dí
\8f\9c\82·
\82é
511 DeleteFile( FilePath );
517 // *************************************************************************
518 //
\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½
519 // *************************************************************************
520 function TShitarabaThreadItem.Download : TDownloadState;
524 downResult : TStringList;
525 responseCode : Longint;
526 logStream : TFileStream;
528 uriList : TStringList;
535 uri := TIdURI.Create( ReadURL );
536 uriList := TStringList.Create;
538 ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
539 FileName := uriList[ 5 ] + '.dat';
540 // http://jbbs.shitaraba.com/bbs/rawmode.cgi/game/1578/1067968274/l100
541 // protocol://host/1/2/3/4/5/uriList.Count - 1
542 if MyLogFolder = '' then begin
543 //
\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¶
544 FilePath := TemporaryFile;
545 FIsTemporary := True;
547 FilePath := MyLogFolder + uriList[ 3 ] + '\' + uriList[ 4 ] + '\' + uriList[ 5 ] + '.dat';
548 FIsTemporary := False;
555 //
\95Û
\91¶
\97p
\82Ì
\83f
\83B
\83\8c\83N
\83g
\83\8a\82ð
\8c@
\82é
556 ForceDirectoriesEx( Copy( FilePath, 1, LastDelimiter( '\', FilePath ) ) );
558 //
\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Í
559 // InternalDownload
\82É
\94C
\82¹
\82é
\82±
\82Æ
\82ª
\8fo
\97\88\82é
560 modified := LastModified;
561 datURL := ReadURL + IntToStr( Count + 1 ) + '-'; //
\90V
\92\85\82Ì
\82Ý
562 responseCode := InternalDownload( PChar( datURL ), modified, tmp, 0 );
565 if (responseCode = 200) or (responseCode = 206) then begin
566 downResult := TStringList.Create;
568 tmpText := CustomStringReplace( string( tmp ), '¡÷¡®', ',' );
569 downResult.Text := EUCtoSJIS( tmpText );
570 ArrangeDownloadData(Count, downResult);
571 if downResult.Count > 0 then begin
572 if FileExists( FilePath ) then
573 logStream := TFileStream.Create( FilePath, fmOpenReadWrite or fmShareDenyWrite )
575 logStream := TFileStream.Create( FilePath, fmCreate or fmShareDenyWrite );
577 logStream.Position := logStream.Size;
578 logStream.Write( PChar( downResult.Text )^, Length( downResult.Text ) );
588 Result := dsDiffComplete;
590 Size := Size + Length( downResult.Text );
591 // CGI
\82©
\82ç
\82Í
\90³
\82µ
\82¢
\93ú
\95t
\82ª
\93¾
\82ç
\82ê
\82È
\82¢
\82Ì
\82Å
\8c»
\8dÝ
\82É
\90Ý
\92è
596 NewReceive := Count + 1;
597 Count := Count + downResult.Count;
598 NewResCount := downResult.Count;
603 Result := dsNotModify;
608 end else if responseCode = 304 then begin
609 Result := dsNotModify;
612 DisposeResultString( tmp );
616 // *************************************************************************
617 // download
\82µ
\82Ä
\82«
\82½Dat
\82Ì
\82 \82Ú
\81[
\82ñ
\82³
\82ê
\82½
\95ª
\82ð
\95â
\8f[
\82µ
\82Ä
\81A
618 //
\83\8c\83X
\90\94\82Æ
\88ê
\92v
\82·
\82é
\82æ
\82¤
\82É
\82·
\82é
619 // *************************************************************************
620 procedure TShitarabaThreadItem.ArrangeDownloadData(
621 start: Integer; //
\90V
\8bK
\81F
\82O
\81@
\92Ç
\8bL
\81F
\91O
\89ñ
\82Ü
\82Å
\82Ì
\8eæ
\93¾
\90\94
622 var Data: TStringList //Dat
\82Ì
\83f
\81[
\83^
630 while i < Data.count + start do begin
632 tmp := Copy(Data[i - start], 1 , AnsiPos('<>', Data[ i - start ] )-1 );
635 if n > i + 1 then begin
636 Data.Insert(i - start, Format('%d<><><><><><>', [i+1]));
650 // *************************************************************************
651 //
\8f\91\82«
\8d\9e\82Ý
\82ð
\8ew
\8e¦
\82³
\82ê
\82½
652 // *************************************************************************
653 function TShitarabaThreadItem.Write(
654 inName : string; //
\96¼
\91O(
\83n
\83\93\83h
\83\8b)
655 inMail : string; //
\83\81\81[
\83\8b\83A
\83h
\83\8c\83X
656 inMessage : string //
\96{
\95¶
657 ) : TDownloadState; //
\8f\91\82«
\8d\9e\82Ý
\82ª
\90¬
\8c÷
\82µ
\82½
\82©
\82Ç
\82¤
\82©
662 uriList : TStringList;
663 responseCode : Integer;
666 uri := TIdURI.Create( URL );
667 uriList := TStringList.Create;
669 ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
671 // http://jbbs.shitaraba.com/bbs/read.cgi/game/1578/1067968274/l100
673 'NAME=' + HttpEncode( SJIStoEUC( inName ) ) +
674 '&MAIL=' + HttpEncode( SJIStoEUC( inMail ) ) +
675 '&MESSAGE=' + HttpEncode( SJIStoEUC( inMessage ) ) +
676 '&BBS=' + uriList[ 4 ] +
677 '&KEY=' + uriList[ 5 ] +
678 '&DIR=' + uriList[ 3 ] +
679 '&TIME=' + IntToStr( DateTimeToUnix( Now ) ) +
680 '&submit=' + HttpEncode( SJIStoEUC( '
\8f\91\82«
\8d\9e\82Þ' ) );
682 //
\93Æ
\8e©
\82É
\92Ê
\90M
\82µ
\82È
\82¢
\8fê
\8d\87\82Í InternalPost
\82É
\94C
\82¹
\82é
\82±
\82Æ
\82ª
\8fo
\97\88\82é
683 responseCode := InternalPost( PChar( WriteURL ), PChar( postData ), postResult );
685 if (responseCode = 200) or
686 ((responseCode = 302) and (Length( Trim( postResult ) ) = 0)) then begin
690 if Assigned( InternalPrint ) then
691 InternalPrint( postResult );
694 DisposeResultString( postResult );
703 // *************************************************************************
704 //
\83\8c\83X
\94Ô
\8d\86 inNo
\82É
\91Î
\82·
\82é html
\82ð
\97v
\8b\81\82³
\82ê
\82½
705 // *************************************************************************
706 function TShitarabaThreadItem.GetRes(
707 inNo : Integer //
\97v
\8b\81\82³
\82ê
\82½
\83\8c\83X
\94Ô
\8d\86
708 ) : string; //
\91Î
\89\9e\82·
\82é HTML
714 //
\93Æ
\8e©
\82É
\83t
\83B
\83\8b\83^
\83\8a\83\93\83O
\82ð
\8ds
\82í
\82È
\82¢
\8fê
\8d\87\82Í
715 // InternalAbon
\82¨
\82æ
\82Ñ Dat2HTML
\82É
\94C
\82¹
\82é
\82±
\82Æ
\82ª
\8fo
\97\88\82é
718 if FDat = nil then begin
719 //
\83\8d\83O
\82É
\91¶
\8dÝ
\82µ
\82È
\82¢
\82Ì
\82Å
\82±
\82Ì
\82Ü
\82Ü
\8fI
\97¹
723 res := Copy( FDat[ inNo - 1 ], AnsiPos( '<>', FDat[ inNo - 1 ] ) + 2, MaxInt );
725 res := GetDat( inNo );
726 tmp := InternalAbonForOne( PChar( res ), PChar( FilePath ),inNo );
728 Result := Dat2HTML( string( tmp ), inNo );
730 DisposeResultString( tmp );
735 // *************************************************************************
736 //
\83\8c\83X
\94Ô
\8d\86 inNo
\82É
\91Î
\82·
\82é Dat
\82ð
\97v
\8b\81\82³
\82ê
\82½
737 // *************************************************************************
738 function TShitarabaThreadItem.GetDat(
739 inNo : Integer //
\97v
\8b\81\82³
\82ê
\82½
\83\8c\83X
\94Ô
\8d\86
740 ) : string; //
\82Q
\82¿
\82á
\82ñ
\82Ë
\82é
\82ÌDat
\8c`
\8e®
743 tmp : array[1..5] of string;
747 //
\93Æ
\8e©
\82É
\83t
\83B
\83\8b\83^
\83\8a\83\93\83O
\82ð
\8ds
\82í
\82È
\82¢
\8fê
\8d\87\82Í
748 // InternalAbon
\82¨
\82æ
\82Ñ Dat2HTML
\82É
\94C
\82¹
\82é
\82±
\82Æ
\82ª
\8fo
\97\88\82é
750 if FDat = nil then begin
751 //
\83\8d\83O
\82É
\91¶
\8dÝ
\82µ
\82È
\82¢
\82Ì
\82Å
\82±
\82Ì
\82Ü
\82Ü
\8fI
\97¹
757 res := Copy( FDat[ inNo - 1 ], AnsiPos( '<>', FDat[ inNo - 1 ] ) + 2, MaxInt );
758 //
\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é
759 //
\96¼
\91O<>
\83\81\81[
\83\8b<>
\93ú
\95t<>
\96{
\95¶<>
\83X
\83\8c\83^
\83C<>ID
760 for i := 0 to 4 do begin
761 tmp[ i + 1 ] := Copy( res, 1, AnsiPos('<>', res) - 1 );
762 Delete( res, 1, AnsiPos('<>', res) + 1 );
764 //
\96¼
\91O<>
\83\81\81[
\83\8b<>
\93ú
\95tID<>
\96{
\95¶<>
\83X
\83\8c\83^
\83C
765 Result := tmp[1] + '<>' + tmp[2] + '<>' + tmp[3] + ' ' + res + '<>'+ tmp[4] + '<>' +tmp[5];
772 // *************************************************************************
773 //
\83X
\83\8c\83b
\83h
\82Ì
\83w
\83b
\83_ html
\82ð
\97v
\8b\81\82³
\82ê
\82½
774 // *************************************************************************
775 function TShitarabaThreadItem.GetHeader(
776 inOptionalHeader : string
780 //
\93Æ
\8e©
\82É
\83t
\83B
\83\8b\83^
\83\8a\83\93\83O
\82ð
\8ds
\82í
\82È
\82¢
\8fê
\8d\87\82Í
781 // InternalHeader
\82É
\94C
\82¹
\82é
\82±
\82Æ
\82ª
\8fo
\97\88\82é
782 Result := InternalHeader(
783 '<meta http-equiv="Content-type" content="text/html; charset=Shift_JIS">' +
787 // GetRes
\82ð
\8cÄ
\82Î
\82ê
\82é
\82±
\82Æ
\82ª
\97\
\91z
\82³
\82ê
\82é
\82Ì
\82Å FDat
\82ð
\90¶
\90¬
\82µ
\82Ä
\82¨
\82
796 // *************************************************************************
797 //
\83X
\83\8c\83b
\83h
\82Ì
\83t
\83b
\83^ html
\82ð
\97v
\8b\81\82³
\82ê
\82½
798 // *************************************************************************
799 function TShitarabaThreadItem.GetFooter(
800 inOptionalFooter : string
804 //
\93Æ
\8e©
\82É
\83t
\83B
\83\8b\83^
\83\8a\83\93\83O
\82ð
\8ds
\82í
\82È
\82¢
\8fê
\8d\87\82Í
805 // InternalFooter
\82É
\94C
\82¹
\82é
\82±
\82Æ
\82ª
\8fo
\97\88\82é
806 Result := InternalFooter( inOptionalFooter );
808 //
\82à
\82¤ GetRes
\82Í
\8cÄ
\82Î
\82ê
\82È
\82¢
\82Æ
\8ev
\82¤
\82Ì
\82Å FDat
\82ð
\8aJ
\95ú
\82µ
\82Ä
\82¨
\82
816 // *************************************************************************
817 //
\82±
\82Ì ThreadItem
\82ª
\91®
\82·
\82é
\94Â
\82Ì URL
\82ð
\97v
\8b\81\82³
\82ê
\82½
818 // *************************************************************************
819 function TShitarabaThreadItem.GetBoardURL : string;
822 uriList : TStringList;
825 uri := TIdURI.Create( ReadURL );
826 uriList := TStringList.Create;
828 ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
829 FileName := uriList[ 5 ] + '.dat';
830 // http://jbbs.shitaraba.com/bbs/read.cgi/game/1578/1067968274/l100
831 // http://jbbs.shitaraba.com/game/1000/subject.txt
832 Result := CreateResultString(
833 uri.Protocol + '://' + uri.Host + '/' + uriList[ 3 ] + '/' + uriList[ 4 ] + '/' );
841 // *************************************************************************
843 // *************************************************************************
844 procedure TShitarabaThreadItem.LoadDat;
847 if FDat = nil then begin
848 if IsLogFile then begin
849 // dat
\82Ì
\93Ç
\82Ý
\8d\9e\82Ý
850 FDat := TStringList.Create;
851 FDat.LoadFromFile( FilePath );
857 // *************************************************************************
859 // *************************************************************************
860 procedure TShitarabaThreadItem.FreeDat;
863 if FDat <> nil then begin
870 // *************************************************************************
871 //
\88À
\91S
\82È
\83u
\83\89\83E
\83U
\95\
\8e¦
\97p
\82Ì URL
872 // *************************************************************************
873 function TShitarabaThreadItem.BrowsableURL : string;
876 uriList : TStringList;
881 foundPos := AnsiPos( '?', URL );
882 if foundPos > 0 then begin
884 uri := TIdURI.Create( URL );
885 uriList := TStringList.Create;
887 ExtractHttpFields( ['/'], [], uri.Path, uriList );
889 ExtractHttpFields( ['&'], [], Copy( URL, foundPos + 1, MaxInt ), uriList );
891 uri.Protocol + '://' + uri.Host + '/bbs/read.cgi/' +
892 dir + '/' + uriList.Values[ 'BBS' ] + '/' + uriList.Values[ 'KEY' ] + '/l100';
898 if Copy( URL, Length( URL ), 1 ) = '/' then
899 uri := TIdURI.Create( URL )
901 uri := TIdURI.Create( URL + '/' );
902 uriList := TStringList.Create;
904 ExtractHttpFields( ['/'], [], uri.Path, uriList );
906 uri.Protocol + '://' + uri.Host + '/bbs/read.cgi/' +
907 uriList[ 3 ] + '/' + uriList[ 4 ] + '/' + uriList[ 5 ] + '/l100';
916 // *************************************************************************
917 //
\88À
\91S
\82È( '/'
\82Å
\8fI
\82í
\82é )
\93Ç
\82Ý
\8d\9e\82Ý
\82Ì URL
918 // *************************************************************************
919 function TShitarabaThreadItem.ReadURL : string;
922 uriList : TStringList;
927 foundPos := AnsiPos( '?', URL );
928 if foundPos > 0 then begin
930 uri := TIdURI.Create( URL );
931 uriList := TStringList.Create;
933 ExtractHttpFields( ['/'], [], uri.Path, uriList );
935 ExtractHttpFields( ['&'], [], Copy( URL, foundPos + 1, MaxInt ), uriList );
936 // http://jbbs.shitaraba.com/bbs/read.cgi?DIR=game&BBS=1578&KEY=1067968274
938 uri.Protocol + '://' + uri.Host + '/bbs/rawmode.cgi/' +
939 dir + '/' + uriList.Values[ 'BBS' ] + '/' + uriList.Values[ 'KEY' ] + '/';
945 if Copy( URL, Length( URL ), 1 ) = '/' then
946 uri := TIdURI.Create( URL )
948 uri := TIdURI.Create( URL + '/' );
949 uriList := TStringList.Create;
951 ExtractHttpFields( ['/'], [], uri.Path, uriList );
952 // http://jbbs.shitaraba.com/bbs/read.cgi/game/1578/1067968274/l100
954 uri.Protocol + '://' + uri.Host + '/bbs/rawmode.cgi/' +
955 uriList[ 3 ] + '/' + uriList[ 4 ] + '/' + uriList[ 5 ] + '/';
964 // *************************************************************************
965 //
\88À
\91S
\82È( '/'
\82Å
\8fI
\82í
\82é )
\8f\91\82«
\8d\9e\82Ý
\82Ì URL
966 // *************************************************************************
967 function TShitarabaThreadItem.WriteURL : string;
970 uriList : TStringList;
973 if Copy( URL, Length( URL ), 1 ) = '/' then
974 uri := TIdURI.Create( URL )
976 uri := TIdURI.Create( URL + '/' );
977 uriList := TStringList.Create;
979 ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
980 // http://jbbs.shitaraba.com/bbs/read.cgi/game/1578/1067968274/l100
982 uri.Protocol + '://' + uri.Host + '/bbs/write.cgi/' +
983 uriList[ 3 ] + '/' + uriList[ 4 ] + '/' + uriList[ 5 ] + '/';
991 // *************************************************************************
992 // TThreadItem
\82ª
\90¶
\90¬
\82³
\82ê
\82½
\8fê
\8d\87\82Ì
\8f\88\92u(TShitarabaThreadItem
\82ð
\90¶
\90¬
\82·
\82é)
993 // *************************************************************************
994 procedure ThreadItemOnCreateOfTShitarabaThreadItem(
998 threadItem : TShitarabaThreadItem;
1001 threadItem := TShitarabaThreadItem.Create( inInstance );
1002 ThreadItemSetLong( inInstance, tipContext, DWORD( threadItem ) );
1006 // *************************************************************************
1007 // TThreadItem
\82ª
\94j
\8aü
\82³
\82ê
\82½
\8fê
\8d\87\82Ì
\8f\88\92u(TShitarabaThreadItem
\82ð
\94j
\8aü
\82·
\82é)
1008 // *************************************************************************
1009 procedure ThreadItemOnDisposeOfTShitarabaThreadItem(
1013 threadItem : TShitarabaThreadItem;
1016 threadItem := TShitarabaThreadItem( ThreadItemGetLong( inInstance, tipContext ) );
1021 // =========================================================================
1022 // TShitarabaBoardItem
1023 // =========================================================================
1025 // *************************************************************************
1026 //
\83R
\83\93\83X
\83g
\83\89\83N
\83^
1027 // *************************************************************************
1028 constructor TShitarabaBoardItem.Create(
1033 uriList : TStringList;
1038 OnDownload := Download;
1039 OnCreateThread := CreateThread;
1040 OnEnumThread := EnumThread;
1041 OnFileName2ThreadURL := ToThreadURL;
1044 FIsTemporary := False;
1047 uri := TIdURI.Create( SubjectURL );
1048 uriList := TStringList.Create;
1050 ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
1051 // http://jbbs.shitaraba.com/game/1000/subject.txt
1052 FilePath := MyLogFolder + uriList[ 1 ] + '\' + uriList[ 2 ] + '\' + uri.Document;
1053 IsLogFile := FileExists( FilePath );
1061 // *************************************************************************
1062 //
\83f
\83X
\83g
\83\89\83N
\83^
1063 // *************************************************************************
1064 destructor TShitarabaBoardItem.Destroy;
1067 if FDat <> nil then begin
1075 //
\88ê
\8e\9e\83t
\83@
\83C
\83\8b\82Ì
\8fê
\8d\87\82Í
\8dí
\8f\9c\82·
\82é
1076 if FIsTemporary then
1077 DeleteFile( FilePath );
1083 // *************************************************************************
1084 //
\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½
1085 // *************************************************************************
1086 function TShitarabaBoardItem.Download : TDownloadState;
1090 responseCode : Longint;
1092 uriList : TStringList;
1099 if FDat <> nil then begin
1106 FDat := TStringList.Create;
1107 uri := TIdURI.Create( SubjectURL );
1108 uriList := TStringList.Create;
1109 //
\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Í
1110 // InternalDownload
\82É
\94C
\82¹
\82é
\82±
\82Æ
\82ª
\8fo
\97\88\82é
1111 modified := LastModified;
1112 responseCode := InternalDownload( PChar( uri.URI ), modified, downResult );
1114 if responseCode = 200 then begin
1116 //
\83p
\83X
\82ð
\8eZ
\8fo
1117 ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
1118 if MyLogFolder = '' then begin
1119 //
\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¶
1120 FilePath := TemporaryFile;
1121 FIsTemporary := True;
1123 FilePath := MyLogFolder + uriList[ 1 ] + '\' + uriList[ 2 ] + '\' + uri.Document;
1124 FIsTemporary := False
1127 //
\95Û
\91¶
\97p
\82Ì
\83f
\83B
\83\8c\83N
\83g
\83\8a\82ð
\8c@
\82é
1128 ForceDirectoriesEx( Copy( FilePath, 1, LastDelimiter( '\', FilePath ) ) );
1130 // EUC
\82ð Shift_JIS
\82É
1131 tmpText := CustomStringReplace( string( downResult ), '¡÷¡®', ',');
1132 FDat.Text := EUCtoSJIS( tmpText );
1133 //
\82µ
\82½
\82ç
\82Î JBBS
\82Í
\83`
\83F
\83b
\83N
\97p
\82É
\90æ
\93ª
\82Æ
\8dÅ
\8fI
\8ds
\82ª
\93¯
\82¶
1134 i := FDat.Count - 1;
1135 if i > 0 then // 1
\8cÂ
\82¾
\82Á
\82½
\82ç
\8fã
\89º
\82à
\82
\82»
\82à
\96³
\82¢
\82©
\82ç 0
\82Í
\8aÜ
\82Ü
\82¸
1136 if FDat[ 0 ] = FDat[ i ] then
1139 FDat.SaveToFile( FilePath );
1143 LastModified := modified;
1149 Result := dsComplete;
1152 DisposeResultString( downResult );
1157 // *************************************************************************
1158 //
\83X
\83\8c\97§
\82Ä
\82ð
\8ew
\8e¦
\82³
\82ê
\82½
1159 // *************************************************************************
1160 function TShitarabaBoardItem.CreateThread(
1161 inSubject : string; //
\83X
\83\8c\83^
\83C
1162 inName : string; //
\96¼
\91O(
\83n
\83\93\83h
\83\8b)
1163 inMail : string; //
\83\81\81[
\83\8b\83A
\83h
\83\8c\83X
1164 inMessage : string //
\96{
\95¶
1165 ) : TDownloadState; //
\8f\91\82«
\8d\9e\82Ý
\82ª
\90¬
\8c÷
\82µ
\82½
\82©
\82Ç
\82¤
\82©
1171 uriList : TStringList;
1172 responseCode : Integer;
1175 uri := TIdURI.Create( URL );
1176 uriList := TStringList.Create;
1178 ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
1180 // http://jbbs.shitaraba.com/bbs/write.cgi/game/1578/new/
1181 // http://jbbs.shitaraba.com/game/1000/subject.txt
1183 uri.Protocol + '://' + uri.Host + '/bbs/write.cgi/' +
1184 uriList[ 1 ] + '/' + uriList[ 2 ] + '/new/';
1186 'SUBJECT=' + HttpEncode( SJIStoEUC( inSubject ) ) +
1187 '&NAME=' + HttpEncode( SJIStoEUC( inName ) ) +
1188 '&MAIL=' + HttpEncode( SJIStoEUC( inMail ) ) +
1189 '&MESSAGE=' + HttpEncode( SJIStoEUC( inMessage ) ) +
1190 '&BBS=' + uriList[ 4 ] +
1191 '&DIR=' + uriList[ 3 ] +
1192 '&TIME=' + IntToStr( DateTimeToUnix( Now ) ) +
1193 '&submit=' + HttpEncode( SJIStoEUC( '
\90V
\8bK
\8f\91\82«
\8d\9e\82Ý' ) );
1195 //
\93Æ
\8e©
\82É
\92Ê
\90M
\82µ
\82È
\82¢
\8fê
\8d\87\82Í InternalPost
\82É
\94C
\82¹
\82é
\82±
\82Æ
\82ª
\8fo
\97\88\82é
1196 responseCode := InternalPost( PChar( postURL ), PChar( postData ), postResult );
1198 if (responseCode = 200) or
1199 ((responseCode = 302) and (Length( Trim( postResult ) ) = 0)) then begin
1200 Result := dsComplete
1203 if Assigned( InternalPrint ) then
1204 InternalPrint( postResult );
1207 DisposeResultString( postResult );
1216 // *************************************************************************
1217 //
\83X
\83\8c\88ê
\97\97\82Ì URL
\82©
\82ç
\83X
\83\8c\83b
\83h
\82Ì URL
\82ð
\93±
\82«
\8fo
\82·
1218 // *************************************************************************
1219 function TShitarabaBoardItem.ToThreadURL(
1220 inFileName : string //
\83X
\83\8c\83b
\83h
\83t
\83@
\83C
\83\8b\96¼
1221 ) : string; //
\83X
\83\8c\83b
\83h
\82Ì URL
1225 uriList : TStringList;
1229 found := AnsiPos( '.', inFileName );
1231 inFileName := Copy( inFileName, 1, found - 1 );
1233 uri := TIdURI.Create( SubjectURL );
1234 uriList := TStringList.Create;
1237 ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
1238 threadURL := uri.Protocol + '://' + uri.Host + '/bbs/read.cgi/' +
1239 uriList[ 1 ] + '/' + uriList[ 2 ] + '/' + inFileName + '/l100';
1240 Result := threadURL;
1251 // *************************************************************************
1252 //
\82±
\82Ì
\94Â
\82É
\82¢
\82
\82Â
\82Ì
\83X
\83\8c\82ª
\82 \82é
\82©
\97v
\8b\81\82³
\82ê
\82½
1253 // *************************************************************************
1254 procedure TShitarabaBoardItem.EnumThread(
1255 inCallBack : TBoardItemEnumThreadCallBack
1259 uriList : TStringList;
1263 if FDat = nil then begin
1264 FDat := TStringList.Create;
1265 uri := TIdURI.Create( SubjectURL );
1266 uriList := TStringList.Create;
1268 //
\83p
\83X
\82ð
\8eZ
\8fo
1269 ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
1270 // http://jbbs.shitaraba.com/game/1000/subject.txt
1271 FilePath := MyLogFolder + uriList[ 1 ] + '\' + uriList[ 2 ] + '\' + uri.Document;
1272 if FileExists( FilePath ) then
1273 //
\93Ç
\82Ý
\8d\9e\82Ý
1274 FDat.LoadFromFile( FilePath );
1281 //
\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é
1282 inherited EnumThread( inCallBack, CustomStringReplace( FDat.Text, ',', '<>' ) );
1288 // *************************************************************************
1289 //
\83X
\83\8c\88ê
\97\97\82Ì URL
\82ð
\8b\81\82ß
\82é
1290 // *************************************************************************
1291 function TShitarabaBoardItem.SubjectURL : string;
1294 uriList : TStringList;
1297 uri := TIdURI.Create( URL );
1298 uriList := TStringList.Create;
1300 if uri.Document <> SUBJECT_NAME then begin
1301 if Copy( URL, Length( URL ), 1 ) = '/' then
1302 Result := URL + SUBJECT_NAME
1304 Result := URL + '/' + SUBJECT_NAME;
1306 //
\82±
\82±
\82É
\82Í
\97\88\82È
\82¢
\82Æ
\8ev
\82¤
\82¯
\82Ç
1316 // *************************************************************************
1317 // TBoardItem
\82ª
\90¶
\90¬
\82³
\82ê
\82½
\8fê
\8d\87\82Ì
\8f\88\92u(TShitarabaBoardItem
\82ð
\90¶
\90¬
\82·
\82é)
1318 // *************************************************************************
1319 procedure BoardItemOnCreateOfTShitarabaBoardItem(
1323 boardItem : TShitarabaBoardItem;
1326 boardItem := TShitarabaBoardItem.Create( inInstance );
1327 BoardItemSetLong( inInstance, bipContext, DWORD( boardItem ) );
1331 // *************************************************************************
1332 // TBoardItem
\82ª
\94j
\8aü
\82³
\82ê
\82½
\8fê
\8d\87\82Ì
\8f\88\92u(TShitarabaBoardItem
\82ð
\94j
\8aü
\82·
\82é)
1333 // *************************************************************************
1334 procedure BoardItemOnDisposeOfTShitarabaBoardItem(
1338 boardItem : TShitarabaBoardItem;
1341 boardItem := TShitarabaBoardItem( BoardItemGetLong( inInstance, bipContext ) );
1348 // =========================================================================
1349 //
\83G
\83\93\83g
\83\8a\83|
\83C
\83\93\83g
1350 // =========================================================================
1352 ul_reason_for_call : DWORD
1358 case ul_reason_for_call of
1363 module := GetModuleHandle( nil );
1365 LoadInternalAPI( module );
1366 LoadInternalFilePathAPI( module );
1367 LoadInternalThreadItemAPI( module );
1368 LoadInternalBoardItemAPI( module );
1370 // =====
\83C
\83\93\83X
\83^
\83\93\83X
\82Ì
\8eæ
\82è
\88µ
\82¢
\82ð TThreadItem
\82©
\82ç TShitarabaThreadItem
\82É
\95Ï
\8dX
\82·
\82é
1371 ThreadItemOnCreate := ThreadItemOnCreateOfTShitarabaThreadItem;
1372 ThreadItemOnDispose := ThreadItemOnDisposeOfTShitarabaThreadItem;
1373 // =====
\83C
\83\93\83X
\83^
\83\93\83X
\82Ì
\8eæ
\82è
\88µ
\82¢
\82ð TBoardItem
\82©
\82ç TShitarabaBoardItem
\82É
\95Ï
\8dX
\82·
\82é
1374 BoardItemOnCreate := BoardItemOnCreateOfTShitarabaBoardItem;
1375 BoardItemOnDispose := BoardItemOnDisposeOfTShitarabaBoardItem;
1379 RemovePlugInMenu( SyncronizeMenu );
1398 DllProc := @DLLEntry;
1399 DLLEntry( DLL_PROCESS_ATTACH );