OSDN Git Service

IDのない板の過去ログの投稿日が抜ける不具合の修正
[gikonavigoeson/gikonavi.git] / res / ExternalBoardPlugIn / ShitarabaJBBSPlugIn.dpr
1 library ShitarabaJBBSPlugIn;
2
3 {
4         ShitarabaJBBSPlugIn
5         \82µ\82½\82ç\82Î\8f\88\97\9d\83\86\83j\83b\83g
6         $Id: ShitarabaJBBSPlugIn.dpr,v 1.38 2005/03/24 13:55:32 h677 Exp $
7 }
8
9 uses
10   Windows,
11   SysUtils,
12   Classes,
13   Math,
14   DateUtils,
15   Dialogs,
16   IdURI,
17   PlugInMain in 'PlugInMain.pas',
18   ThreadItem in 'ThreadItem.pas',
19   BoardItem in 'BoardItem.pas',
20         FilePath in 'FilePath.pas',
21   Y_TextConverter in 'Y_TextConverter.pas',
22   MojuUtils in '..\..\MojuUtils.pas',
23   ShitarabaJBBSAcquireBoard in 'ShitarabaJBBSAcquireBoard.pas' {ShitarabaJBBSAcquireBoardDialog};
24
25 {$R *.res}
26
27 type
28         // =========================================================================
29         // TShitarabaThreadItem
30         // =========================================================================
31         TShitarabaThreadItem = class(TThreadItem)
32         private
33                 FIsTemporary    : Boolean;
34                 FDat                                    : TStringList;
35
36         public
37                 constructor     Create( inInstance : DWORD );
38                 destructor      Destroy; override;
39
40         private
41                 function        Download : TDownloadState;
42                 function        StorageDownload(AURL : string) : TDownloadState;
43                 function        Write( inName : string; inMail : string; inMessage : string ) : TDownloadState;
44                 function        GetRes( inNo : Integer ) : string;
45                 function        GetDat( inNo : Integer ) : string;
46                 function        GetHeader( inOptionalHeader : string ) : string;
47                 function        GetFooter( inOptionalFooter : string ) : string;
48                 function        GetBoardURL : string;
49                 procedure       ArrangeDownloadData( start: Integer;var Data: TStringList);
50                 procedure       LoadDat;
51                 procedure       FreeDat;
52                 function        BrowsableURL : string;
53                 function        ReadURL : string;
54                 function        WriteURL : string;
55         end;
56
57         // =========================================================================
58         // TShitarabaBoardItem
59         // =========================================================================
60         TShitarabaBoardItem = class(TBoardItem)
61         private
62                 FIsTemporary    : Boolean;
63                 FDat                                    : TStringList;
64
65         public
66                 constructor     Create( inInstance : DWORD );
67                 destructor      Destroy; override;
68
69         private
70                 function        Download : TDownloadState;
71                 function        CreateThread( inSubject : string; inName : string; inMail : string; inMessage : string ) : TDownloadState;
72                 function        ToThreadURL( inFileName : string ) : string;
73                 procedure       EnumThread( inCallBack : TBoardItemEnumThreadCallBack );
74
75                 function        SubjectURL : string;
76         end;
77
78 const
79         LOG_DIR                                         = 'ShitarabaJBBS\';
80         SUBJECT_NAME                    = 'subject.txt';
81
82         PLUGIN_NAME                             = 'ShitarabaJBBS';
83         MAJOR_VERSION                   = 1;
84         MINOR_VERSION                   = 1;
85         RELEASE_VERSION         = 'alpha';
86         REVISION_VERSION        = 4;
87
88         SYNCRONIZE_MENU_CAPTION = '\82µ\82½\82ç\82ÎJBBS\94Â\8dX\90V';
89
90 var
91         SyncronizeMenu          : HMENU;
92
93 // =========================================================================
94 // \8eG\97p\8aÖ\90\94
95 // =========================================================================
96
97 // *************************************************************************
98 // \83e\83\93\83|\83\89\83\8a\82È\83p\83X\82Ì\8eæ\93¾
99 // *************************************************************************
100 function TemporaryFile : string;
101 var
102         tempPath : array [0..MAX_PATH] of       char;
103 begin
104
105         GetTempPath( SizeOf(tempPath), tempPath );
106         repeat
107                 Result := tempPath + IntToStr( Random( $7fffffff ) );
108         until not FileExists( Result );
109
110 end;
111
112 // *************************************************************************
113 // \82µ\82½\82ç\82Î\97p\83\8d\83O\83t\83H\83\8b\83_\8eæ\93¾
114 // *************************************************************************
115 function MyLogFolder : string;
116 var
117         folder : PChar;
118 begin
119
120         folder := LogFolder;
121         if Length( folder ) = 0 then
122                 Result := ''
123         else
124                 Result := folder + LOG_DIR;
125     DisposeResultString(folder);
126
127 end;
128
129 (*************************************************************************
130  *\83f\83B\83\8c\83N\83g\83\8a\82ª\91\8dÝ\82·\82é\82©\83`\83F\83b\83N
131  *************************************************************************)
132 function DirectoryExistsEx(const Name: string): Boolean;
133 var
134         Code: Integer;
135 begin
136         Code := GetFileAttributes(PChar(Name));
137         Result := (Code <> -1) and (FILE_ATTRIBUTE_DIRECTORY and Code <> 0);
138 end;
139
140 (*************************************************************************
141  *\83f\83B\83\8c\83N\83g\83\8a\8dì\90¬\81i\95¡\90\94\8aK\91w\91Î\89\9e\81j
142  *************************************************************************)
143 function ForceDirectoriesEx(Dir: string): Boolean;
144 begin
145         Result := True;
146         if Length(Dir) = 0 then
147                 raise Exception.Create('\83t\83H\83\8b\83_\82ª\8dì\90¬\8fo\97\88\82Ü\82¹\82ñ');
148         Dir := ExcludeTrailingPathDelimiter(Dir);
149         if (Length(Dir) < 3) or DirectoryExistsEx(Dir)
150                 or (ExtractFilePath(Dir) = Dir) then Exit; // avoid 'xyz:\' problem.
151         Result := ForceDirectoriesEx(ExtractFilePath(Dir)) and CreateDir(Dir);
152 end;
153
154 // \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
155 procedure ExtractHttpFields(
156         const chrSep : TSysCharSet;
157         const chrWhite : TSysCharSet;
158         const strValue : string;
159         var strResult : TStringList;
160         unknownFlag : boolean = false
161 );
162 var
163         last, p, strLen : Integer;
164 begin
165
166         strLen := Length( strValue );
167         p := 1;
168         last := 1;
169
170         while p <= strLen do
171         begin
172
173                 if strValue[ p ] in chrSep then
174                 begin
175                         strResult.Add( Copy( strValue, last, p - last ) );
176                         last := p + 1;
177                 end;
178
179                 p := p + 1;
180
181         end;
182
183         if last <> p then
184                 strResult.Add( Copy( strValue, last, strLen - last + 1 ) );
185
186 end;
187
188 \rfunction HttpEncode(
189 \r       const strValue : string
190 ) : string;
191 var
192         i : Integer;
193         strLen : Integer;
194         strResult : string;
195         b : Integer;
196 const
197         kHexCode : array [0..15] of char = (
198                                 '0', '1', '2', '3', '4', '5', '6', '7',
199                                 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' );
200 begin
201
202         strLen := Length( strValue );
203         i := 1;
204
205         while i <= strLen do
206         begin
207
208                 case strValue[ i ] of
209                 '0' .. '9', 'a' .. 'z', 'A' .. 'Z', '*', '-', '.', '@', '_':
210                         begin
211                                 strResult := strResult + strValue[ i ];
212                         end;
213                 else
214                         begin
215                                 b := Integer( strValue[ i ] );
216                                 strResult := strResult + '%'
217                                                                 + kHexCode[ b div $10 ]
218                                                                 + kHexCode[ b mod $10 ];
219                         end;
220                 end;
221
222                 i := i + 1;
223
224         end;
225
226         Result := strResult;
227
228 end;
229
230
231
232 // =========================================================================
233 // PlugIn
234 // =========================================================================
235
236 // *************************************************************************
237 // \83v\83\89\83O\83C\83\93\82ª(\90³\82µ\82­)\83\8d\81[\83h\82³\82ê\82½
238 // *************************************************************************
239 procedure OnLoad(
240         inInstance : DWORD                              // \83v\83\89\83O\83C\83\93\82Ì\83C\83\93\83X\83^\83\93\83X
241 ); stdcall;
242 begin
243
244         // \83v\83\89\83O\83C\83\93\83\81\83j\83\85\81[\82É\92Ç\89Á
245         SyncronizeMenu := AddPlugInMenu( inInstance, SYNCRONIZE_MENU_CAPTION );
246
247 end;
248
249 // *************************************************************************
250 // \83v\83\89\83O\83C\83\93\82Ì\83o\81[\83W\83\87\83\93\82ð\97v\8b\81\82³\82ê\82½
251 // *************************************************************************
252 procedure OnVersionInfo(
253         var outAgent            : PChar;        // \83o\81[\83W\83\87\83\93\82ð\88ê\90Ø\8aÜ\82Ü\82È\82¢\8f\83\90\88\82È\96¼\8fÌ
254         var outMajor            : DWORD;        // \83\81\83W\83\83\81[\83o\81[\83W\83\87\83\93
255         var outMinor            : DWORD;        // \83}\83C\83i\81[\83o\81[\83W\83\87\83\93
256         var outRelease  : PChar;        // \83\8a\83\8a\81[\83X\92i\8aK\96¼
257         var outRevision : DWORD         // \83\8a\83r\83W\83\87\83\93\83i\83\93\83o\81[
258 ); stdcall;
259 begin
260
261         try
262                 outAgent                := CreateResultString( PChar( PLUGIN_NAME ) );
263                 outMajor                := MAJOR_VERSION;
264                 outMinor                := MINOR_VERSION;
265                 outRelease      := CreateResultString( PChar( RELEASE_VERSION ) );
266                 outRevision     := REVISION_VERSION;
267         except
268                 outAgent                := nil;
269                 outMajor                := 0;
270                 outMinor                := 0;
271                 outRelease      := nil;
272                 outRevision     := 0;
273         end;
274
275 end;
276
277 // *************************************************************************
278 // \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©
279 // *************************************************************************
280 function OnAcceptURL(
281         inURL                   : PChar                         // \94»\92f\82ð\8bÂ\82¢\82Å\82¢\82é URL
282 ): TAcceptType; stdcall;        // URL \82Ì\8eí\97Þ
283 var
284         uri                             : TIdURI;
285         uriList         : TStringList;
286         foundPos        : Integer;
287 //      i                       : Integer;
288 const
289         BBS_HOST_OLD    = 'jbbs.shitaraba.com';
290         BBS_HOST_OLD2   = 'jbbs.livedoor.com';
291         BBS_HOST                = 'jbbs.livedoor.jp';
292         THREAD_MARK     = '/bbs/read.cgi';
293 begin
294
295         try
296                 // \83z\83X\83g\96¼\82ª jbbs.livedoor.com \82Å\8fI\82í\82é\8fê\8d\87\82Í\8eó\82¯\95t\82¯\82é\82æ\82¤\82É\82µ\82Ä\82¢\82é
297                 uri                     := TIdURI.Create( inURL );
298                 uriList := TStringList.Create;
299                 try
300                         if (uri.Host = BBS_HOST_OLD) or (uri.Host = BBS_HOST_OLD2) then
301                                 uri.Host := BBS_HOST;
302                                 
303                         ExtractHttpFields( ['/'], [], uri.Path, uriList );
304                         if (AnsiPos( BBS_HOST, uri.Host ) > 0) and (Length( uri.Host ) - AnsiPos( BBS_HOST, uri.Host ) + 1 = Length( BBS_HOST )) then begin
305                                 foundPos := AnsiPos( THREAD_MARK, inURL );
306
307                                 if foundPos > 0 then
308                                         Result := atThread
309                                 else if (uriList.Count > 2) and (AnsiPos('.html', uri.Document) > 0) then
310                                         Result := atThread
311                                 else if uriList.Count > 2 then  // \8dÅ\8cã\82ª '/' \82Å\95Â\82ß\82ç\82ê\82Ä\82é\82È\82ç 4
312                                         Result := atBoard
313                                 else
314                                         Result := atBBS;
315
316                         end else begin
317                                 Result := atNoAccept;
318                         end;
319
320                 finally
321                         uri.Free;
322                         uriList.Free;
323                 end;
324         except
325                 Result := atNoAccept;
326         end;
327
328 end;
329
330 // *************************************************************************
331 // \82µ\82½\82ç\82ÎJBBS\94Â\8dX\90V
332 // *************************************************************************
333 procedure OnBoardSyncronizeMenu(
334         inHandle        : HMENU                                 // \83\81\83j\83\85\81[\83n\83\93\83h\83\8b
335 ); stdcall;
336 var
337         dialog                          : TShitarabaJBBSAcquireBoardDialog;
338 begin
339
340         dialog := TShitarabaJBBSAcquireBoardDialog.Create( nil );
341         dialog.ShowModal;
342
343 end;
344
345 // \83\81\83j\83\85\81[\83n\83\93\83h\83\89
346 procedure OnPlugInMenu(
347         inHandle : HMENU                                        // \83\81\83j\83\85\81[\83n\83\93\83h\83\8b
348 ); stdcall;
349 begin
350
351         if inHandle = SyncronizeMenu then
352                 OnBoardSyncronizeMenu( inHandle );
353
354 end;
355
356 // =========================================================================
357 // TShitarabaThreadItem
358 // =========================================================================
359
360 // *************************************************************************
361 // \83R\83\93\83X\83g\83\89\83N\83^
362 // *************************************************************************
363 constructor TShitarabaThreadItem.Create(
364         inInstance      : DWORD
365 );
366 var
367         uri                                     : TIdURI;
368         uriList                 : TStringList;
369 begin
370
371         inherited;
372
373         OnDownload              := Download;
374         OnWrite                         := Write;
375         OnGetRes                        := GetRes;
376         OnGetDat                        := GetDat;
377         OnGetHeader             := GetHeader;
378         OnGetFooter             := GetFooter;
379         OnGetBoardURL   := GetBoardURL;
380
381         FilePath                        := '';
382         FIsTemporary    := False;
383         FDat                                    := nil;
384         URL                                             := BrowsableURL;
385
386         uri                     := TIdURI.Create( ReadURL );
387         uriList := TStringList.Create;
388         try
389                 ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
390                 if uriList[ 5 ] = 'l100' then begin
391                         FileName        := uriList[ 4 ] + '.dat';
392                         FilePath        := MyLogFolder + uriList[ 2 ] + '\' + uriList[ 3 ] + '\' + uriList[ 4 ] + '.dat';
393                         IsLogFile       := FileExists( FilePath );
394                 end else begin
395                         FileName        := uriList[ 5 ] + '.dat';
396                         FilePath        := MyLogFolder + uriList[ 3 ] + '\' + uriList[ 4 ] + '\' + uriList[ 5 ] + '.dat';
397                         IsLogFile       := FileExists( FilePath );
398                 end;
399         finally
400                 uri.Free;
401                 uriList.Free;
402         end;
403
404 end;
405
406 // *************************************************************************
407 // \83f\83X\83g\83\89\83N\83^
408 // *************************************************************************
409 destructor TShitarabaThreadItem.Destroy;
410 begin
411
412         FreeDat;
413
414         // \88ê\8e\9e\83t\83@\83C\83\8b\82Ì\8fê\8d\87\82Í\8dí\8f\9c\82·\82é
415         if FIsTemporary then
416                 DeleteFile( FilePath );
417
418         inherited;
419
420 end;
421
422 // *************************************************************************
423 // \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½
424 // *************************************************************************
425 function TShitarabaThreadItem.Download : TDownloadState;
426 var
427         modified                        : Double;
428         tmp                                             : PChar;
429         downResult              : TStringList;
430         responseCode    : Longint;
431         logStream                       : TFileStream;
432         uri                                             : TIdURI;
433         uriList                         : TStringList;
434         datURL, tmpURL                          : string;
435         tmpText: string;
436 begin
437
438         Result := dsError;
439
440         uri := TIdURI.Create( ReadURL );
441         uriList := TStringList.Create;
442         try
443                 ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
444                 FileName := uriList[ 5 ] + '.dat';
445                 // http://jbbs.livedoor.com/bbs/rawmode.cgi/game/1578/1067968274/l100
446                 // protocol://host/1/2/3/4/5/uriList.Count - 1
447                 if MyLogFolder = '' then begin
448                         // \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
449                         FilePath                        := TemporaryFile;
450                         FIsTemporary    := True;
451                 end else begin
452                         FilePath                        := MyLogFolder + uriList[ 3 ] + '\' + uriList[ 4 ] + '\' + uriList[ 5 ] + '.dat';
453                         FIsTemporary    := False;
454                 end;
455         finally
456                 uri.Free;
457                 uriList.Free;
458         end;
459
460         // \95Û\91\97p\82Ì\83f\83B\83\8c\83N\83g\83\8a\82ð\8c@\82é
461         ForceDirectoriesEx( Copy( FilePath, 1, LastDelimiter( '\', FilePath ) ) );
462
463         // \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Í
464         // InternalDownload \82É\94C\82¹\82é\82±\82Æ\82ª\8fo\97\88\82é
465         modified        := LastModified;
466         datURL          := ReadURL + IntToStr( Count + 1 ) + '-'; // \90V\92\85\82Ì\82Ý
467         responseCode := InternalDownload( PChar( datURL ), modified, tmp, 0 );
468
469         try
470                 if (responseCode = 200) or (responseCode = 206) then begin
471                         downResult := TStringList.Create;
472                         try
473                                                                 tmpText := CustomStringReplace( string( tmp ), '¡÷¡®', ',' );
474                                 downResult.Text := EUCtoSJIS( tmpText );
475                                                                 ArrangeDownloadData(Count, downResult);
476                                 if downResult.Count > 0 then begin
477                                         if FileExists( FilePath ) then
478                                                 logStream := TFileStream.Create( FilePath, fmOpenReadWrite or fmShareDenyWrite )
479                                         else
480                                                 logStream := TFileStream.Create( FilePath, fmCreate or fmShareDenyWrite );
481                                         try
482                                                 logStream.Position      := logStream.Size;
483                                                 logStream.Write( PChar( downResult.Text )^, Length( downResult.Text ) );
484                                         finally
485                                                 logStream.Free;
486                                         end;
487
488                                         if Count = 0 then
489                                                                                         // \90V\8bK
490                                                 Result := dsComplete
491                                         else
492                                                 // \92Ç\8bL
493                                                 Result := dsDiffComplete;
494
495                                                                                 Size                                    := Size + Length( downResult.Text );
496                                         // CGI \82©\82ç\82Í\90³\82µ\82¢\93ú\95t\82ª\93¾\82ç\82ê\82È\82¢\82Ì\82Å\8c»\8dÝ\82É\90Ý\92è
497                                         LastModified    := Now;
498
499
500
501                                         NewReceive              := Count + 1;
502                                         Count                                   := Count + downResult.Count;
503                                         NewResCount             := downResult.Count;
504
505
506
507                                 end else begin
508                                         Result := dsNotModify;
509                                 end;
510                         finally
511                                 downResult.Free;
512                         end;
513                 end else if responseCode = 302 then begin
514                         //http://jbbs.shitaraba.com/bbs/read.cgi/game/3477/1077473358/
515                         //http://jbbs.shitaraba.com/game/bbs/read.cgi?BBS=3477&KEY=1077473358
516                         //http://jbbs.shitaraba.com/game/3477/storage/1077473358.html
517                         //\89ß\8b\8e\83\8d\83O
518                         //tmpURL := URL;
519                         if Assigned( InternalPrint ) then
520                                 InternalPrint( '\89ß\8b\8e\83\8d\83O\91q\8cÉ\93ü\82è' );
521                         uri := TIdURI.Create( ReadURL );
522                         uriList := TStringList.Create;
523                         try
524                                 ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
525                                 tmpURL := uri.Protocol + '://' + uri.Host +
526                                                 '/' + uriList[3] + '/' + uriList[4] + '/storage/' + uriList[ 5 ] + '.html';
527                         finally
528                                 uriList.Free;
529                                 uri.Free;
530                         end;
531                         Result := StorageDownload(tmpURL);
532                 end else if responseCode = 304 then begin
533                         Result := dsNotModify;
534                 end;
535         finally
536                 DisposeResultString( tmp );
537         end;
538
539 end;
540 // *************************************************************************
541 // download\82µ\82Ä\82«\82½Dat\82Ì\82 \82Ú\81[\82ñ\82³\82ê\82½\95ª\82ð\95â\8f[\82µ\82Ä\81A
542 // \83\8c\83X\90\94\82Æ\88ê\92v\82·\82é\82æ\82¤\82É\82·\82é
543 // *************************************************************************
544 procedure       TShitarabaThreadItem.ArrangeDownloadData(
545         start: Integer; // \90V\8bK\81F\82O\81@\92Ç\8bL\81F\91O\89ñ\82Ü\82Å\82Ì\8eæ\93¾\90\94
546                 var Data: TStringList   //Dat\82Ì\83f\81[\83^
547 );
548 var
549         i: Integer;
550                 n: Integer;
551                 tmp: string;
552 begin
553         i := start;
554                 while i < Data.count + start do begin
555                         try
556                                         tmp := Copy(Data[i - start], 1 , AnsiPos('<>', Data[ i - start ] )-1 );
557                                                 try
558                                                         n := StrToInt(tmp);
559                                                                 if n > i + 1 then begin
560                                                                         Data.Insert(i - start, Format('%d<><><><><><>', [i+1]));
561                                                                 end;
562                                                                 Inc(i);
563                                                 except
564                                                         Inc(i);
565                         end;
566                                 except
567
568                                 end;
569                 end;
570
571 end;
572 // *************************************************************************
573 // \89ß\8b\8e\83\8d\83O\97pDownload\8aÖ\90\94
574 // *************************************************************************
575 function        TShitarabaThreadItem.StorageDownload(
576         AURL : string
577 ) : TDownloadState;
578 var
579         modified                        : Double;
580         tmp                                             : PChar;
581     uri : TIdURI;
582         uriList : TStringList;
583         downResult              : TStringList;
584         responseCode    : Longint;
585         logStream                       : TFileStream;
586         tmpText, tmpLine, tmpTitle: string;
587         tmpHTML: TStringList;
588
589         i, j, tS, tE: Integer;
590         tmpDatToken : array[0..6] of string;
591 begin
592
593         Result := dsError;
594         uri := TIdURI.Create( ReadURL );
595         uriList := TStringList.Create;
596         try
597                 ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
598                 FileName := uriList[ 5 ] + '.dat';
599                 // http://jbbs.livedoor.com/bbs/rawmode.cgi/game/1578/1067968274/l100
600                 // protocol://host/1/2/3/4/5/uriList.Count - 1
601                 if MyLogFolder = '' then begin
602                         // \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
603                         FilePath                        := TemporaryFile;
604                         FIsTemporary    := True;
605                 end else begin
606                         FilePath                        := MyLogFolder + uriList[ 3 ] + '\' + uriList[ 4 ] + '\' + uriList[ 5 ] + '.dat';
607                         FIsTemporary    := False;
608                 end;
609         finally
610                 uri.Free;
611                 uriList.Free;
612         end;
613
614         // \95Û\91\97p\82Ì\83f\83B\83\8c\83N\83g\83\8a\82ð\8c@\82é
615         ForceDirectoriesEx( Copy( FilePath, 1, LastDelimiter( '\', FilePath ) ) );
616
617
618
619         // \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Í
620         // InternalDownload \82É\94C\82¹\82é\82±\82Æ\82ª\8fo\97\88\82é
621         modified        := LastModified;
622
623         responseCode := InternalDownload( PChar( AURL ), modified, tmp, 0 );
624
625         try
626                 if (responseCode = 200) or (responseCode = 206) then begin
627                         downResult := TStringList.Create;
628                         try
629                                 tmpText := CustomStringReplace( string( tmp ), '¡÷¡®', ',' );
630
631
632
633                                 //**\82±\82±\82ÅHTML\83t\83@\83C\83\8b\82ð\82µ\82½\82ç\82ÎJBBS\82Ìdat\8c`\8e®\82É\95Ï\8a·\82·\82é
634                                 tmpHTML := TStringList.Create;
635
636                                 try
637                                         tmpHTML.Text := EUCtoSJIS( tmpText );
638                                         //Title\82Ì\8eæ\93¾
639                                         for i := 0 to tmpHTML.Count - 1 do begin
640                                                 tmpLine := AnsiLowerCase(tmpHTML[i]);
641                                                 tS := AnsiPos('<title>', tmpLine);
642                                                 tE := AnsiPos('</title>', tmpLine);
643
644                                                 if tS > 0 then begin
645                                                         if tE - tS  = 1 then begin
646                                                                 tmpTitle := '';
647                                                         end else begin
648                                                                 tmpTitle := Copy(tmpHTML[i], ts + 7, Length(tmpHTML[i]));
649                                                                 tmpLine := AnsiLowerCase(tmpTitle);
650                                                                 tE := AnsiPos('</title>', tmpLine);
651
652                                                                 if tE > 0 then begin
653                                                                         tmpTitle := Copy(tmpTitle, 1, tE - 1);
654                                                                 end else begin
655                                                                         j := i + 1;
656                                                                         tmpLine := AnsiLowerCase(tmpHTML[j]);
657                                                                         tE := AnsiPos('</title>', tmpLine);
658                                                                         tmpTitle := tmpTitle  + tmpHTML[j];
659                                                                         while( tE = 0 ) do begin
660                                                                                 j := i + 1;
661                                                                                 if j = tmpHTML.Count then break;
662                                                                                 tmpLine := AnsiLowerCase(tmpHTML[j]);
663                                                                                 tE := AnsiPos('</title>', tmpLine);
664                                                                                 tmpTitle := tmpTitle  + tmpHTML[j];
665                                                                         end;
666                                                                         if tE = 0 then tmpTitle := ''
667                                                                         else begin
668                                                                                 tmpLine := AnsiLowerCase(tmpTitle);
669                                                                                 tE := AnsiPos('</title>', tmpLine);
670                                                                                 tmpTitle := Copy(tmpTitle, 1, tE - 1);
671                                                                         end;
672                                                                 end;
673                                                         end;
674                                                 end;
675                                         end;
676                                         //Title := tmpTitle;
677                                         //tS := 0; tE := 0;
678                                         //\96{\95\82Ì\8eæ\93¾ <DL>\82Ì\8e\9f\82Ì\8ds\82©\82ç</DL>\82Ì\91O\82Ì\8ds\82Ü\82Å
679                                         for i := tmpHTML.Count - 1 downto 0 do begin
680                                                 tmpLine := AnsiLowerCase(tmpHTML[i]);
681                                                 tE := AnsiPos('</dl>', tmpLine);
682                                                 if tE > 0 then begin
683                             tmpHTML[i] := COpy(tmpHTML[i], 1, tE -1);
684                                                         break;
685                                                 end;
686                                                 tmpHTML.Delete(i);
687                                         end;
688                                         j := 0;
689                                         for i := 0 to tmpHTML.Count - 1 do begin
690                                                 tmpLine := AnsiLowerCase(tmpHTML[i]);
691                                                 tS := AnsiPos('<dl>', tmpLine);
692                                                 if tS > 0 then begin
693                                                         j := i + 1;
694                                                         break;
695                                                 end;
696                                         end;
697                                         for i := j downto 0 do
698                                                 tmpHTML.Delete(i);
699
700                                         //<DD><DT>\82»\82ê\82¼\82ê\88ê\8ds\82É\95Ï\8a·\82·\82é
701                                         for i := tmpHTML.Count - 1 downto 1 do begin
702                                                 tmpLine := AnsiLowerCase(tmpHTML[i]);
703                                                 if (AnsiPos('<dd>', tmpLine) = 0) and (AnsiPos('<dt>', tmpLine) = 0) then begin
704                                                         tmpLine := CustomStringReplace(tmpHTML[i-1], #13#10, '') +
705                                                                                         CustomStringReplace(tmpHTML[i], #13#10, '');
706                                                         tmpHTML.Insert(i-1, tmpLine);
707                                                         tmpHTML.Delete(i + 1);
708                                                         tmpHTML.Delete(i);
709                                                 end;
710                                         end;
711                                         //\8fã\82Ü\82Å\82Ì\8f\88\97\9d\82Å\88È\89º\82Ì\82æ\82¤\82È\8c`\82É\82È\82Á\82Ä\82é
712                                         //<dt><a name="958">958 </a> \96¼\91O\81F<font color="#008800"><b> \96¼\82à\96³\82«\8cR\8et </b></font> \93\8a\8de\93ú\81F 2004/06/30(\90\85) 15:17 [ r1FsjJhA ]<br><dd>\81`\81`
713                                         //<dt><a name="951">951 </a> \96¼\91O\81F<a href="mailto:sage"><b> \96¼\82à\96³\82«\8cR\8et </B></a> \93\8a\8de\93ú\81F 2004/06/30(\90\85) 12:31 [ .oGr0rtc ]<br><dd>\81`\81`
714                     //<dt><a name="951">951 </a> \96¼\91O\81F<a href="mailto:sage"><b> \96¼\82à\96³\82«\8cR\8et </B></a> \93\8a\8de\93ú\81F 2004/06/30(\90\85) 12:31<br><dd>\81`\81` <-ID\82Ì\82È\82¢\94Â
715                                         //\8fã\82Ì\82æ\82¤\82È\82Ì\82ð\89º\82Ì\82æ\82¤\82Èdat\82Ì\8c`\8e®\82É\95Ï\8a·\82·\82é
716                                         //\83\8c\83X\94Ô\8d\86<><font color=#FF0000>HN</font><>\83\81\83\8b\97\93<>\93ú\95t\8e\9e\8d\8f<>\96{\95¶<>\83^\83C\83g\83\8b\81i\82P\82Ì\82Ý\81j<>ID
717                                         //2<>\96¼\82à\96³\82«\8cR\8et<>sage<>2004/06/22(\89Î) 09:05<>\82Q\82°\82Æ\81[<><>26bmLAzg
718                                         for i := 0 to tmpHTML.Count - 1 do begin
719                                                 tmpDatToken[0] := ''; tmpDatToken[1] := ''; tmpDatToken[2] := '';
720                                                 tmpDatToken[3] := ''; tmpDatToken[4] := ''; tmpDatToken[6] := '';
721                                                 //==\82Ü\82¸\82Í\96{\95\82ð\8eæ\93¾==//
722                                                 tmpLine := AnsiLowerCase(tmpHTML[i]);
723                                                 tS := AnsiPos('<dd>', tmpLine);
724                                                 if tS > 0 then begin
725                                                         tmpDatToken[4] := Copy(tmpHTML[i], tS + 4, Length(tmpHTML[i]));
726                                                         tmpHTML[i] := Copy(tmpHTML[i], 1, tS -1);
727                                                 end else
728                                                         tmpDatToken[4] := '';
729                                                 //====================//
730                                                 //==\83\8c\83X\94Ô\8d\86\8eæ\93¾==//
731                                                 tmpLine := AnsiLowerCase(tmpHTML[i]);
732                                                 tS := AnsiPos('">', tmpLine);
733                                                 tE := AnsiPos('</a>', tmpLine);
734                                                 if tE > tS then begin
735                                                         tmpDatToken[0] := Copy(tmpHTML[i], tS + 2, tE - (tS + 2) - 1);
736                                                         tmpDatToken[0] := Trim(tmpDatToken[0]);
737                                                         tmpHTML[i] := Copy(tmpHTML[i], tE + 4, Length(tmpHTML[i]));
738                                                 end else
739                                                         tmpDatToken[0] := IntToStr(i);
740                                                 tS := AnsiPos('<', tmpHTML[i]);
741                                                 if tS > 0 then begin
742                                                         tmpHTML[i] := Copy(tmpHTML[i], tS, Length(tmpHTML[i]));
743                                                 end;
744                                                 //====================//
745                                                 //==\83\81\83\8b\97\93\8eæ\93¾==//
746                                                 tmpLine := AnsiLowerCase(tmpHTML[i]);
747                                                 tS := AnsiPos('<a href="mailto:', tmpLine);
748                                                 if tS > 0 then begin //\83\81\83\8b\97\93\83A\83\8a
749                                                         tE := AnsiPos('">', tmpLine);
750                                                         tmpDatToken[2] := Copy(tmpHTML[i], tS + 16, tE - (tS + 16));
751                                                         tmpHTML[i] := Copy(tmpHTML[i], tE + 5, Length(tmpHTML[i]));
752                             tmpHTML[i] := CustomStringReplace(tmpHTML[i], '</a>', '', true);
753                                                 end else begin  //\83\81\83\8b\97\93\96³\82µ
754                                                         tmpDatToken[2] := '';
755                                                 end;
756                                                 //====================//
757                                                 //==HN\8eæ\93¾==//
758                                                 tmpLine := AnsiLowerCase(tmpHTML[i]);
759                                                 tE := AnsiPos('\93\8a\8de\93ú\81F', tmpLine);
760                                                 if tE > 0 then begin
761                                                         tmpDatToken[1] := Trim(Copy(tmpHTML[i], 1, tE - 1 ));
762                                                         tmpDatToken[1] := CustomStringReplace(tmpDatToken[1], '<b>', '', true);
763                                                         tmpDatToken[1] := CustomStringReplace(tmpDatToken[1], '</b>', '', true);
764                                                         tmpHTML[i] := Copy(tmpHTML[i], tE + 8, Length(tmpHTML[i]));
765                                                 end else begin
766                                                         tmpDatToken[1] := '';
767                                                 end;
768                                                 //====================//
769                                                 //==\93ú\95t\8e\9e\8d\8f\82Ì\8eæ\93¾==//
770                                                 tmpLine := AnsiLowerCase(tmpHTML[i]);
771                                                 tE := AnsiPos('[', tmpLine);
772                                                 if tE > 0 then begin
773                                                         tmpDatToken[3] := Trim(Copy(tmpHTML[i], 1, tE - 1 ));
774                                                         tmpHTML[i] := Copy(tmpHTML[i], tE + 1, Length(tmpHTML[i]));
775                                                 end else begin
776                                                         tmpDatToken[3] := '';
777                                                 end;
778                                                 //====================//
779                                                 //==ID\82Ì\8eæ\93¾==//
780                                                 tmpLine := AnsiLowerCase(tmpHTML[i]);
781                         tS := AnsiPos('<br>', tmpLine);
782                                                 tE := AnsiPos(']', tmpLine);
783                                                 if (tE > 0) and (tE > tS) then begin
784                                                         tmpDatToken[6] := Trim(Copy(tmpHTML[i], 1, tE - 1 ));
785                                                 end else if (tS > 0) then begin
786                                                         tmpDatToken[6] := Trim(Copy(tmpHTML[i], 1, tS - 1 ));
787                                                 end else
788                             tmpDatToken[6] := Trim(tmpHTML[i]);
789                                                 //====================//
790                                                 tS := StrToIntDef(tmpDatToken[0], -1);
791                                                 if  tS = 1      then
792                                                         tmpLine := tmpDatToken[0] + '<>' + tmpDatToken[1] + '<>' + tmpDatToken[2] + '<>' +
793                                                                         tmpDatToken[3] + '<>' + tmpDatToken[4] + '<>' + tmpTitle + '<>' + tmpDatToken[6]
794                                                 else
795                                                         tmpLine := tmpDatToken[0] + '<>' + tmpDatToken[1] + '<>' +tmpDatToken[2] + '<>' +
796                                                                         tmpDatToken[3] + '<>' + tmpDatToken[4] + '<><>' + tmpDatToken[6];
797                                                 tmpHTML[i] := tmpLine;
798                                         end;
799
800
801
802
803                                         downResult.Text := tmpHTML.Text;
804                                 finally
805                                         tmpHTML.free;
806                                 end;
807
808                                 ArrangeDownloadData(Count, downResult);
809
810                                 if downResult.Count > 0 then begin
811                                         if FileExists( FilePath ) then
812                                                 DeleteFile(FilePath);
813
814                                         logStream := TFileStream.Create( FilePath, fmCreate or fmShareDenyWrite );
815                                         try
816                                                 logStream.Position      := 0;
817                                                 logStream.Write( PChar( downResult.Text )^, Length( downResult.Text ) );
818                                         finally
819                                                 logStream.Free;
820                                         end;
821
822                                         // \90V\8bK
823                                         Result := dsComplete;
824
825                                         Size    := Length( downResult.Text );
826                                         // CGI \82©\82ç\82Í\90³\82µ\82¢\93ú\95t\82ª\93¾\82ç\82ê\82È\82¢\82Ì\82Å\8c»\8dÝ\82É\90Ý\92è
827                                         LastModified    := Now;
828
829
830
831                                         NewReceive              := 1;
832                                         Count                                   := downResult.Count;
833                                         NewResCount             := downResult.Count;
834                                         //http://jbbs.livedoor.com/bbs/read.cgi/game/1578/1086710948/l100
835                                         //http://jbbs.livedoor.com/game/1578/storage/1086710948.html
836                                         //URL := 'http://jbbs.livedoor.com/bbs/read.cgi' +
837                                         //              CustomStringReplace(Path, '/storage', '')
838                                         //              + FileName;
839                                         DownloadHost := 'storage';
840                                 end else begin
841                                         Result := dsNotModify;
842                                 end;
843                         finally
844                                 downResult.Free;
845                         end;
846                 end else if responseCode = 304 then begin
847                         Result := dsNotModify;
848                 end;
849         finally
850                 DisposeResultString( tmp );
851         end;
852
853 end;
854
855 // *************************************************************************
856 // \8f\91\82«\8d\9e\82Ý\82ð\8ew\8e¦\82³\82ê\82½
857 // *************************************************************************
858 function        TShitarabaThreadItem.Write(
859         inName                          : string;       // \96¼\91O(\83n\83\93\83h\83\8b)
860         inMail                          : string;       // \83\81\81[\83\8b\83A\83h\83\8c\83X
861         inMessage                       : string        // \96{\95
862 ) : TDownloadState;                             // \8f\91\82«\8d\9e\82Ý\82ª\90¬\8c÷\82µ\82½\82©\82Ç\82¤\82©
863 var
864         postData                        : string;
865         postResult              : PChar;
866         uri                                             : TIdURI;
867         uriList                         : TStringList;
868         responseCode    : Integer;
869 begin
870
871         uri                     := TIdURI.Create( URL );
872         uriList := TStringList.Create;
873         try
874                 ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
875
876                 // http://jbbs.livedoor.com/bbs/read.cgi/game/1578/1067968274/l100
877                 postData        :=
878                         'NAME='                 + HttpEncode( SJIStoEUC( inName ) ) +
879                         '&MAIL='                + HttpEncode( SJIStoEUC( inMail ) ) +
880                         '&MESSAGE='     + HttpEncode( SJIStoEUC( inMessage ) ) +
881                         '&BBS='                 + uriList[ 4 ] +
882                         '&KEY='                 + uriList[ 5 ] +
883                         '&DIR='                 + uriList[ 3 ] +
884                         '&TIME='                + IntToStr( DateTimeToUnix( Now ) ) +
885                         '&submit='      + HttpEncode( SJIStoEUC( '\8f\91\82«\8d\9e\82Þ' ) );
886
887                 // \93Æ\8e©\82É\92Ê\90M\82µ\82È\82¢\8fê\8d\87\82Í InternalPost \82É\94C\82¹\82é\82±\82Æ\82ª\8fo\97\88\82é
888                 responseCode := InternalPost( PChar( WriteURL ), PChar( postData ), postResult );
889                 try
890                         if (responseCode = 200) or
891                                 ((responseCode = 302) and (Length( Trim( postResult ) ) = 0)) then begin
892                                 Result := dsComplete
893                         end else begin
894                                 Result := dsError;
895                                 if Assigned( InternalPrint ) then
896                                         InternalPrint( postResult );
897                         end;
898                 finally
899                         DisposeResultString( postResult );
900                 end;
901         finally
902                 uri.Free;
903                 uriList.Free;
904         end;
905
906 end;
907
908 // *************************************************************************
909 // \83\8c\83X\94Ô\8d\86 inNo \82É\91Î\82·\82é html \82ð\97v\8b\81\82³\82ê\82½
910 // *************************************************************************
911 function TShitarabaThreadItem.GetRes(
912         inNo            : Integer               // \97v\8b\81\82³\82ê\82½\83\8c\83X\94Ô\8d\86
913 ) : string;                                             // \91Î\89\9e\82·\82é HTML
914 var
915         res                     : string;
916         tmp                     : PChar;
917 begin
918
919         // \93Æ\8e©\82É\83t\83B\83\8b\83^\83\8a\83\93\83O\82ð\8ds\82í\82È\82¢\8fê\8d\87\82Í
920         // InternalAbon \82¨\82æ\82Ñ Dat2HTML \82É\94C\82¹\82é\82±\82Æ\82ª\8fo\97\88\82é
921                 {
922         LoadDat;
923         if FDat = nil then begin
924                 // \83\8d\83O\82É\91\8dÝ\82µ\82È\82¢\82Ì\82Å\82±\82Ì\82Ü\82Ü\8fI\97¹
925                 Result := '';
926                 Exit;
927         end;
928         res := Copy( FDat[ inNo - 1 ], AnsiPos( '<>', FDat[ inNo - 1 ] ) + 2, MaxInt );
929                 }
930         res := GetDat( inNo );
931         if res = '' then begin
932                 Result := '';
933                 Exit;
934         end else begin
935                 tmp := InternalAbonForOne( PChar( res ), PChar( FilePath ),inNo );
936                 try
937                         Result := Dat2HTML( string( tmp ), inNo );
938                 finally
939                         DisposeResultString( tmp );
940                 end;
941         end;
942
943 end;
944
945 // *************************************************************************
946 // \83\8c\83X\94Ô\8d\86 inNo \82É\91Î\82·\82é Dat \82ð\97v\8b\81\82³\82ê\82½
947 // *************************************************************************
948 function TShitarabaThreadItem.GetDat(
949         inNo            : Integer               // \97v\8b\81\82³\82ê\82½\83\8c\83X\94Ô\8d\86
950 ) : string;                                             // \82Q\82¿\82á\82ñ\82Ë\82é\82ÌDat\8c`\8e®
951 var
952         res                     : string;
953         tmp                     : array[1..5] of string;
954         i                       : Integer;
955         pTmp            : PChar;
956 begin
957         pTmp := nil;
958         // \93Æ\8e©\82É\83t\83B\83\8b\83^\83\8a\83\93\83O\82ð\8ds\82í\82È\82¢\8fê\8d\87\82Í
959         // InternalAbon \82¨\82æ\82Ñ Dat2HTML \82É\94C\82¹\82é\82±\82Æ\82ª\8fo\97\88\82é
960         LoadDat;
961         if (FDat = nil) or (inNo - 1 < 0 ) or (inNo - 1 >= FDat.Count) then begin
962                 // \83\8d\83O\82É\91\8dÝ\82µ\82È\82¢\82Ì\82Å\82±\82Ì\82Ü\82Ü\8fI\97¹
963                 Result := '';
964                 Exit;
965         end;
966         try
967                 res := Copy( FDat[ inNo - 1 ], AnsiPos( '<>', FDat[ inNo - 1 ] ) + 2, MaxInt );
968                 //\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é
969                 // \96¼\91O<>\83\81\81[\83\8b<>\93ú\95t<>\96{\95¶<>\83X\83\8c\83^\83C<>ID
970                 for i := 0 to 4 do begin
971                         tmp[ i + 1 ] := Copy( res, 1, AnsiPos('<>', res) - 1 );
972                         Delete( res, 1, AnsiPos('<>', res) + 1 );
973                 end;
974                 // \96¼\91O<>\83\81\81[\83\8b<>\93ú\95tID<>\96{\95¶<>\83X\83\8c\83^\83C
975                 pTmp := CreateResultString(tmp[1] + '<>' + tmp[2] + '<>' + tmp[3] + ' ' + res + '<>'+ tmp[4] + '<>' +tmp[5]);
976                 Result := string(pTmp);
977         finally
978                 DisposeResultString(pTmp);
979         end;
980
981 end;
982
983 // *************************************************************************
984 // \83X\83\8c\83b\83h\82Ì\83w\83b\83_ html \82ð\97v\8b\81\82³\82ê\82½
985 // *************************************************************************
986 function TShitarabaThreadItem.GetHeader(
987         inOptionalHeader        : string
988 ) : string;
989 begin
990
991         // \93Æ\8e©\82É\83t\83B\83\8b\83^\83\8a\83\93\83O\82ð\8ds\82í\82È\82¢\8fê\8d\87\82Í
992         // InternalHeader \82É\94C\82¹\82é\82±\82Æ\82ª\8fo\97\88\82é
993         Result := InternalHeader(
994                 '<meta http-equiv="Content-type" content="text/html; charset=Shift_JIS">' +
995                 inOptionalHeader );
996
997
998         // GetRes \82ð\8cÄ\82Î\82ê\82é\82±\82Æ\82ª\97\\91z\82³\82ê\82é\82Ì\82Å FDat \82ð\90\90¬\82µ\82Ä\82¨\82­
999         try
1000                 FreeDat;
1001                 LoadDat;
1002         except
1003         end;
1004
1005 end;
1006
1007 // *************************************************************************
1008 // \83X\83\8c\83b\83h\82Ì\83t\83b\83^ html \82ð\97v\8b\81\82³\82ê\82½
1009 // *************************************************************************
1010 function TShitarabaThreadItem.GetFooter(
1011         inOptionalFooter : string
1012 ) : string;
1013 begin
1014
1015         // \93Æ\8e©\82É\83t\83B\83\8b\83^\83\8a\83\93\83O\82ð\8ds\82í\82È\82¢\8fê\8d\87\82Í
1016         // InternalFooter \82É\94C\82¹\82é\82±\82Æ\82ª\8fo\97\88\82é
1017         Result := InternalFooter( inOptionalFooter );
1018
1019         // \82à\82¤ GetRes \82Í\8cÄ\82Î\82ê\82È\82¢\82Æ\8ev\82¤\82Ì\82Å FDat \82ð\8aJ\95ú\82µ\82Ä\82¨\82­
1020         try
1021                 FreeDat;
1022         except
1023         end;
1024
1025 end;
1026
1027 // *************************************************************************
1028 // \82±\82Ì ThreadItem \82ª\91®\82·\82é\94Â\82Ì URL \82ð\97v\8b\81\82³\82ê\82½
1029 // *************************************************************************
1030 function        TShitarabaThreadItem.GetBoardURL : string;
1031 var
1032         uri                                             : TIdURI;
1033         uriList                         : TStringList;
1034         tmphost:        String;
1035 const
1036         BBS_HOST_OLD    = 'jbbs.shitaraba.com';
1037         BBS_HOST_OLD2   = 'jbbs.livedoor.com';
1038         BBS_HOST                = 'jbbs.livedoor.jp';
1039 begin
1040
1041         uri                     := TIdURI.Create( ReadURL );
1042         uriList := TStringList.Create;
1043         try
1044                 ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
1045
1046                 tmphost := uri.Host;
1047
1048                 if (tmphost = BBS_HOST_OLD) or (tmphost = BBS_HOST_OLD2) then
1049                         tmphost := BBS_HOST;
1050
1051                 FileName := uriList[ 5 ] + '.dat';
1052                 // http://jbbs.livedoor.com/bbs/read.cgi/computer/351/1090404452/l100
1053                 // http://jbbs.livedoor.com/bbs/read.cgi/game/1578/1067968274/l100
1054                 // http://jbbs.livedoor.com/game/1000/subject.txt
1055                 Result          := CreateResultString(
1056                         uri.Protocol + '://' + tmphost + '/' + uriList[ 3 ] + '/' + uriList[ 4 ] + '/' );
1057         finally
1058                 uri.Free;
1059                 uriList.Free;
1060         end;
1061
1062 end;
1063
1064 // *************************************************************************
1065 // FDat \82Ì\90\90¬
1066 // *************************************************************************
1067 procedure       TShitarabaThreadItem.LoadDat;
1068 begin
1069
1070         if FDat = nil then begin
1071                 if IsLogFile then begin
1072                         // dat \82Ì\93Ç\82Ý\8d\9e\82Ý
1073                         FDat := TStringList.Create;
1074                         FDat.LoadFromFile( FilePath );
1075                 end;
1076         end;
1077
1078 end;
1079
1080 // *************************************************************************
1081 // FDat \82Ì\8aJ\95ú
1082 // *************************************************************************
1083 procedure       TShitarabaThreadItem.FreeDat;
1084 begin
1085
1086         if FDat <> nil then begin
1087                 FDat.Free;
1088                 FDat := nil;
1089         end;
1090
1091 end;
1092
1093 // *************************************************************************
1094 // \88À\91S\82È\83u\83\89\83E\83U\95\\8e¦\97p\82Ì URL
1095 // *************************************************************************
1096 function        TShitarabaThreadItem.BrowsableURL : string;
1097 const
1098         THREAD_MARK     = '/bbs/read.cgi';
1099 var
1100         uri                             : TIdURI;
1101         uriList         : TStringList;
1102         foundPos        : Integer;
1103         dir, tmphost            : string;
1104 const
1105         BBS_HOST_OLD    = 'jbbs.shitaraba.com';
1106         BBS_HOST_OLD2   = 'jbbs.livedoor.com';
1107         BBS_HOST                = 'jbbs.livedoor.jp';
1108 begin
1109
1110         foundPos := AnsiPos( '?', URL );
1111         if foundPos > 0 then begin
1112                 // \8b\8c\8e®
1113                 uri := TIdURI.Create( URL );
1114                 uriList := TStringList.Create;
1115                 try
1116                         ExtractHttpFields( ['/'], [], uri.Path, uriList );
1117                         dir := uriList[ 1 ];
1118
1119                         tmphost := uri.Host;
1120                         if (tmphost = BBS_HOST_OLD) or (tmphost = BBS_HOST_OLD2)  then
1121                                 tmphost := BBS_HOST;
1122
1123                         ExtractHttpFields( ['&'], [], Copy( URL, foundPos + 1, MaxInt ), uriList );
1124                         Result :=
1125                                 uri.Protocol + '://' + tmphost + '/bbs/read.cgi/' +
1126                                 dir + '/' + uriList.Values[ 'BBS' ] + '/' + uriList.Values[ 'KEY' ] + '/l100';
1127                 finally
1128                         uri.Free;
1129                         uriList.Free;
1130                 end;
1131         end else begin
1132                 if Copy( URL, Length( URL ), 1 ) = '/' then
1133                         uri := TIdURI.Create( URL )
1134                 else
1135                         uri := TIdURI.Create( URL + '/' );
1136
1137                 uriList := TStringList.Create;
1138                 try
1139                         ExtractHttpFields( ['/'], [], uri.Path, uriList );
1140
1141                         tmphost := uri.Host;
1142                         if (tmphost = BBS_HOST_OLD) or (tmphost = BBS_HOST_OLD2)  then
1143                                 tmphost := BBS_HOST;
1144
1145                         if( AnsiPos(THREAD_MARK, URL) > 0) and (uriList.Count > 5) then begin
1146                                 Result :=
1147                                         uri.Protocol + '://' + tmphost + THREAD_MARK + '/' +
1148                                         uriList[ 3 ] + '/' + uriList[ 4 ] + '/' + uriList[ 5 ] + '/l100';
1149
1150                         end else if AnsiPos(THREAD_MARK, URL) = 0 then begin
1151                         //\83R\83R\82Å\89ß\8b\8e\83\8d\83O\82©\82Ç\82¤\82©\83`\83F\83b\83N\81H
1152                                 if(AnsiPos('.html/', uri.Path) > 0) then begin
1153                                         Result := uri.Protocol + '://' + tmphost + THREAD_MARK +
1154                                                 CustomStringReplace(CustomStringReplace(uri.Path, '/storage', ''), '.html/', '/') + 'l100';
1155                                 end else
1156                                         Result := URL;
1157                         end;
1158                 finally
1159                         uri.Free;
1160                         uriList.Free;
1161                 end;
1162         end;
1163
1164 end;
1165
1166 // *************************************************************************
1167 // \88À\91S\82È( '/' \82Å\8fI\82í\82é )\93Ç\82Ý\8d\9e\82Ý\82Ì URL
1168 // *************************************************************************
1169 function        TShitarabaThreadItem.ReadURL : string;
1170 const
1171         THREAD_MARK     = '/bbs/read.cgi';
1172 var
1173         uri                             : TIdURI;
1174         uriList         : TStringList;
1175         foundPos        : Integer;
1176         dir, tmphost                    : string;
1177 const
1178         BBS_HOST_OLD    = 'jbbs.shitaraba.com';
1179         BBS_HOST_OLD2   = 'jbbs.livedoor.com';
1180         BBS_HOST                = 'jbbs.livedoor.jp';
1181 begin
1182
1183         foundPos := AnsiPos( '?', URL );
1184         if foundPos > 0 then begin
1185                 // \8b\8c\8e®
1186                 uri := TIdURI.Create( URL );
1187                 uriList := TStringList.Create;
1188                 try
1189                         ExtractHttpFields( ['/'], [], uri.Path, uriList );
1190                         dir := uriList[ 1 ];
1191
1192                         tmphost := uri.Host;
1193                         if (tmphost = BBS_HOST_OLD) or (tmphost = BBS_HOST_OLD2)  then
1194                                 tmphost := BBS_HOST;
1195
1196                         ExtractHttpFields( ['&'], [], Copy( URL, foundPos + 1, MaxInt ), uriList );
1197                         // http://jbbs.livedoor.com/bbs/read.cgi?DIR=game&BBS=1578&KEY=1067968274
1198                         Result :=
1199                                 uri.Protocol + '://' + tmphost + '/bbs/rawmode.cgi/' +
1200                                 dir + '/' + uriList.Values[ 'BBS' ] + '/' + uriList.Values[ 'KEY' ] + '/';
1201                 finally
1202                         uri.Free;
1203                         uriList.Free;
1204                 end;
1205         end else begin
1206                 if Copy( URL, Length( URL ), 1 ) = '/' then
1207                         uri := TIdURI.Create( URL )
1208                 else
1209                         uri := TIdURI.Create( URL + '/' );
1210                 uriList := TStringList.Create;
1211                 try
1212                         ExtractHttpFields( ['/'], [], uri.Path, uriList );
1213
1214                         tmphost := uri.Host;
1215                         if (tmphost = BBS_HOST_OLD) or (tmphost = BBS_HOST_OLD2)  then
1216                                 tmphost := BBS_HOST;
1217                         // http://jbbs.livedoor.com/bbs/read.cgi/game/1578/1067968274/l100
1218                         if( AnsiPos(THREAD_MARK, URL) > 0) and (uriList.Count > 5) then begin
1219                                 Result :=
1220                                         uri.Protocol + '://' + tmphost + '/bbs/rawmode.cgi/' +
1221                                         uriList[ 3 ] + '/' + uriList[ 4 ] + '/' + uriList[ 5 ] + '/';
1222                         end;
1223                 finally
1224                         uri.Free;
1225                         uriList.Free;
1226                 end;
1227         end;
1228
1229 end;
1230
1231 // *************************************************************************
1232 // \88À\91S\82È( '/' \82Å\8fI\82í\82é )\8f\91\82«\8d\9e\82Ý\82Ì URL
1233 // *************************************************************************
1234 function        TShitarabaThreadItem.WriteURL : string;
1235 var
1236         uri                     : TIdURI;
1237         uriList : TStringList;
1238 begin
1239
1240         if Copy( URL, Length( URL ), 1 ) = '/' then
1241                 uri := TIdURI.Create( URL )
1242         else
1243                 uri := TIdURI.Create( URL + '/' );
1244         uriList := TStringList.Create;
1245         try
1246                 ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
1247                 // http://jbbs.livedoor.com/bbs/read.cgi/game/1578/1067968274/l100
1248                 Result          :=
1249                         uri.Protocol + '://' + uri.Host + '/bbs/write.cgi/' +
1250                         uriList[ 3 ] + '/' + uriList[ 4 ] + '/' + uriList[ 5 ] + '/';
1251         finally
1252                 uri.Free;
1253                 uriList.Free;
1254         end;
1255
1256 end;
1257
1258 // *************************************************************************
1259 // TThreadItem \82ª\90\90¬\82³\82ê\82½\8fê\8d\87\82Ì\8f\88\92u(TShitarabaThreadItem \82ð\90\90¬\82·\82é)
1260 // *************************************************************************
1261 procedure ThreadItemOnCreateOfTShitarabaThreadItem(
1262         inInstance : DWORD
1263 );
1264 var
1265         threadItem : TShitarabaThreadItem;
1266 begin
1267
1268         threadItem := TShitarabaThreadItem.Create( inInstance );
1269         ThreadItemSetLong( inInstance, tipContext, DWORD( threadItem ) );
1270
1271 end;
1272
1273 // *************************************************************************
1274 // TThreadItem \82ª\94j\8aü\82³\82ê\82½\8fê\8d\87\82Ì\8f\88\92u(TShitarabaThreadItem \82ð\94j\8aü\82·\82é)
1275 // *************************************************************************
1276 procedure ThreadItemOnDisposeOfTShitarabaThreadItem(
1277         inInstance : DWORD
1278 );
1279 var
1280         threadItem : TShitarabaThreadItem;
1281 begin
1282
1283         threadItem := TShitarabaThreadItem( ThreadItemGetLong( inInstance, tipContext ) );
1284         threadItem.Free;
1285
1286 end;
1287
1288 // =========================================================================
1289 // TShitarabaBoardItem
1290 // =========================================================================
1291
1292 // *************************************************************************
1293 // \83R\83\93\83X\83g\83\89\83N\83^
1294 // *************************************************************************
1295 constructor TShitarabaBoardItem.Create(
1296         inInstance      : DWORD
1297 );
1298 var
1299         uri                                     : TIdURI;
1300         uriList                 : TStringList;
1301 const
1302         BBS_HOST_OLD    = 'jbbs.shitaraba.com';
1303         BBS_HOST_OLD2   = 'jbbs.livedoor.com';
1304         BBS_HOST                = 'jbbs.livedoor.jp';
1305 begin
1306
1307         inherited;
1308
1309         OnDownload                                              := Download;
1310         OnCreateThread                          := CreateThread;
1311         OnEnumThread                                    := EnumThread;
1312         OnFileName2ThreadURL    := ToThreadURL;
1313
1314         FilePath                        := '';
1315         FIsTemporary    := False;
1316         FDat                                    := nil;
1317
1318         uri                     := TIdURI.Create( SubjectURL );
1319         uriList := TStringList.Create;
1320         try
1321                 if (uri.Host = BBS_HOST_OLD) or (uri.Host = BBS_HOST_OLD2) then
1322                         uri.Host := BBS_HOST;
1323                 URL := uri.Protocol + '://' + uri.Host + uri.Path;
1324
1325                 ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
1326                 // http://jbbs.livedoor.com/game/1000/subject.txt
1327                 FilePath        := MyLogFolder + uriList[ 1 ] + '\' + uriList[ 2 ] + '\' + uri.Document;
1328                 IsLogFile       := FileExists( FilePath );
1329         finally
1330                 uri.Free;
1331                 uriList.Free;
1332         end;
1333
1334 end;
1335  
1336 // *************************************************************************
1337 // \83f\83X\83g\83\89\83N\83^
1338 // *************************************************************************
1339 destructor TShitarabaBoardItem.Destroy;
1340 begin
1341
1342         if FDat <> nil then begin
1343                 try
1344                         FDat.Free;
1345                         FDat := nil;
1346                 except
1347                 end;
1348         end;
1349
1350         // \88ê\8e\9e\83t\83@\83C\83\8b\82Ì\8fê\8d\87\82Í\8dí\8f\9c\82·\82é
1351         if FIsTemporary then
1352                 DeleteFile( FilePath );
1353
1354         inherited;
1355
1356 end;
1357
1358 // *************************************************************************
1359 // \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½
1360 // *************************************************************************
1361 function TShitarabaBoardItem.Download : TDownloadState;
1362 var
1363         modified                        : Double;
1364         downResult              : PChar;
1365         responseCode    : Longint;
1366         uri                                             : TIdURI;
1367         uriList                         : TStringList;
1368         i                                                       : Integer;
1369                 tmpText : String;
1370 begin
1371
1372         Result := dsError;
1373
1374         if FDat <> nil then begin
1375                 try
1376                         FDat.Free;
1377                         FDat := nil;
1378                 except
1379                 end;
1380         end;
1381         FDat            := TStringList.Create;
1382         uri                     := TIdURI.Create( SubjectURL );
1383         uriList := TStringList.Create;
1384         // \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Í
1385         // InternalDownload \82É\94C\82¹\82é\82±\82Æ\82ª\8fo\97\88\82é
1386         modified                        := LastModified;
1387         responseCode    := InternalDownload( PChar( uri.URI ), modified, downResult );
1388         try
1389                 if responseCode = 200 then begin
1390                         try
1391                                 // \83p\83X\82ð\8eZ\8fo
1392                                 ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
1393                                 if MyLogFolder = '' then begin
1394                                         // \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
1395                                         FilePath                        := TemporaryFile;
1396                                         FIsTemporary    := True;
1397                                 end else begin
1398                                         FilePath                        := MyLogFolder + uriList[ 1 ] + '\' + uriList[ 2 ] + '\' + uri.Document;
1399                                         FIsTemporary    := False
1400                                 end;
1401
1402                                 // \95Û\91\97p\82Ì\83f\83B\83\8c\83N\83g\83\8a\82ð\8c@\82é
1403                                 ForceDirectoriesEx( Copy( FilePath, 1, LastDelimiter( '\', FilePath ) ) );
1404
1405                                 // EUC \82ð Shift_JIS \82É
1406                                                                 tmpText := CustomStringReplace( string( downResult ), '¡÷¡®', ',');
1407                                 FDat.Text := EUCtoSJIS( tmpText );
1408                                 // \82µ\82½\82ç\82ΠJBBS \82Í\83`\83F\83b\83N\97p\82É\90æ\93ª\82Æ\8dÅ\8fI\8ds\82ª\93¯\82
1409                                 i := FDat.Count - 1;
1410                                 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¸
1411                                         if FDat[ 0 ] = FDat[ i ] then
1412                                                 FDat.Delete( i );
1413                                 // \95Û\91
1414                                 FDat.SaveToFile( FilePath );
1415
1416                                 IsLogFile                       := True;
1417                                 RoundDate                       := Now;
1418                                 LastModified    := modified;
1419                                 LastGetTime             := Now;
1420                         finally
1421                                 uri.Free;
1422                                 uriList.Free;
1423                         end;
1424                         Result := dsComplete;
1425                 end;
1426         finally
1427                 DisposeResultString( downResult );
1428         end;
1429
1430 end;
1431
1432 // *************************************************************************
1433 // \83X\83\8c\97§\82Ä\82ð\8ew\8e¦\82³\82ê\82½
1434 // *************************************************************************
1435 function        TShitarabaBoardItem.CreateThread(
1436         inSubject                       : string;       // \83X\83\8c\83^\83C
1437         inName                          : string;       // \96¼\91O(\83n\83\93\83h\83\8b)
1438         inMail                          : string;       // \83\81\81[\83\8b\83A\83h\83\8c\83X
1439         inMessage                       : string        // \96{\95
1440 ) : TDownloadState;                             // \8f\91\82«\8d\9e\82Ý\82ª\90¬\8c÷\82µ\82½\82©\82Ç\82¤\82©
1441 var
1442         postURL                         : string;
1443         postData                        : string;
1444         postResult              : PChar;
1445         uri                                             : TIdURI;
1446         uriList                         : TStringList;
1447         responseCode    : Integer;
1448 begin
1449
1450         uri                     := TIdURI.Create( URL );
1451         uriList := TStringList.Create;
1452         try
1453                 ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
1454
1455                 // http://jbbs.livedoor.com/bbs/write.cgi/game/1578/new/
1456                 // http://jbbs.livedoor.com/game/1000/subject.txt
1457                 postURL         :=
1458                         uri.Protocol + '://' + uri.Host + '/bbs/write.cgi/' +
1459                         uriList[ 1 ] + '/' + uriList[ 2 ] + '/new/';
1460                 postData        :=
1461                         'SUBJECT='      + HttpEncode( SJIStoEUC( inSubject ) ) +
1462                         '&NAME='                + HttpEncode( SJIStoEUC( inName ) ) +
1463                         '&MAIL='                + HttpEncode( SJIStoEUC( inMail ) ) +
1464                         '&MESSAGE='     + HttpEncode( SJIStoEUC( inMessage ) ) +
1465                         '&BBS='                 + uriList[ 4 ] +
1466                         '&DIR='                 + uriList[ 3 ] +
1467                         '&TIME='                + IntToStr( DateTimeToUnix( Now ) ) +
1468                         '&submit='      + HttpEncode( SJIStoEUC( '\90V\8bK\8f\91\82«\8d\9e\82Ý' ) );
1469
1470                 // \93Æ\8e©\82É\92Ê\90M\82µ\82È\82¢\8fê\8d\87\82Í InternalPost \82É\94C\82¹\82é\82±\82Æ\82ª\8fo\97\88\82é
1471                 responseCode := InternalPost( PChar( postURL ), PChar( postData ), postResult );
1472                 try
1473                         if (responseCode = 200) or
1474                                 ((responseCode = 302) and (Length( Trim( postResult ) ) = 0)) then begin
1475                                 Result := dsComplete
1476                         end else begin
1477                                 Result := dsError;
1478                                 if Assigned( InternalPrint ) then
1479                                         InternalPrint( postResult );
1480                         end;
1481                 finally
1482                         DisposeResultString( postResult );
1483                 end;
1484         finally
1485                 uri.Free;
1486                 uriList.Free;
1487         end;
1488
1489 end;
1490
1491 // *************************************************************************
1492 // \83X\83\8c\88ê\97\97\82Ì URL \82©\82ç\83X\83\8c\83b\83h\82Ì URL \82ð\93±\82«\8fo\82·
1493 // *************************************************************************
1494 function TShitarabaBoardItem.ToThreadURL(
1495         inFileName      : string        // \83X\83\8c\83b\83h\83t\83@\83C\83\8b\96¼
1496 ) : string;                                                     // \83X\83\8c\83b\83h\82Ì URL
1497 var
1498         threadURL               : string;
1499         uri                                     : TIdURI;
1500         uriList                 : TStringList;
1501         found                           : Integer;
1502 begin
1503
1504         found := AnsiPos( '.', inFileName );
1505         if found > 0 then
1506                 inFileName := Copy( inFileName, 1, found - 1 );
1507
1508         uri                     := TIdURI.Create( SubjectURL );
1509         uriList := TStringList.Create;
1510         try
1511                 try
1512                         ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
1513                         threadURL       := uri.Protocol + '://' + uri.Host + '/bbs/read.cgi/' +
1514                                 uriList[ 1 ] + '/' + uriList[ 2 ] + '/' + inFileName + '/l100';
1515                         Result          := threadURL;
1516                 finally
1517                         uri.Free;
1518                         uriList.Free;
1519                 end;
1520         except
1521                 Result := '';
1522         end;
1523
1524 end;
1525
1526 // *************************************************************************
1527 // \82±\82Ì\94Â\82É\82¢\82­\82Â\82Ì\83X\83\8c\82ª\82 \82é\82©\97v\8b\81\82³\82ê\82½
1528 // *************************************************************************
1529 procedure       TShitarabaBoardItem.EnumThread(
1530         inCallBack      : TBoardItemEnumThreadCallBack
1531 );
1532 var
1533         uri                                     : TIdURI;
1534         uriList                 : TStringList;
1535 begin
1536
1537         try
1538                 if FDat = nil then begin
1539                         FDat            := TStringList.Create;
1540                         uri                     := TIdURI.Create( SubjectURL );
1541                         uriList := TStringList.Create;
1542                         try
1543                                 // \83p\83X\82ð\8eZ\8fo
1544                                 ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
1545                                 // http://jbbs.livedoor.com/game/1000/subject.txt
1546                                 FilePath        := MyLogFolder + uriList[ 1 ] + '\' + uriList[ 2 ] + '\' + uri.Document;
1547                                 if FileExists( FilePath ) then
1548                                         // \93Ç\82Ý\8d\9e\82Ý
1549                                         FDat.LoadFromFile( FilePath );
1550                         finally
1551                                 uri.Free;
1552                                 uriList.Free;
1553                         end;
1554                 end;
1555
1556                 // \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é
1557                 inherited EnumThread( inCallBack, CustomStringReplace( FDat.Text, ',', '<>' ) );
1558         except
1559         end;
1560
1561 end;
1562
1563 // *************************************************************************
1564 // \83X\83\8c\88ê\97\97\82Ì URL \82ð\8b\81\82ß\82é
1565 // *************************************************************************
1566 function        TShitarabaBoardItem.SubjectURL : string;
1567 var
1568         uri                     : TIdURI;
1569         uriList : TStringList;
1570 begin
1571
1572         uri                     := TIdURI.Create( URL );
1573         uriList := TStringList.Create;
1574         try
1575                 if uri.Document <> SUBJECT_NAME then begin
1576                         if Copy( URL, Length( URL ), 1 ) = '/' then
1577                                 Result := URL + SUBJECT_NAME
1578                         else
1579                                 Result := URL + '/' + SUBJECT_NAME;
1580                 end else begin
1581                         // \82±\82±\82É\82Í\97\88\82È\82¢\82Æ\8ev\82¤\82¯\82Ç
1582                         Result := URL;
1583                 end;
1584         finally
1585                 uri.Free;
1586                 uriList.Free;
1587         end;
1588
1589 end;
1590
1591 // *************************************************************************
1592 // TBoardItem \82ª\90\90¬\82³\82ê\82½\8fê\8d\87\82Ì\8f\88\92u(TShitarabaBoardItem \82ð\90\90¬\82·\82é)
1593 // *************************************************************************
1594 procedure BoardItemOnCreateOfTShitarabaBoardItem(
1595         inInstance : DWORD
1596 );
1597 var
1598         boardItem : TShitarabaBoardItem;
1599 begin
1600
1601         boardItem := TShitarabaBoardItem.Create( inInstance );
1602         BoardItemSetLong( inInstance, bipContext, DWORD( boardItem ) );
1603
1604 end;
1605
1606 // *************************************************************************
1607 // TBoardItem \82ª\94j\8aü\82³\82ê\82½\8fê\8d\87\82Ì\8f\88\92u(TShitarabaBoardItem \82ð\94j\8aü\82·\82é)
1608 // *************************************************************************
1609 procedure BoardItemOnDisposeOfTShitarabaBoardItem(
1610         inInstance : DWORD
1611 );
1612 var
1613         boardItem : TShitarabaBoardItem;
1614 begin
1615
1616         boardItem := TShitarabaBoardItem( BoardItemGetLong( inInstance, bipContext ) );
1617         boardItem.Free;
1618
1619 end;
1620
1621
1622
1623 // =========================================================================
1624 // \83G\83\93\83g\83\8a\83|\83C\83\93\83g
1625 // =========================================================================
1626 procedure DLLEntry(
1627         ul_reason_for_call : DWORD
1628 );
1629 var
1630         module : HMODULE;
1631 begin
1632
1633         case ul_reason_for_call of
1634                 DLL_PROCESS_ATTACH:
1635                 begin
1636                         Randomize;
1637
1638                         module := GetModuleHandle( nil );
1639
1640                         LoadInternalAPI( module );
1641                         LoadInternalFilePathAPI( module );
1642                         LoadInternalThreadItemAPI( module );
1643                         LoadInternalBoardItemAPI( module );
1644
1645                         // ===== \83C\83\93\83X\83^\83\93\83X\82Ì\8eæ\82è\88µ\82¢\82ð TThreadItem \82©\82ç TShitarabaThreadItem \82É\95Ï\8dX\82·\82é
1646                         ThreadItemOnCreate      := ThreadItemOnCreateOfTShitarabaThreadItem;
1647                         ThreadItemOnDispose     := ThreadItemOnDisposeOfTShitarabaThreadItem;
1648                         // ===== \83C\83\93\83X\83^\83\93\83X\82Ì\8eæ\82è\88µ\82¢\82ð TBoardItem \82©\82ç TShitarabaBoardItem \82É\95Ï\8dX\82·\82é
1649                         BoardItemOnCreate               := BoardItemOnCreateOfTShitarabaBoardItem;
1650                         BoardItemOnDispose      := BoardItemOnDisposeOfTShitarabaBoardItem;
1651                 end;
1652                 DLL_PROCESS_DETACH:
1653                 begin
1654                         RemovePlugInMenu( SyncronizeMenu );
1655                 end;
1656                 DLL_THREAD_ATTACH:
1657                         ;
1658                 DLL_THREAD_DETACH:
1659                         ;
1660         end;
1661
1662 end;
1663
1664 exports
1665         OnLoad,
1666         OnVersionInfo,
1667         OnAcceptURL,
1668         OnPlugInMenu;
1669
1670 begin
1671
1672         try
1673                 DllProc := @DLLEntry;
1674                 DLLEntry( DLL_PROCESS_ATTACH );
1675         except end;
1676
1677 end.