1 library ShitarabaJBBSPlugIn;
5 \82µ
\82½
\82ç
\82Î
\8f\88\97\9d\83\86\83j
\83b
\83g
15 PlugInMain in 'PlugInMain.pas',
16 ThreadItem in 'ThreadItem.pas',
17 BoardItem in 'BoardItem.pas',
18 FilePath in 'FilePath.pas',
19 Y_TextConverter in 'Y_TextConverter.pas',
20 MojuUtils in '..\..\MojuUtils.pas';
25 // =========================================================================
26 // TShitarabaThreadItem
27 // =========================================================================
28 TShitarabaThreadItem = class(TThreadItem)
30 FIsTemporary : Boolean;
34 constructor Create( inInstance : DWORD );
35 destructor Destroy; override;
38 function Download : TDownloadState;
39 function Write( inName : string; inMail : string; inMessage : string ) : TDownloadState;
40 function GetRes( inNo : Integer ) : string;
41 function GetDat( inNo : Integer ) : string;
42 function GetHeader( inOptionalHeader : string ) : string;
43 function GetFooter( inOptionalFooter : string ) : string;
44 function GetBoardURL : string;
48 function BrowsableURL : string;
49 function ReadURL : string;
50 function WriteURL : string;
53 // =========================================================================
54 // TShitarabaBoardItem
55 // =========================================================================
56 TShitarabaBoardItem = class(TBoardItem)
58 FIsTemporary : Boolean;
62 constructor Create( inInstance : DWORD );
63 destructor Destroy; override;
66 function Download : TDownloadState;
67 function CreateThread( inSubject : string; inName : string; inMail : string; inMessage : string ) : TDownloadState;
68 function ToThreadURL( inFileName : string ) : string;
69 procedure EnumThread( inCallBack : TBoardItemEnumThreadCallBack );
71 function SubjectURL : string;
75 LOG_DIR = 'ShitarabaJBBS\';
76 SUBJECT_NAME = 'subject.txt';
78 PLUGIN_NAME = 'ShitarabaJBBS';
81 RELEASE_VERSION = 'beta';
82 REVISION_VERSION = 12;
84 // =========================================================================
86 // =========================================================================
88 // *************************************************************************
89 //
\83e
\83\93\83|
\83\89\83\8a\82È
\83p
\83X
\82Ì
\8eæ
\93¾
90 // *************************************************************************
91 function TemporaryFile : string;
93 tempPath : array [0..MAX_PATH] of char;
96 GetTempPath( SizeOf(tempPath), tempPath );
98 Result := tempPath + IntToStr( Random( $7fffffff ) );
99 until not FileExists( Result );
103 // *************************************************************************
104 //
\82µ
\82½
\82ç
\82Î
\97p
\83\8d\83O
\83t
\83H
\83\8b\83_
\8eæ
\93¾
105 // *************************************************************************
106 function MyLogFolder : string;
112 if Length( folder ) = 0 then
115 Result := folder + LOG_DIR;
119 (*************************************************************************
120 *
\83f
\83B
\83\8c\83N
\83g
\83\8a\82ª
\91¶
\8dÝ
\82·
\82é
\82©
\83`
\83F
\83b
\83N
121 *************************************************************************)
122 function DirectoryExistsEx(const Name: string): Boolean;
126 Code := GetFileAttributes(PChar(Name));
127 Result := (Code <> -1) and (FILE_ATTRIBUTE_DIRECTORY and Code <> 0);
130 (*************************************************************************
131 *
\83f
\83B
\83\8c\83N
\83g
\83\8a\8dì
\90¬
\81i
\95¡
\90\94\8aK
\91w
\91Î
\89\9e\81j
132 *************************************************************************)
133 function ForceDirectoriesEx(Dir: string): Boolean;
136 if Length(Dir) = 0 then
137 raise Exception.Create('
\83t
\83H
\83\8b\83_
\82ª
\8dì
\90¬
\8fo
\97\88\82Ü
\82¹
\82ñ');
138 Dir := ExcludeTrailingPathDelimiter(Dir);
139 if (Length(Dir) < 3) or DirectoryExistsEx(Dir)
140 or (ExtractFilePath(Dir) = Dir) then Exit; // avoid 'xyz:\' problem.
141 Result := ForceDirectoriesEx(ExtractFilePath(Dir)) and CreateDir(Dir);
144 //
\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
145 procedure ExtractHttpFields(
146 const chrSep : TSysCharSet;
147 const chrWhite : TSysCharSet;
148 const strValue : string;
149 var strResult : TStringList;
150 unknownFlag : boolean = false
153 last, p, strLen : Integer;
156 strLen := Length( strValue );
163 if strValue[ p ] in chrSep then
165 strResult.Add( Copy( strValue, last, p - last ) );
174 strResult.Add( Copy( strValue, last, strLen - last + 1 ) );
178 \rfunction HttpEncode(
179 \r const strValue : string
187 kHexCode : array [0..15] of char = (
188 '0', '1', '2', '3', '4', '5', '6', '7',
189 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' );
192 strLen := Length( strValue );
198 case strValue[ i ] of
199 '0' .. '9', 'a' .. 'z', 'A' .. 'Z', '*', '-', '.', '@', '_':
201 strResult := strResult + strValue[ i ];
205 b := Integer( strValue[ i ] );
206 strResult := strResult + '%'
207 + kHexCode[ b div $10 ]
208 + kHexCode[ b mod $10 ];
222 // =========================================================================
224 // =========================================================================
226 // *************************************************************************
227 //
\83v
\83\89\83O
\83C
\83\93\82Ì
\83o
\81[
\83W
\83\87\83\93\82ð
\97v
\8b\81\82³
\82ê
\82½
228 // *************************************************************************
229 procedure OnVersionInfo(
230 var outAgent : PChar; //
\83o
\81[
\83W
\83\87\83\93\82ð
\88ê
\90Ø
\8aÜ
\82Ü
\82È
\82¢
\8f\83\90\88\82È
\96¼
\8fÌ
231 var outMajor : DWORD; //
\83\81\83W
\83\83\81[
\83o
\81[
\83W
\83\87\83\93
232 var outMinor : DWORD; //
\83}
\83C
\83i
\81[
\83o
\81[
\83W
\83\87\83\93
233 var outRelease : PChar; //
\83\8a\83\8a\81[
\83X
\92i
\8aK
\96¼
234 var outRevision : DWORD //
\83\8a\83r
\83W
\83\87\83\93\83i
\83\93\83o
\81[
239 outAgent := CreateResultString( PChar( PLUGIN_NAME ) );
240 outMajor := MAJOR_VERSION;
241 outMinor := MINOR_VERSION;
242 outRelease := CreateResultString( PChar( RELEASE_VERSION ) );
243 outRevision := REVISION_VERSION;
254 // *************************************************************************
255 //
\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©
256 // *************************************************************************
257 function OnAcceptURL(
258 inURL : PChar //
\94»
\92f
\82ð
\8bÂ
\82¢
\82Å
\82¢
\82é URL
259 ): TAcceptType; stdcall; // URL
\82Ì
\8eí
\97Þ
262 uriList : TStringList;
265 BBS_HOST = 'jbbs.shitaraba.com';
266 THREAD_MARK = '/bbs/read.cgi';
270 //
\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é
271 uri := TIdURI.Create( inURL );
272 uriList := TStringList.Create;
274 ExtractHttpFields( ['/'], [], uri.Path, uriList );
275 foundPos := AnsiPos( BBS_HOST, uri.Host );
276 if (foundPos > 0) and (Length( uri.Host ) - foundPos + 1 = Length( BBS_HOST )) then begin
277 foundPos := ANsiPos( THREAD_MARK, inURL );
280 else if uriList.Count > 2 then //
\8dÅ
\8cã
\82ª '/'
\82Å
\95Â
\82ß
\82ç
\82ê
\82Ä
\82é
\82È
\82ç 4
285 Result := atNoAccept;
292 Result := atNoAccept;
299 // =========================================================================
300 // TShitarabaThreadItem
301 // =========================================================================
303 // *************************************************************************
304 //
\83R
\83\93\83X
\83g
\83\89\83N
\83^
305 // *************************************************************************
306 constructor TShitarabaThreadItem.Create(
311 uriList : TStringList;
316 OnDownload := Download;
320 OnGetHeader := GetHeader;
321 OnGetFooter := GetFooter;
322 OnGetBoardURL := GetBoardURL;
325 FIsTemporary := False;
329 uri := TIdURI.Create( ReadURL );
330 uriList := TStringList.Create;
332 ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
333 FileName := uriList[ 5 ] + '.dat';
334 FilePath := MyLogFolder + uriList[ 3 ] + '\' + uriList[ 4 ] + '\' + uriList[ 5 ] + '.dat';
335 IsLogFile := FileExists( FilePath );
343 // *************************************************************************
344 //
\83f
\83X
\83g
\83\89\83N
\83^
345 // *************************************************************************
346 destructor TShitarabaThreadItem.Destroy;
351 //
\88ê
\8e\9e\83t
\83@
\83C
\83\8b\82Ì
\8fê
\8d\87\82Í
\8dí
\8f\9c\82·
\82é
353 DeleteFile( FilePath );
359 // *************************************************************************
360 //
\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½
361 // *************************************************************************
362 function TShitarabaThreadItem.Download : TDownloadState;
366 downResult : TStringList;
367 responseCode : Longint;
368 logStream : TFileStream;
370 uriList : TStringList;
377 uri := TIdURI.Create( ReadURL );
378 uriList := TStringList.Create;
380 ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
381 FileName := uriList[ 5 ] + '.dat';
382 // http://jbbs.shitaraba.com/bbs/rawmode.cgi/game/1578/1067968274/l100
383 // protocol://host/1/2/3/4/5/uriList.Count - 1
384 if MyLogFolder = '' then begin
385 //
\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¶
386 FilePath := TemporaryFile;
387 FIsTemporary := True;
389 FilePath := MyLogFolder + uriList[ 3 ] + '\' + uriList[ 4 ] + '\' + uriList[ 5 ] + '.dat';
390 FIsTemporary := False;
397 //
\95Û
\91¶
\97p
\82Ì
\83f
\83B
\83\8c\83N
\83g
\83\8a\82ð
\8c@
\82é
398 ForceDirectoriesEx( Copy( FilePath, 1, LastDelimiter( '\', FilePath ) ) );
400 //
\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Í
401 // InternalDownload
\82É
\94C
\82¹
\82é
\82±
\82Æ
\82ª
\8fo
\97\88\82é
402 modified := LastModified;
403 datURL := ReadURL + IntToStr( Count + 1 ) + '-'; //
\90V
\92\85\82Ì
\82Ý
404 responseCode := InternalDownload( PChar( datURL ), modified, tmp, 0 );
407 if (responseCode = 200) or (responseCode = 206) then begin
408 downResult := TStringList.Create;
410 tmpText := CustomStringReplace( string( tmp ), '¡÷¡®', ' ' );
411 downResult.Text := EUCtoSJIS( tmpText );
412 if downResult.Count > 0 then begin
413 if FileExists( FilePath ) then
414 logStream := TFileStream.Create( FilePath, fmOpenReadWrite or fmShareDenyWrite )
416 logStream := TFileStream.Create( FilePath, fmCreate or fmShareDenyWrite );
418 logStream.Position := logStream.Size;
419 logStream.Write( PChar( downResult.Text )^, Length( downResult.Text ) );
424 NewReceive := Count + 1;
425 Count := Count + downResult.Count;
426 NewResCount := downResult.Count;
427 Size := Size + Length( downResult.Text );
429 // CGI
\82©
\82ç
\82Í
\90³
\82µ
\82¢
\93ú
\95t
\82ª
\93¾
\82ç
\82ê
\82È
\82¢
\82Ì
\82Å
\8c»
\8dÝ
\82É
\90Ý
\92è
437 Result := dsDiffComplete;
439 Result := dsNotModify;
444 end else if responseCode = 304 then begin
445 Result := dsNotModify;
448 DisposeResultString( tmp );
453 // *************************************************************************
454 //
\8f\91\82«
\8d\9e\82Ý
\82ð
\8ew
\8e¦
\82³
\82ê
\82½
455 // *************************************************************************
456 function TShitarabaThreadItem.Write(
457 inName : string; //
\96¼
\91O(
\83n
\83\93\83h
\83\8b)
458 inMail : string; //
\83\81\81[
\83\8b\83A
\83h
\83\8c\83X
459 inMessage : string //
\96{
\95¶
460 ) : TDownloadState; //
\8f\91\82«
\8d\9e\82Ý
\82ª
\90¬
\8c÷
\82µ
\82½
\82©
\82Ç
\82¤
\82©
465 uriList : TStringList;
466 responseCode : Integer;
469 uri := TIdURI.Create( URL );
470 uriList := TStringList.Create;
472 ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
474 // http://jbbs.shitaraba.com/bbs/read.cgi/game/1578/1067968274/l100
476 'NAME=' + HttpEncode( SJIStoEUC( inName ) ) +
477 '&MAIL=' + HttpEncode( SJIStoEUC( inMail ) ) +
478 '&MESSAGE=' + HttpEncode( SJIStoEUC( inMessage ) ) +
479 '&BBS=' + uriList[ 4 ] +
480 '&KEY=' + uriList[ 5 ] +
481 '&DIR=' + uriList[ 3 ] +
482 '&TIME=' + IntToStr( DateTimeToUnix( Now ) ) +
483 '&submit=' + HttpEncode( SJIStoEUC( '
\8f\91\82«
\8d\9e\82Þ' ) );
485 //
\93Æ
\8e©
\82É
\92Ê
\90M
\82µ
\82È
\82¢
\8fê
\8d\87\82Í InternalPost
\82É
\94C
\82¹
\82é
\82±
\82Æ
\82ª
\8fo
\97\88\82é
486 responseCode := InternalPost( PChar( WriteURL ), PChar( postData ), postResult );
488 if (responseCode = 200) or
489 ((responseCode = 302) and (Length( Trim( postResult ) ) = 0)) then begin
493 if Assigned( InternalPrint ) then
494 InternalPrint( postResult );
497 DisposeResultString( postResult );
506 // *************************************************************************
507 //
\83\8c\83X
\94Ô
\8d\86 inNo
\82É
\91Î
\82·
\82é html
\82ð
\97v
\8b\81\82³
\82ê
\82½
508 // *************************************************************************
509 function TShitarabaThreadItem.GetRes(
510 inNo : Integer //
\97v
\8b\81\82³
\82ê
\82½
\83\8c\83X
\94Ô
\8d\86
511 ) : string; //
\91Î
\89\9e\82·
\82é HTML
517 //
\93Æ
\8e©
\82É
\83t
\83B
\83\8b\83^
\83\8a\83\93\83O
\82ð
\8ds
\82í
\82È
\82¢
\8fê
\8d\87\82Í
518 // InternalAbon
\82¨
\82æ
\82Ñ Dat2HTML
\82É
\94C
\82¹
\82é
\82±
\82Æ
\82ª
\8fo
\97\88\82é
520 if FDat = nil then begin
521 //
\83\8d\83O
\82É
\91¶
\8dÝ
\82µ
\82È
\82¢
\82Ì
\82Å
\82±
\82Ì
\82Ü
\82Ü
\8fI
\97¹
525 res := Copy( FDat[ inNo - 1 ], AnsiPos( '<>', FDat[ inNo - 1 ] ) + 2, MaxInt );
526 tmp := InternalAbonForOne( PChar( res ), PChar( FilePath ),inNo );
528 Result := Dat2HTML( string( tmp ), inNo );
530 DisposeResultString( tmp );
535 // *************************************************************************
536 //
\83\8c\83X
\94Ô
\8d\86 inNo
\82É
\91Î
\82·
\82é Dat
\82ð
\97v
\8b\81\82³
\82ê
\82½
537 // *************************************************************************
538 function TShitarabaThreadItem.GetDat(
539 inNo : Integer //
\97v
\8b\81\82³
\82ê
\82½
\83\8c\83X
\94Ô
\8d\86
540 ) : string; //
\82Q
\82¿
\82á
\82ñ
\82Ë
\82é
\82ÌDat
\8c`
\8e®
545 //
\93Æ
\8e©
\82É
\83t
\83B
\83\8b\83^
\83\8a\83\93\83O
\82ð
\8ds
\82í
\82È
\82¢
\8fê
\8d\87\82Í
546 // InternalAbon
\82¨
\82æ
\82Ñ Dat2HTML
\82É
\94C
\82¹
\82é
\82±
\82Æ
\82ª
\8fo
\97\88\82é
548 if FDat = nil then begin
549 //
\83\8d\83O
\82É
\91¶
\8dÝ
\82µ
\82È
\82¢
\82Ì
\82Å
\82±
\82Ì
\82Ü
\82Ü
\8fI
\97¹
554 res := Copy( FDat[ inNo - 1 ], AnsiPos( '<>', FDat[ inNo - 1 ] ) + 2, MaxInt );
562 // *************************************************************************
563 //
\83X
\83\8c\83b
\83h
\82Ì
\83w
\83b
\83_ html
\82ð
\97v
\8b\81\82³
\82ê
\82½
564 // *************************************************************************
565 function TShitarabaThreadItem.GetHeader(
566 inOptionalHeader : string
570 //
\93Æ
\8e©
\82É
\83t
\83B
\83\8b\83^
\83\8a\83\93\83O
\82ð
\8ds
\82í
\82È
\82¢
\8fê
\8d\87\82Í
571 // InternalHeader
\82É
\94C
\82¹
\82é
\82±
\82Æ
\82ª
\8fo
\97\88\82é
572 Result := InternalHeader(
573 '<meta http-equiv="Content-type" content="text/html; charset=Shift_JIS">' +
577 // GetRes
\82ð
\8cÄ
\82Î
\82ê
\82é
\82±
\82Æ
\82ª
\97\
\91z
\82³
\82ê
\82é
\82Ì
\82Å FDat
\82ð
\90¶
\90¬
\82µ
\82Ä
\82¨
\82
586 // *************************************************************************
587 //
\83X
\83\8c\83b
\83h
\82Ì
\83t
\83b
\83^ html
\82ð
\97v
\8b\81\82³
\82ê
\82½
588 // *************************************************************************
589 function TShitarabaThreadItem.GetFooter(
590 inOptionalFooter : string
594 //
\93Æ
\8e©
\82É
\83t
\83B
\83\8b\83^
\83\8a\83\93\83O
\82ð
\8ds
\82í
\82È
\82¢
\8fê
\8d\87\82Í
595 // InternalFooter
\82É
\94C
\82¹
\82é
\82±
\82Æ
\82ª
\8fo
\97\88\82é
596 Result := InternalFooter( inOptionalFooter );
598 //
\82à
\82¤ GetRes
\82Í
\8cÄ
\82Î
\82ê
\82È
\82¢
\82Æ
\8ev
\82¤
\82Ì
\82Å FDat
\82ð
\8aJ
\95ú
\82µ
\82Ä
\82¨
\82
606 // *************************************************************************
607 //
\82±
\82Ì ThreadItem
\82ª
\91®
\82·
\82é
\94Â
\82Ì URL
\82ð
\97v
\8b\81\82³
\82ê
\82½
608 // *************************************************************************
609 function TShitarabaThreadItem.GetBoardURL : string;
612 uriList : TStringList;
615 uri := TIdURI.Create( ReadURL );
616 uriList := TStringList.Create;
618 ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
619 FileName := uriList[ 5 ] + '.dat';
620 // http://jbbs.shitaraba.com/bbs/read.cgi/game/1578/1067968274/l100
621 // http://jbbs.shitaraba.com/game/1000/subject.txt
622 Result := CreateResultString(
623 uri.Protocol + '://' + uri.Host + '/' + uriList[ 3 ] + '/' + uriList[ 4 ] + '/' );
631 // *************************************************************************
633 // *************************************************************************
634 procedure TShitarabaThreadItem.LoadDat;
637 if FDat = nil then begin
638 if IsLogFile then begin
639 // dat
\82Ì
\93Ç
\82Ý
\8d\9e\82Ý
640 FDat := TStringList.Create;
641 FDat.LoadFromFile( FilePath );
647 // *************************************************************************
649 // *************************************************************************
650 procedure TShitarabaThreadItem.FreeDat;
653 if FDat <> nil then begin
660 // *************************************************************************
661 //
\88À
\91S
\82È
\83u
\83\89\83E
\83U
\95\
\8e¦
\97p
\82Ì URL
662 // *************************************************************************
663 function TShitarabaThreadItem.BrowsableURL : string;
666 uriList : TStringList;
671 foundPos := AnsiPos( '?', URL );
672 if foundPos > 0 then begin
674 uri := TIdURI.Create( URL );
675 uriList := TStringList.Create;
677 ExtractHttpFields( ['/'], [], uri.Path, uriList );
679 ExtractHttpFields( ['&'], [], Copy( URL, foundPos + 1, MaxInt ), uriList );
681 uri.Protocol + '://' + uri.Host + '/bbs/read.cgi/' +
682 dir + '/' + uriList.Values[ 'BBS' ] + '/' + uriList.Values[ 'KEY' ] + '/l100';
688 if Copy( URL, Length( URL ), 1 ) = '/' then
689 uri := TIdURI.Create( URL )
691 uri := TIdURI.Create( URL + '/' );
692 uriList := TStringList.Create;
694 ExtractHttpFields( ['/'], [], uri.Path, uriList );
696 uri.Protocol + '://' + uri.Host + '/bbs/read.cgi/' +
697 uriList[ 3 ] + '/' + uriList[ 4 ] + '/' + uriList[ 5 ] + '/l100';
706 // *************************************************************************
707 //
\88À
\91S
\82È( '/'
\82Å
\8fI
\82í
\82é )
\93Ç
\82Ý
\8d\9e\82Ý
\82Ì URL
708 // *************************************************************************
709 function TShitarabaThreadItem.ReadURL : string;
712 uriList : TStringList;
717 foundPos := AnsiPos( '?', URL );
718 if foundPos > 0 then begin
720 uri := TIdURI.Create( URL );
721 uriList := TStringList.Create;
723 ExtractHttpFields( ['/'], [], uri.Path, uriList );
725 ExtractHttpFields( ['&'], [], Copy( URL, foundPos + 1, MaxInt ), uriList );
726 // http://jbbs.shitaraba.com/bbs/read.cgi?DIR=game&BBS=1578&KEY=1067968274
728 uri.Protocol + '://' + uri.Host + '/bbs/rawmode.cgi/' +
729 dir + '/' + uriList.Values[ 'BBS' ] + '/' + uriList.Values[ 'KEY' ] + '/';
735 if Copy( URL, Length( URL ), 1 ) = '/' then
736 uri := TIdURI.Create( URL )
738 uri := TIdURI.Create( URL + '/' );
739 uriList := TStringList.Create;
741 ExtractHttpFields( ['/'], [], uri.Path, uriList );
742 // http://jbbs.shitaraba.com/bbs/read.cgi/game/1578/1067968274/l100
744 uri.Protocol + '://' + uri.Host + '/bbs/rawmode.cgi/' +
745 uriList[ 3 ] + '/' + uriList[ 4 ] + '/' + uriList[ 5 ] + '/';
754 // *************************************************************************
755 //
\88À
\91S
\82È( '/'
\82Å
\8fI
\82í
\82é )
\8f\91\82«
\8d\9e\82Ý
\82Ì URL
756 // *************************************************************************
757 function TShitarabaThreadItem.WriteURL : string;
760 uriList : TStringList;
763 if Copy( URL, Length( URL ), 1 ) = '/' then
764 uri := TIdURI.Create( URL )
766 uri := TIdURI.Create( URL + '/' );
767 uriList := TStringList.Create;
769 ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
770 // http://jbbs.shitaraba.com/bbs/read.cgi/game/1578/1067968274/l100
772 uri.Protocol + '://' + uri.Host + '/bbs/write.cgi/' +
773 uriList[ 3 ] + '/' + uriList[ 4 ] + '/' + uriList[ 5 ] + '/';
781 // *************************************************************************
782 // TThreadItem
\82ª
\90¶
\90¬
\82³
\82ê
\82½
\8fê
\8d\87\82Ì
\8f\88\92u(TShitarabaThreadItem
\82ð
\90¶
\90¬
\82·
\82é)
783 // *************************************************************************
784 procedure ThreadItemOnCreateOfTShitarabaThreadItem(
788 threadItem : TShitarabaThreadItem;
791 threadItem := TShitarabaThreadItem.Create( inInstance );
792 ThreadItemSetLong( inInstance, tipContext, DWORD( threadItem ) );
796 // *************************************************************************
797 // TThreadItem
\82ª
\94j
\8aü
\82³
\82ê
\82½
\8fê
\8d\87\82Ì
\8f\88\92u(TShitarabaThreadItem
\82ð
\94j
\8aü
\82·
\82é)
798 // *************************************************************************
799 procedure ThreadItemOnDisposeOfTShitarabaThreadItem(
803 threadItem : TShitarabaThreadItem;
806 threadItem := TShitarabaThreadItem( ThreadItemGetLong( inInstance, tipContext ) );
811 // =========================================================================
812 // TShitarabaBoardItem
813 // =========================================================================
815 // *************************************************************************
816 //
\83R
\83\93\83X
\83g
\83\89\83N
\83^
817 // *************************************************************************
818 constructor TShitarabaBoardItem.Create(
823 uriList : TStringList;
828 OnDownload := Download;
829 OnCreateThread := CreateThread;
830 OnEnumThread := EnumThread;
831 OnFileName2ThreadURL := ToThreadURL;
834 FIsTemporary := False;
837 uri := TIdURI.Create( SubjectURL );
838 uriList := TStringList.Create;
840 ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
841 // http://jbbs.shitaraba.com/game/1000/subject.txt
842 FilePath := MyLogFolder + uriList[ 1 ] + '\' + uriList[ 2 ] + '\' + uri.Document;
843 IsLogFile := FileExists( FilePath );
851 // *************************************************************************
852 //
\83f
\83X
\83g
\83\89\83N
\83^
853 // *************************************************************************
854 destructor TShitarabaBoardItem.Destroy;
857 if FDat <> nil then begin
865 //
\88ê
\8e\9e\83t
\83@
\83C
\83\8b\82Ì
\8fê
\8d\87\82Í
\8dí
\8f\9c\82·
\82é
867 DeleteFile( FilePath );
873 // *************************************************************************
874 //
\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½
875 // *************************************************************************
876 function TShitarabaBoardItem.Download : TDownloadState;
880 responseCode : Longint;
882 uriList : TStringList;
889 if FDat <> nil then begin
896 FDat := TStringList.Create;
897 uri := TIdURI.Create( SubjectURL );
898 uriList := TStringList.Create;
899 //
\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Í
900 // InternalDownload
\82É
\94C
\82¹
\82é
\82±
\82Æ
\82ª
\8fo
\97\88\82é
901 modified := LastModified;
902 responseCode := InternalDownload( PChar( uri.URI ), modified, downResult );
904 if responseCode = 200 then begin
906 //
\83p
\83X
\82ð
\8eZ
\8fo
907 ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
908 if MyLogFolder = '' then begin
909 //
\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¶
910 FilePath := TemporaryFile;
911 FIsTemporary := True;
913 FilePath := MyLogFolder + uriList[ 1 ] + '\' + uriList[ 2 ] + '\' + uri.Document;
914 FIsTemporary := False
917 //
\95Û
\91¶
\97p
\82Ì
\83f
\83B
\83\8c\83N
\83g
\83\8a\82ð
\8c@
\82é
918 ForceDirectoriesEx( Copy( FilePath, 1, LastDelimiter( '\', FilePath ) ) );
920 // EUC
\82ð Shift_JIS
\82É
921 tmpText := CustomStringReplace( string( downResult ), '¡÷¡®', ' ');
922 FDat.Text := EUCtoSJIS( tmpText );
923 //
\82µ
\82½
\82ç
\82Î JBBS
\82Í
\83`
\83F
\83b
\83N
\97p
\82É
\90æ
\93ª
\82Æ
\8dÅ
\8fI
\8ds
\82ª
\93¯
\82¶
925 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¸
926 if FDat[ 0 ] = FDat[ i ] then
929 FDat.SaveToFile( FilePath );
933 LastModified := modified;
939 Result := dsComplete;
942 DisposeResultString( downResult );
947 // *************************************************************************
948 //
\83X
\83\8c\97§
\82Ä
\82ð
\8ew
\8e¦
\82³
\82ê
\82½
949 // *************************************************************************
950 function TShitarabaBoardItem.CreateThread(
951 inSubject : string; //
\83X
\83\8c\83^
\83C
952 inName : string; //
\96¼
\91O(
\83n
\83\93\83h
\83\8b)
953 inMail : string; //
\83\81\81[
\83\8b\83A
\83h
\83\8c\83X
954 inMessage : string //
\96{
\95¶
955 ) : TDownloadState; //
\8f\91\82«
\8d\9e\82Ý
\82ª
\90¬
\8c÷
\82µ
\82½
\82©
\82Ç
\82¤
\82©
961 uriList : TStringList;
962 responseCode : Integer;
965 uri := TIdURI.Create( URL );
966 uriList := TStringList.Create;
968 ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
970 // http://jbbs.shitaraba.com/bbs/write.cgi/game/1578/new/
971 // http://jbbs.shitaraba.com/game/1000/subject.txt
973 uri.Protocol + '://' + uri.Host + '/bbs/write.cgi/' +
974 uriList[ 1 ] + '/' + uriList[ 2 ] + '/new/';
976 'SUBJECT=' + HttpEncode( SJIStoEUC( inSubject ) ) +
977 '&NAME=' + HttpEncode( SJIStoEUC( inName ) ) +
978 '&MAIL=' + HttpEncode( SJIStoEUC( inMail ) ) +
979 '&MESSAGE=' + HttpEncode( SJIStoEUC( inMessage ) ) +
980 '&BBS=' + uriList[ 4 ] +
981 '&DIR=' + uriList[ 3 ] +
982 '&TIME=' + IntToStr( DateTimeToUnix( Now ) ) +
983 '&submit=' + HttpEncode( SJIStoEUC( '
\90V
\8bK
\8f\91\82«
\8d\9e\82Ý' ) );
985 //
\93Æ
\8e©
\82É
\92Ê
\90M
\82µ
\82È
\82¢
\8fê
\8d\87\82Í InternalPost
\82É
\94C
\82¹
\82é
\82±
\82Æ
\82ª
\8fo
\97\88\82é
986 responseCode := InternalPost( PChar( postURL ), PChar( postData ), postResult );
988 if (responseCode = 200) or
989 ((responseCode = 302) and (Length( Trim( postResult ) ) = 0)) then begin
993 if Assigned( InternalPrint ) then
994 InternalPrint( postResult );
997 DisposeResultString( postResult );
1006 // *************************************************************************
1007 //
\83X
\83\8c\88ê
\97\97\82Ì URL
\82©
\82ç
\83X
\83\8c\83b
\83h
\82Ì URL
\82ð
\93±
\82«
\8fo
\82·
1008 // *************************************************************************
1009 function TShitarabaBoardItem.ToThreadURL(
1010 inFileName : string //
\83X
\83\8c\83b
\83h
\83t
\83@
\83C
\83\8b\96¼
1011 ) : string; //
\83X
\83\8c\83b
\83h
\82Ì URL
1015 uriList : TStringList;
1019 found := AnsiPos( '.', inFileName );
1021 inFileName := Copy( inFileName, 1, found - 1 );
1023 uri := TIdURI.Create( SubjectURL );
1024 uriList := TStringList.Create;
1027 ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
1028 threadURL := uri.Protocol + '://' + uri.Host + '/bbs/read.cgi/' +
1029 uriList[ 1 ] + '/' + uriList[ 2 ] + '/' + inFileName + '/l100';
1030 Result := threadURL;
1041 // *************************************************************************
1042 //
\82±
\82Ì
\94Â
\82É
\82¢
\82
\82Â
\82Ì
\83X
\83\8c\82ª
\82 \82é
\82©
\97v
\8b\81\82³
\82ê
\82½
1043 // *************************************************************************
1044 procedure TShitarabaBoardItem.EnumThread(
1045 inCallBack : TBoardItemEnumThreadCallBack
1049 uriList : TStringList;
1053 if FDat = nil then begin
1054 FDat := TStringList.Create;
1055 uri := TIdURI.Create( SubjectURL );
1056 uriList := TStringList.Create;
1058 //
\83p
\83X
\82ð
\8eZ
\8fo
1059 ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
1060 // http://jbbs.shitaraba.com/game/1000/subject.txt
1061 FilePath := MyLogFolder + uriList[ 1 ] + '\' + uriList[ 2 ] + '\' + uri.Document;
1062 if FileExists( FilePath ) then
1063 //
\93Ç
\82Ý
\8d\9e\82Ý
1064 FDat.LoadFromFile( FilePath );
1071 //
\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é
1072 inherited EnumThread( inCallBack, CustomStringReplace( FDat.Text, ',', '<>' ) );
1078 // *************************************************************************
1079 //
\83X
\83\8c\88ê
\97\97\82Ì URL
\82ð
\8b\81\82ß
\82é
1080 // *************************************************************************
1081 function TShitarabaBoardItem.SubjectURL : string;
1084 uriList : TStringList;
1087 uri := TIdURI.Create( URL );
1088 uriList := TStringList.Create;
1090 if uri.Document <> SUBJECT_NAME then begin
1091 if Copy( URL, Length( URL ), 1 ) = '/' then
1092 Result := URL + SUBJECT_NAME
1094 Result := URL + '/' + SUBJECT_NAME;
1096 //
\82±
\82±
\82É
\82Í
\97\88\82È
\82¢
\82Æ
\8ev
\82¤
\82¯
\82Ç
1106 // *************************************************************************
1107 // TBoardItem
\82ª
\90¶
\90¬
\82³
\82ê
\82½
\8fê
\8d\87\82Ì
\8f\88\92u(TShitarabaBoardItem
\82ð
\90¶
\90¬
\82·
\82é)
1108 // *************************************************************************
1109 procedure BoardItemOnCreateOfTShitarabaBoardItem(
1113 boardItem : TShitarabaBoardItem;
1116 boardItem := TShitarabaBoardItem.Create( inInstance );
1117 BoardItemSetLong( inInstance, bipContext, DWORD( boardItem ) );
1121 // *************************************************************************
1122 // TBoardItem
\82ª
\94j
\8aü
\82³
\82ê
\82½
\8fê
\8d\87\82Ì
\8f\88\92u(TShitarabaBoardItem
\82ð
\94j
\8aü
\82·
\82é)
1123 // *************************************************************************
1124 procedure BoardItemOnDisposeOfTShitarabaBoardItem(
1128 boardItem : TShitarabaBoardItem;
1131 boardItem := TShitarabaBoardItem( BoardItemGetLong( inInstance, bipContext ) );
1138 // =========================================================================
1139 //
\83G
\83\93\83g
\83\8a\83|
\83C
\83\93\83g
1140 // =========================================================================
1142 ul_reason_for_call : DWORD
1148 case ul_reason_for_call of
1153 module := GetModuleHandle( nil );
1155 LoadInternalAPI( module );
1156 LoadInternalFilePathAPI( module );
1157 LoadInternalThreadItemAPI( module );
1158 LoadInternalBoardItemAPI( module );
1160 // =====
\83C
\83\93\83X
\83^
\83\93\83X
\82Ì
\8eæ
\82è
\88µ
\82¢
\82ð TThreadItem
\82©
\82ç TShitarabaThreadItem
\82É
\95Ï
\8dX
\82·
\82é
1161 ThreadItemOnCreate := ThreadItemOnCreateOfTShitarabaThreadItem;
1162 ThreadItemOnDispose := ThreadItemOnDisposeOfTShitarabaThreadItem;
1163 // =====
\83C
\83\93\83X
\83^
\83\93\83X
\82Ì
\8eæ
\82è
\88µ
\82¢
\82ð TBoardItem
\82©
\82ç TShitarabaBoardItem
\82É
\95Ï
\8dX
\82·
\82é
1164 BoardItemOnCreate := BoardItemOnCreateOfTShitarabaBoardItem;
1165 BoardItemOnDispose := BoardItemOnDisposeOfTShitarabaBoardItem;
1184 DllProc := @DLLEntry;
1185 DLLEntry( DLL_PROCESS_ATTACH );