OSDN Git Service

MojuUtilsへのpathを相対参照にした。
[gikonavigoeson/gikonavi.git] / res / ExternalBoardPlugIn / MachiBBSPlugIn.dpr
1 library MachiBBSPlugIn;
2
3 {
4         MachiBBSBoardPlugIn
5         \82Ü\82¿BBS\8f\88\97\9d\83\86\83j\83b\83g
6 }
7
8 uses
9         Windows, SysUtils, Classes, Math, DateUtils,
10         IdURI,
11         PlugInMain in 'PlugInMain.pas',
12         ThreadItem in 'ThreadItem.pas',
13         BoardItem in 'BoardItem.pas',
14         FilePath in 'FilePath.pas',
15     MojuUtils in '..\..\MojuUtils.pas';
16
17 {$R *.res}
18
19 type
20         // =========================================================================
21         // TMachiBBSThreadItem
22         // =========================================================================
23         TMachiBBSThreadItem = class(TThreadItem)
24         private
25                 FIsTemporary    : Boolean;
26                 FDat                                    : TStringList;
27
28         public
29                 constructor     Create( inInstance : DWORD );
30                 destructor      Destroy; override;
31
32         private
33                 function        Download : TDownloadState;
34                 function        Write( inName : string; inMail : string; inMessage : string ) : TDownloadState;
35                 function        GetRes( inNo : Integer ) : string;
36                 function        GetHeader( inOptionalHeader : string ) : string;
37                 function        GetFooter( inOptionalFooter : string ) : string;
38                 function        GetBoardURL : string;
39
40                 procedure       To2chDat( ioHTML : TStringList; inStartNo : Integer = 1 );
41                 procedure       LoadDat;
42                 procedure       FreeDat;
43                 function        ReadURL : string;
44         end;
45
46         // =========================================================================
47         // TMachiBBSBoardItem
48         // =========================================================================
49         TMachiBBSBoardItem = class(TBoardItem)
50         private
51                 FIsTemporary    : Boolean;
52                 FDat                                    : TStringList;
53
54         public
55                 constructor     Create( inInstance : DWORD );
56                 destructor      Destroy; override;
57
58         private
59                 function        Download : TDownloadState;
60                 function        CreateThread( inSubject : string; inName : string; inMail : string; inMessage : string ) : TDownloadState;
61                 function        ToThreadURL( inFileName : string ) : string;
62                 procedure       EnumThread( inCallBack : TBoardItemEnumThreadCallBack );
63
64                 function        SubjectURL : string;
65         end;
66
67         // =========================================================================
68         // \83T\83u\83W\83F\83N\83g\83\8c\83R\81[\83h
69         // =========================================================================
70         TSubjectRec = record
71                 FFileName: string;
72                 FTitle: string;
73                 FCount: Integer;
74         end;
75
76 const
77         LOG_DIR                                         = 'MachiBBS\';
78         SUBJECT_NAME                    = 'subject.txt';
79
80         PLUGIN_NAME                             = 'MachiBBSPlugIn';
81         MAJOR_VERSION                   = 1;
82         MINOR_VERSION                   = 0;
83         RELEASE_VERSION         = 'beta';
84         REVISION_VERSION        = 11;
85
86 // =========================================================================
87 // \8eG\97p\8aÖ\90\94
88 // =========================================================================
89
90 // *************************************************************************
91 // \83e\83\93\83|\83\89\83\8a\82È\83p\83X\82Ì\8eæ\93¾
92 // *************************************************************************
93 function TemporaryFile : string;
94 var
95         tempPath : array [0..MAX_PATH] of       char;
96 begin
97
98         GetTempPath( SizeOf(tempPath), tempPath );
99         repeat
100                 Result := tempPath + IntToStr( Random( $7fffffff ) );
101         until not FileExists( Result );
102
103 end;
104
105 // *************************************************************************
106 // \82Ü\82¿BBS\97p\83\8d\83O\83t\83H\83\8b\83_\8eæ\93¾
107 // *************************************************************************
108 function MyLogFolder : string;
109 var
110         folder : string;
111 begin
112
113         folder := LogFolder;
114         if Length( folder ) = 0 then
115                 Result := ''
116         else
117                 Result := folder + LOG_DIR;
118
119 end;
120
121 (*************************************************************************
122  *\83f\83B\83\8c\83N\83g\83\8a\82ª\91\8dÝ\82·\82é\82©\83`\83F\83b\83N
123  *************************************************************************)
124 function DirectoryExistsEx(const Name: string): Boolean;
125 var
126         Code: Integer;
127 begin
128         Code := GetFileAttributes(PChar(Name));
129         Result := (Code <> -1) and (FILE_ATTRIBUTE_DIRECTORY and Code <> 0);
130 end;
131
132 (*************************************************************************
133  *\83f\83B\83\8c\83N\83g\83\8a\8dì\90¬\81i\95¡\90\94\8aK\91w\91Î\89\9e\81j
134  *************************************************************************)
135 function ForceDirectoriesEx(Dir: string): Boolean;
136 begin
137         Result := True;
138         if Length(Dir) = 0 then
139                 raise Exception.Create('\83t\83H\83\8b\83_\82ª\8dì\90¬\8fo\97\88\82Ü\82¹\82ñ');
140         Dir := ExcludeTrailingPathDelimiter(Dir);
141         if (Length(Dir) < 3) or DirectoryExistsEx(Dir)
142                 or (ExtractFilePath(Dir) = Dir) then Exit; // avoid 'xyz:\' problem.
143         Result := ForceDirectoriesEx(ExtractFilePath(Dir)) and CreateDir(Dir);
144 end;
145
146 // \82Æ\82è\82 \82¦\82¸\82Ì\91ã\97p\95i\82È\82Ì\82Å chrWhite \82ð\8dl\97\82µ\82Ä\82¢\82È\82¢\82±\82Æ\82É\92\8d\88Ó\81I\81I\81I
147 procedure ExtractHttpFields(
148         const chrSep : TSysCharSet;
149         const chrWhite : TSysCharSet;
150         const strValue : string;
151         var strResult : TStringList;
152         unknownFlag : boolean = false
153 );
154 var
155         last, p, strLen : Integer;
156 begin
157
158         strLen := Length( strValue );
159         p := 1;
160         last := 1;
161
162         while p <= strLen do
163         begin
164
165                 if strValue[ p ] in chrSep then
166                 begin
167                         strResult.Add( Copy( strValue, last, p - last ) );
168                         last := p + 1;
169                 end;
170
171                 p := p + 1;
172
173         end;
174
175         if last <> p then
176                 strResult.Add( Copy( strValue, last, strLen - last + 1 ) );
177
178 end;
179
180 \rfunction HttpEncode(
181 \r       const strValue : string
182 ) : string;
183 var
184         i : Integer;
185         strLen : Integer;
186         strResult : string;
187         b : Integer;
188 const
189         kHexCode : array [0..15] of char = (
190                                 '0', '1', '2', '3', '4', '5', '6', '7',
191                                 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' );
192 begin
193
194         strLen := Length( strValue );
195         i := 1;
196
197         while i <= strLen do
198         begin
199
200                 case strValue[ i ] of
201                 '0' .. '9', 'a' .. 'z', 'A' .. 'Z', '*', '-', '.', '@', '_':
202                         begin
203                                 strResult := strResult + strValue[ i ];
204                         end;
205                 else
206                         begin
207                                 b := Integer( strValue[ i ] );
208                                 strResult := strResult + '%'
209                                                                 + kHexCode[ b div $10 ]
210                                                                 + kHexCode[ b mod $10 ];
211                         end;
212                 end;
213
214                 i := i + 1;
215
216         end;
217
218         Result := strResult;
219
220 end;
221
222
223
224 // =========================================================================
225 // PlugIn
226 // =========================================================================
227
228 // *************************************************************************
229 // \83v\83\89\83O\83C\83\93\82Ì\83o\81[\83W\83\87\83\93\82ð\97v\8b\81\82³\82ê\82½
230 // *************************************************************************
231 procedure OnVersionInfo(
232         var outAgent            : PChar;        // \83o\81[\83W\83\87\83\93\82ð\88ê\90Ø\8aÜ\82Ü\82È\82¢\8f\83\90\88\82È\96¼\8fÌ
233         var outMajor            : DWORD;        // \83\81\83W\83\83\81[\83o\81[\83W\83\87\83\93
234         var outMinor            : DWORD;        // \83}\83C\83i\81[\83o\81[\83W\83\87\83\93
235         var outRelease  : PChar;        // \83\8a\83\8a\81[\83X\92i\8aK\96¼
236         var outRevision : DWORD         // \83\8a\83r\83W\83\87\83\93\83i\83\93\83o\81[
237 ); stdcall;
238 begin
239
240         try
241                 outAgent                := CreateResultString( PChar( PLUGIN_NAME ) );
242                 outMajor                := MAJOR_VERSION;
243                 outMinor                := MINOR_VERSION;
244                 outRelease      := CreateResultString( PChar( RELEASE_VERSION ) );
245                 outRevision     := REVISION_VERSION;
246         except
247                 outAgent                := nil;
248                 outMajor                := 0;
249                 outMinor                := 0;
250                 outRelease      := nil;
251                 outRevision     := 0;
252         end;
253
254 end;
255
256 // *************************************************************************
257 // \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©
258 // *************************************************************************
259 function OnAcceptURL(
260         inURL                   : PChar                         // \94»\92f\82ð\8bÂ\82¢\82Å\82¢\82é URL
261 ): TAcceptType; stdcall;        // URL \82Ì\8eí\97Þ
262 var
263         uri                             : TIdURI;
264         uriList         : TStringList;
265         foundPos        : Integer;
266 const
267         BBS_HOST                = 'machi.to';
268         THREAD_MARK     = '/bbs/read.pl';
269 begin
270
271         try
272                 // \83z\83X\83g\96¼\82ª machi.to \82Å\8fI\82í\82é\8fê\8d\87\82Í\8eó\82¯\95t\82¯\82é\82æ\82¤\82É\82µ\82Ä\82¢\82é
273                 uri                     := TIdURI.Create( inURL );
274                 uriList := TStringList.Create;
275                 try
276                         ExtractHttpFields( ['/'], [], uri.Path, uriList );
277                         foundPos := AnsiPos( BBS_HOST, uri.Host );
278                         if (foundPos > 0) and (Length( uri.Host ) - foundPos + 1 = Length( BBS_HOST )) then begin
279                                 foundPos := Pos( THREAD_MARK, inURL );
280                                 if foundPos > 0 then
281                                         Result := atThread
282                                 else if (uriList.Count > 1) and (uri.Path <> '/') then  // \8dÅ\8cã\82ª '/' \82Å\95Â\82ß\82ç\82ê\82Ä\82é\82È\82ç 3
283                                         Result := atBoard
284                                 else
285                                         Result := atBBS;
286                         end else begin
287                                 Result := atNoAccept;
288                         end;
289                 finally
290                         uri.Free;
291                         uriList.Free;
292                 end;
293         except
294                 Result := atNoAccept;
295         end;
296
297 end;
298
299
300
301 // =========================================================================
302 // TMachiBBSThreadItem
303 // =========================================================================
304
305 // *************************************************************************
306 // \83R\83\93\83X\83g\83\89\83N\83^
307 // *************************************************************************
308 constructor TMachiBBSThreadItem.Create(
309         inInstance      : DWORD
310 );
311 var
312         uri                                     : TIdURI;
313         uriList                 : TStringList;
314 begin
315
316         inherited;
317
318         OnDownload              := Download;
319         OnWrite                         := Write;
320         OnGetRes                        := GetRes;
321         OnGetHeader             := GetHeader;
322         OnGetFooter             := GetFooter;
323         OnGetBoardURL   := GetBoardURL;
324
325         FilePath                        := '';
326         FIsTemporary    := False;
327         FDat                                    := nil;
328         URL                                             := ReadURL + '&LAST=50';
329
330         uri                     := TIdURI.Create( URL );
331         uriList := TStringList.Create;
332         try
333                 // http://hokkaido.machi.to/bbs/read.pl?BBS=hokkaidou&KEY=1061764446&LAST=50
334                 ExtractHttpFields(
335                         ['&'], [],
336                         Copy( uri.Params, AnsiPos( '?', uri.Params ) + 1, Length( uri.Params ) ), uriList );
337                 FileName        := uriList.Values[ 'KEY' ] + '.dat';
338                 FilePath        := MyLogFolder + uriList.Values[ 'BBS' ] + '\' + uriList.Values[ 'KEY' ] + '.dat';
339                 IsLogFile       := FileExists( FilePath );
340         finally
341                 uri.Free;
342                 uriList.Free;
343         end;
344
345 end;
346
347 // *************************************************************************
348 // \83f\83X\83g\83\89\83N\83^
349 // *************************************************************************
350 destructor TMachiBBSThreadItem.Destroy;
351 begin
352
353         FreeDat;
354
355         // \88ê\8e\9e\83t\83@\83C\83\8b\82Ì\8fê\8d\87\82Í\8dí\8f\9c\82·\82é
356         if FIsTemporary then
357                 DeleteFile( FilePath );
358
359         inherited;
360
361 end;
362
363 // *************************************************************************
364 // \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½
365 // *************************************************************************
366 function TMachiBBSThreadItem.Download : TDownloadState;
367 var
368         modified                        : Double;
369         tmp                                             : PChar;
370         downResult              : TStringList;
371         content                         : TStringList;
372         responseCode    : Longint;
373         logStream                       : TFileStream;
374         uri                                             : TIdURI;
375         uriList                         : TStringList;
376         datURL                          : string;
377         foundPos                        : Integer;
378         procedure       downAndParse;
379         begin
380                 responseCode := InternalDownload( PChar( datURL ), modified, tmp, 0 );
381
382                 try
383                         if responseCode = 200 then begin
384                                 downResult      := TStringList.Create;
385                                 try
386                                         downResult.Text := string( tmp );
387
388                                         // \83^\83C\83g\83\8b\82Ì\8eæ\93¾
389                                         foundPos                                := AnsiPos( '<title>', downResult.Text ) + Length( '<title>' );
390                                         Title                                           := Copy(
391                                                 downResult.Text,
392                                                 foundPos,
393                                                 AnsiPos( '</title>', downResult.Text ) - foundPos );
394
395                                         // \83\8c\83X\82Ì\8aJ\8en\88Ê\92u
396                                         foundPos                                := AnsiPos( '<dt', downResult.Text );
397                                         downResult.Text := Copy( downResult.Text, foundPos, Length( downResult.Text ) );
398                                         if foundPos > 0 then begin
399                                                 // \83\8c\83X\82Ì\8fI\97¹\88Ê\92u
400                                                 foundPos := AnsiPos( '<table', downResult.Text ) - 1;
401                                                 if foundPos > 0 then
402                                                         downResult.Text := Copy( downResult.Text, 1, foundPos );
403
404                                                 // \82Ü\82¿BBS\82Í dat \92¼\93Ç\82Ý\82ª\8fo\97\88\82È\82¢\82µ\81Acgi \88È\8aO\82É\8d·\95ª\93Ç\82Ý\8d\9e\82Ý\82Ì\95û\96@\82ª\82 \82é\82í\82¯\82Å\82à\96³\82¢\82Ì\82Å
405                                                 // \91f\82Ì\82Ü\82Ü\82ð\96³\97\9d\82É\95Û\82Æ\82¤\82Æ\82Í\82¹\82¸\82É 2ch \82Ì dat \8c`\8e®\82É\95Ï\8a·\82µ\82½\82à\82Ì\82ð\95Û\91\82µ\82Ä\82µ\82Ü\82¤
406                                                 To2chDat( downResult, Count + 1 );
407                                                 content.Text := content.Text + downResult.Text;
408                                         end;
409                                 finally
410                                         downResult.Free;
411                                 end;
412                         end else begin
413                                 Result := dsNotModify;
414                                 Exit;
415                         end;
416                 finally
417                         DisposeResultString( tmp );
418                 end;
419         end;
420 begin
421
422         Result := dsError;
423
424         uri                     := TIdURI.Create( URL );
425         uriList := TStringList.Create;
426         content := TStringList.Create;
427         try
428                 ExtractHttpFields(
429                         ['&'], [],
430                         Copy( uri.Params, AnsiPos( '?', uri.Params ) + 1, Length( uri.Params ) ), uriList );
431                 FileName := uriList.Values[ 'KEY' ] + '.dat';
432                 if MyLogFolder = '' then begin
433                         // \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
434                         FilePath                        := TemporaryFile;
435                         FIsTemporary    := True;
436                 end else begin
437                         FilePath        := MyLogFolder + uriList.Values[ 'BBS' ] + '\' + uriList.Values[ 'KEY' ] + '.dat';
438                         FIsTemporary    := False;
439                 end;
440
441                 // \95Û\91\97p\82Ì\83f\83B\83\8c\83N\83g\83\8a\82ð\8c@\82é
442                 ForceDirectoriesEx( Copy( FilePath, 1, LastDelimiter( '\', FilePath ) ) );
443
444                 // \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Í
445                 // InternalDownload \82É\94C\82¹\82é\82±\82Æ\82ª\8fo\97\88\82é
446                 modified        := LastModified;
447                 if Count = 0 then
448                         // 1\81`
449                         datURL          :=
450                                 uri.Protocol + '://' + uri.Host + '/bbs/read.pl?' +
451                                 'BBS=' + uriList.Values[ 'BBS' ] + '&KEY=' + uriList.Values[ 'KEY' ] +
452                                 '&START=' + IntToStr( 1 )
453                 else
454                         // \90V\92\85\82Ì\82Ý
455                         datURL          :=
456                                 uri.Protocol + '://' + uri.Host + '/bbs/read.pl?' +
457                                 'BBS=' + uriList.Values[ 'BBS' ] + '&KEY=' + uriList.Values[ 'KEY' ] +
458                                 '&START=' + IntToStr( Count + 1 ) + '&NOFIRST=TRUE';
459                 // \83_\83E\83\93\83\8d\81[\83h
460                 downAndParse;
461
462                 if content.Count > 0 then begin
463                         if Count <= 0 then begin
464                                 Result := dsComplete;
465                                 // \90V\8bK\8f\91\82«\8d\9e\82Ý
466                                 content[ 0 ]    := content[ 0 ] + Title;
467                                 logStream                       := TFileStream.Create( FilePath, fmCreate or fmShareDenyWrite );
468                                 try
469                                         logStream.Position      := logStream.Size;
470                                         logStream.Write( PChar( content.Text )^, Length( content.Text ) );
471                                 finally
472                                         logStream.Free;
473                                 end;
474                                 NewReceive      := 1;
475                                 Count                           := content.Count;
476                         end else begin
477                                 Result := dsDiffComplete;
478                                 // \92Ç\8bL
479                                 logStream := TFileStream.Create( FilePath, fmOpenReadWrite or fmShareDenyWrite );
480                                 try
481                                         logStream.Position      := logStream.Size;
482                                         logStream.Write( PChar( content.Text )^, Length( content.Text ) );
483                                 finally
484                                         logStream.Free;
485                                 end;
486                                 NewReceive      := Count + 1;
487                                 Count                           := Count + content.Count;
488                         end;
489
490                         // CGI \82©\82ç\82Í\90³\82µ\82¢\93ú\95t\82ª\93¾\82ç\82ê\82È\82¢\82Ì\82Å\8c»\8dÝ\82É\90Ý\92è
491                         LastModified    := Now;
492                         NewResCount             := content.Count;
493                 end else begin
494                         Result := dsNotModify;
495                 end;
496         finally
497                 uri.Free;
498                 uriList.Free;
499                 content.Free;
500         end;
501
502 end;
503
504 // *************************************************************************
505 // \8f\91\82«\8d\9e\82Ý\82ð\8ew\8e¦\82³\82ê\82½
506 // *************************************************************************
507 function        TMachiBBSThreadItem.Write(
508         inName                          : string;       // \96¼\91O(\83n\83\93\83h\83\8b)
509         inMail                          : string;       // \83\81\81[\83\8b\83A\83h\83\8c\83X
510         inMessage                       : string        // \96{\95
511 ) : TDownloadState;                             // \8f\91\82«\8d\9e\82Ý\82ª\90¬\8c÷\82µ\82½\82©\82Ç\82¤\82©
512 var
513         postURL                         : string;
514         postData                        : string;
515         postResult              : PChar;
516         uri                                             : TIdURI;
517         uriList                         : TStringList;
518 begin
519
520         uri                     := TIdURI.Create( URL );
521         uriList := TStringList.Create;
522         try
523                 ExtractHttpFields(
524                         ['&'], [],
525                         Copy( uri.Params, AnsiPos( '?', uri.Params ) + 1, Length( uri.Params ) ), uriList );
526
527                 postURL         := uri.Protocol + '://' + uri.Host + '/bbs/write.cgi';
528                 postData        :=
529                         'NAME='                 + HttpEncode( inName ) +
530                         '&MAIL='                + HttpEncode( inMail ) +
531                         '&MESSAGE='     + HttpEncode( inMessage ) +
532                         '&BBS='                 + uriList.Values[ 'BBS' ] +
533                         '&KEY='                 + uriList.Values[ 'KEY' ] +
534                         '&TIME='                + IntToStr( DateTimeToUnix( Now ) ) +
535                         '&submit='      + HttpEncode( '\8f\91\82«\8d\9e\82Þ' );
536
537                 // \93Æ\8e©\82É\92Ê\90M\82µ\82È\82¢\8fê\8d\87\82Í InternalPost \82É\94C\82¹\82é\82±\82Æ\82ª\8fo\97\88\82é
538                 InternalPost( PChar( postURL ), PChar( postData ), postResult );
539                 DisposeResultString( postResult );
540
541                 Result := dsComplete
542         finally
543                 uri.Free;
544                 uriList.Free;
545         end;
546
547 end;
548
549 // *************************************************************************
550 // \83\8c\83X\94Ô\8d\86 inNo \82É\91Î\82·\82é html \82ð\97v\8b\81\82³\82ê\82½
551 // *************************************************************************
552 function TMachiBBSThreadItem.GetRes(
553         inNo            : Integer               // \97v\8b\81\82³\82ê\82½\83\8c\83X\94Ô\8d\86
554 ) : string;                                             // \91Î\89\9e\82·\82é HTML
555 var
556         res                     : string;
557         tmp                     : PChar;
558 begin
559
560         // \93Æ\8e©\82É\83t\83B\83\8b\83^\83\8a\83\93\83O\82ð\8ds\82í\82È\82¢\8fê\8d\87\82Í
561         // InternalAbon \82¨\82æ\82Ñ Dat2HTML \82É\94C\82¹\82é\82±\82Æ\82ª\8fo\97\88\82é
562         LoadDat;
563         if FDat = nil then begin
564                 // \83\8d\83O\82É\91\8dÝ\82µ\82È\82¢\82Ì\82Å\82±\82Ì\82Ü\82Ü\8fI\97¹
565                 Result := '';
566                 Exit;
567         end;
568         res                     := FDat[ inNo - 1 ];
569         tmp                     := InternalAbonForOne( PChar( res ), PChar(FilePath), inNo);
570         try
571                 Result  := Dat2HTML( string( tmp ), inNo );
572         finally
573                 DisposeResultString( tmp );
574         end;
575
576 end;
577
578 // *************************************************************************
579 // \83X\83\8c\83b\83h\82Ì\83w\83b\83_ html \82ð\97v\8b\81\82³\82ê\82½
580 // *************************************************************************
581 function TMachiBBSThreadItem.GetHeader(
582         inOptionalHeader        : string
583 ) : string;
584 begin
585
586         // \93Æ\8e©\82É\83t\83B\83\8b\83^\83\8a\83\93\83O\82ð\8ds\82í\82È\82¢\8fê\8d\87\82Í
587         // InternalHeader \82É\94C\82¹\82é\82±\82Æ\82ª\8fo\97\88\82é
588         Result := InternalHeader(
589                 '<meta http-equiv="Content-type" content="text/html; charset=Shift_JIS">' +
590                 inOptionalHeader );
591
592
593         // GetRes \82ð\8cÄ\82Î\82ê\82é\82±\82Æ\82ª\97\\91z\82³\82ê\82é\82Ì\82Å FDat \82ð\90\90¬\82µ\82Ä\82¨\82­
594         try
595                 FreeDat;
596                 LoadDat;
597         except
598         end;
599
600 end;
601
602 // *************************************************************************
603 // \83X\83\8c\83b\83h\82Ì\83t\83b\83^ html \82ð\97v\8b\81\82³\82ê\82½
604 // *************************************************************************
605 function TMachiBBSThreadItem.GetFooter(
606         inOptionalFooter : string
607 ) : string;
608 begin
609
610         // \93Æ\8e©\82É\83t\83B\83\8b\83^\83\8a\83\93\83O\82ð\8ds\82í\82È\82¢\8fê\8d\87\82Í
611         // InternalFooter \82É\94C\82¹\82é\82±\82Æ\82ª\8fo\97\88\82é
612         Result := InternalFooter( inOptionalFooter );
613
614         // \82à\82¤ GetRes \82Í\8cÄ\82Î\82ê\82È\82¢\82Æ\8ev\82¤\82Ì\82Å FDat \82ð\8aJ\95ú\82µ\82Ä\82¨\82­
615         try
616                 FreeDat;
617         except
618         end;
619
620 end;
621
622 // *************************************************************************
623 // \82±\82Ì ThreadItem \82ª\91®\82·\82é\94Â\82Ì URL \82ð\97v\8b\81\82³\82ê\82½
624 // *************************************************************************
625 function        TMachiBBSThreadItem.GetBoardURL : string;
626 var
627         uri                                             : TIdURI;
628         uriList                         : TStringList;
629 begin
630
631         if Copy( URL, Length( URL ), 1 ) = '/' then
632                 uri := TIdURI.Create( URL )
633         else
634                 uri := TIdURI.Create( URL + '/' );
635         uriList := TStringList.Create;
636         try
637                 ExtractHttpFields(
638                         ['&'], [],
639                         Copy( uri.Params, AnsiPos( '?', uri.Params ) + 1, Length( uri.Params ) ), uriList );
640                 FileName := uriList.Values[ 'KEY' ] + '.dat';
641                 // http://hokkaido.machi.to/bbs/read.pl?BBS=hokkaidou&KEY=1061764446
642                 // http://hokkaido.machi.to/hokkaidou/
643                 Result          := CreateResultString(
644                         uri.Protocol + '://' + uri.Host + '/' + uriList.Values[ 'BBS' ] + '/' );
645         finally
646                 uri.Free;
647                 uriList.Free;
648         end;
649
650 end;
651
652 // *************************************************************************
653 // \82Ü\82¿BBS\82Ì HTML \82ð 2ch \82Ì dat \8c`\8e®\82É
654 // *************************************************************************
655 procedure       TMachiBBSThreadItem.To2chDat(
656         ioHTML                          : TStringList;
657         inStartNo                       : Integer = 1
658 );
659 var
660         i, bound                        : Integer;
661         foundPos                        : Integer;
662         strTmp                          : string;
663         res                                             : TStringList;
664         no                                              : Integer;
665 const
666         MAIL_TAG                        = '<a href="mailto:';
667 begin
668
669         //===== 2ch \82Ì dat \8c`\8e®\82É\95Ï\8a·
670         // \83z\83X\83g\96¼\82Ì\8cã\82Å\89ü\8ds\82³\82ê\82Ä\82¢\82½\82è\82·\82é\82Ì\82Å\89ü\8ds\82ð\82·\82×\82Ä\8eæ\82è\8f\9c\82­
671         ioHTML.Text     := CustomStringReplace( ioHTML.Text, #13#10, '');
672         //StringReplace( ioHTML.Text, #13#10, '', [rfReplaceAll] );
673         // \91ã\82í\82è\82É <dt> \82ð\8ds\82Ì\8bæ\90Ø\82è\82É\82·\82é
674         ioHTML.Text     := CustomStringReplace( ioHTML.Text, '<dt>', #10 );
675         //StringReplace( ioHTML.Text, '<dt>', #10, [rfReplaceAll] );
676         // <dt> \82©\82ç\8en\82Ü\82Á\82Ä\82¢\82é\82Ì\82Å\8dÅ\8f\89\82Í\8bó\82Ì\82Í\82¸
677         if Length( ioHTML[ 0 ] ) = 0 then
678                 ioHTML.Delete( 0 );
679
680         // \8cy\82­\82 \82Ú\81[\82ñ\83`\83F\83b\83N
681         // \81¦\91å\8eG\94c\82¾\82©\82ç\82¿\82á\82ñ\82Æ\8fo\97\88\82Ä\82È\82¢\82©\82à
682         try
683                 i                       := 0;
684                 while i < ioHTML.Count do begin
685                         foundPos := AnsiPos( ' ', ioHTML[ i ] );
686                         if foundPos > 0 then begin
687                                 no := StrToInt( Copy( ioHTML[ i ], 1, foundPos - 1 ) );
688                                 if inStartNo < no then
689                                         ioHTML.Insert( i, '<><><><>' );
690                         end;
691                         Inc( i );
692                         Inc( inStartNo );
693                 end;
694         except
695                 // \82 \82Ú\81[\82ñ\83`\83F\83b\83N\82Å\96â\91è\82ª\94­\90\82µ\82Ä\82à\90æ\82Ö\90i\82ß\82½\82¢\82Ì\82Å
696         end;
697
698         // \83g\83\8a\83b\83v\82Ì\8cã\82Ì '<b> </b>' \82ð\8bó\82É
699         ioHTML.Text     := CustomStringReplace( ioHTML.Text, '<b> </b>', '', true );
700         //StringReplace( ioHTML.Text, '<b> </b>', '', [rfReplaceAll, rfIgnoreCase] );
701         // '<b>' \82Í\83\81\81[\83\8b\82Æ\96¼\91O\82Ì\8bæ\90Ø\82è
702         ioHTML.Text     := CustomStringReplace( ioHTML.Text, '<b>', '<>', true );
703         //StringReplace( ioHTML.Text, '<b>', '<>', [rfReplaceAll, rfIgnoreCase] );
704         // \83\81\81[\83\8b\82Æ\96¼\91O\82É\82Â\82¢\82Ä\82­\82é\95Â\82\83^\83O\82ð\93\8a\8de\93ú\82Æ\82Ì\8bæ\90Ø\82è\82É
705         ioHTML.Text     := CustomStringReplace( ioHTML.Text, '</b></a>', '<>', true );
706         //StringReplace( ioHTML.Text, '</b></a>', '<>', [rfReplaceAll, rfIgnoreCase] );
707         ioHTML.Text     := CustomStringReplace( ioHTML.Text, '</b>', '<>', true );
708         //StringReplace( ioHTML.Text, '</b>', '<>', [rfReplaceAll, rfIgnoreCase] );
709         // '<dd>' \82ð\96{\95\82Æ\82Ì\8bæ\90Ø\82è\82É
710         ioHTML.Text     := CustomStringReplace( ioHTML.Text, '<dd>', '<>', true );
711         //StringReplace( ioHTML.Text, '<dd>', '<>', [rfReplaceAll, rfIgnoreCase] );
712
713         res := TStringList.Create;
714         try
715                 bound := ioHTML.Count - 1;
716                 for i := 0 to bound do begin
717                         res.Text := CustomStringReplace( ioHTML[ i ], '<>', #10 );
718                                                 //StringReplace( ioHTML[ i ], '<>', #10, [rfReplaceAll] );
719                         if res.Count >= 3 then begin    // 3 \96¢\96\9e\82Í\82 \82è\82¦\82È\82¢\82Æ\8ev\82¤\82¯\82Ç\88À\91S\82Ì\82½\82ß
720                                 foundPos := AnsiPos( MAIL_TAG, res[ 0 ] );
721                                 if foundPos > 0 then begin
722                                         // \83\81\81[\83\8b\83A\83h\83\8c\83X\82ð\94²\82«\8fo\82·
723                                         foundPos        := foundPos + Length( MAIL_TAG );
724                                         res[ 0 ]        := Copy( res[ 0 ], foundPos, Length( res[ 0 ] ) );
725                                         strTmp          := Copy( res[ 0 ], 1, AnsiPos( '">', res[ 0 ] ) - 1 );
726                                         // \83\81\81[\83\8b\82Æ\96¼\91O\82ª\8bt\82È\82Ì\82Å\82Ð\82Á\82­\82è\95Ô\82µ\82Ä\96ß\82·
727                                         res[ 0 ]        := res[ 1 ];
728                                         res[ 1 ]        := strTmp;
729                                 end else begin
730                                         // \83\81\81[\83\8b\82Æ\96¼\91O\82ª\8bt\82È\82Ì\82Å\82Ð\82Á\82­\82è\95Ô\82·
731                                         res[ 0 ]        := res[ 1 ];
732                                         res[ 1 ]        := '';
733                                 end;
734                                 res[ 2 ] := StringReplace( res[ 2 ], '[', 'IP:', [] );
735                                 res[ 2 ] := StringReplace( res[ 2 ], ']', '', [] );
736                         end;
737                         ioHTML[ i ] := CustomStringReplace( res.Text, #13#10, '<>');
738                         //StringReplace( res.Text, #13#10, '<>', [rfReplaceAll] );
739                 end;
740         finally
741                 res.Free;
742         end;
743
744 end;
745
746 // *************************************************************************
747 // FDat \82Ì\90\90¬
748 // *************************************************************************
749 procedure       TMachiBBSThreadItem.LoadDat;
750 begin
751
752         if FDat = nil then begin
753                 if IsLogFile then begin
754                         // dat \82Ì\93Ç\82Ý\8d\9e\82Ý
755                         FDat := TStringList.Create;
756                         FDat.LoadFromFile( FilePath );
757                 end;
758         end;
759
760 end;
761
762 // *************************************************************************
763 // FDat \82Ì\8aJ\95ú
764 // *************************************************************************
765 procedure       TMachiBBSThreadItem.FreeDat;
766 begin
767
768         if FDat <> nil then begin
769                 FDat.Free;
770                 FDat := nil;
771         end;
772
773 end;
774
775 // *************************************************************************
776 // \88À\91S\82È( '/' \82Å\8fI\82í\82é )\93Ç\82Ý\8d\9e\82Ý\82Ì URL
777 // *************************************************************************
778 function        TMachiBBSThreadItem.ReadURL : string;
779 var
780         uri                             : TIdURI;
781         uriList         : TStringList;
782         foundPos        : Integer;
783 begin
784
785         foundPos := AnsiPos( '?', URL );
786         if foundPos > 0 then begin
787                 uri := TIdURI.Create( URL );
788                 uriList := TStringList.Create;
789                 try
790                         ExtractHttpFields( ['&'], [], Copy( URL, foundPos + 1, MaxInt ), uriList );
791                         Result :=
792                                 uri.Protocol + '://' + uri.Host + '/bbs/read.pl?' +
793                                 'BBS=' + uriList.Values[ 'BBS' ] + '&KEY=' + uriList.Values[ 'KEY' ];
794                 finally
795                         uri.Free;
796                         uriList.Free;
797                 end;
798         end;
799
800 end;
801
802 // *************************************************************************
803 // TThreadItem \82ª\90\90¬\82³\82ê\82½\8fê\8d\87\82Ì\8f\88\92u(TMachiBBSThreadItem \82ð\90\90¬\82·\82é)
804 // *************************************************************************
805 procedure ThreadItemOnCreateOfTMachiBBSThreadItem(
806         inInstance : DWORD
807 );
808 var
809         threadItem : TMachiBBSThreadItem;
810 begin
811
812         threadItem := TMachiBBSThreadItem.Create( inInstance );
813         ThreadItemSetLong( inInstance, tipContext, DWORD( threadItem ) );
814
815 end;
816
817 // *************************************************************************
818 // TThreadItem \82ª\94j\8aü\82³\82ê\82½\8fê\8d\87\82Ì\8f\88\92u(TMachiBBSThreadItem \82ð\94j\8aü\82·\82é)
819 // *************************************************************************
820 procedure ThreadItemOnDisposeOfTMachiBBSThreadItem(
821         inInstance : DWORD
822 );
823 var
824         threadItem : TMachiBBSThreadItem;
825 begin
826
827         threadItem := TMachiBBSThreadItem( ThreadItemGetLong( inInstance, tipContext ) );
828         threadItem.Free;
829
830 end;
831
832 // =========================================================================
833 // TMachiBBSBoardItem
834 // =========================================================================
835
836 // *************************************************************************
837 // \83R\83\93\83X\83g\83\89\83N\83^
838 // *************************************************************************
839 constructor TMachiBBSBoardItem.Create(
840         inInstance      : DWORD
841 );
842 var
843         uri                                     : TIdURI;
844         uriList                 : TStringList;
845 begin
846
847         inherited;
848
849         OnDownload                                              := Download;
850         OnCreateThread                          := CreateThread;
851         OnEnumThread                                    := EnumThread;
852         OnFileName2ThreadURL    := ToThreadURL;
853
854         FilePath                        := '';
855         FIsTemporary    := False;
856         FDat                                    := nil;
857
858         uri                     := TIdURI.Create( SubjectURL );
859         uriList := TStringList.Create;
860         try
861                 ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
862                 // http://hokkaido.machi.to/hokkaidou/subject.txt
863                 FilePath        := MyLogFolder + uriList[ 1 ] + '\' + uri.Document;
864                 IsLogFile       := FileExists( FilePath );
865         finally
866                 uri.Free;
867                 uriList.Free;
868         end;
869
870 end;
871  
872 // *************************************************************************
873 // \83f\83X\83g\83\89\83N\83^
874 // *************************************************************************
875 destructor TMachiBBSBoardItem.Destroy;
876 begin
877
878         if FDat <> nil then begin
879                 try
880                         FDat.Free;
881                         FDat := nil;
882                 except
883                 end;
884         end;
885
886         // \88ê\8e\9e\83t\83@\83C\83\8b\82Ì\8fê\8d\87\82Í\8dí\8f\9c\82·\82é
887         if FIsTemporary then
888                 DeleteFile( FilePath );
889
890         inherited;
891
892 end;
893
894 // *************************************************************************
895 // \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½
896 // *************************************************************************
897 function TMachiBBSBoardItem.Download : TDownloadState;
898 var
899         modified                        : Double;
900         downResult              : PChar;
901         responseCode    : Longint;
902         uri                                             : TIdURI;
903         uriList                         : TStringList;
904 begin
905
906         Result := dsError;
907
908         if FDat <> nil then begin
909                 try
910                         FDat.Free;
911                         FDat := nil;
912                 except
913                 end;
914         end;
915         FDat            := TStringList.Create;
916         uri                     := TIdURI.Create( SubjectURL );
917         uriList := TStringList.Create;
918         // \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Í
919         // InternalDownload \82É\94C\82¹\82é\82±\82Æ\82ª\8fo\97\88\82é
920         modified                        := LastModified;
921         responseCode    := InternalDownload( PChar( uri.URI ), modified, downResult );
922         try
923                 if responseCode = 200 then begin
924                         try
925                                 // \83p\83X\82ð\8eZ\8fo
926                                 ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
927                                 if MyLogFolder = '' then begin
928                                         // \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
929                                         FilePath                        := TemporaryFile;
930                                         FIsTemporary    := True;
931                                 end else begin
932                                         FilePath                        := MyLogFolder + uriList[ 1 ] + '\' + uri.Document;
933                                         FIsTemporary    := False
934                                 end;
935
936                                 // \95Û\91\97p\82Ì\83f\83B\83\8c\83N\83g\83\8a\82ð\8c@\82é
937                                 ForceDirectoriesEx( Copy( FilePath, 1, LastDelimiter( '\', FilePath ) ) );
938
939                                 FDat.Text := string( downResult );
940                                 // \95Û\91
941                                 FDat.SaveToFile( FilePath );
942
943                                 IsLogFile                       := True;
944                                 RoundDate                       := Now;
945                                 LastModified    := modified;
946                                 LastGetTime             := Now;
947                         finally
948                                 uri.Free;
949                                 uriList.Free;
950                         end;
951                         Result := dsComplete;
952                 end;
953         finally
954                 DisposeResultString( downResult );
955         end;
956
957 end;
958
959 // *************************************************************************
960 // \83X\83\8c\97§\82Ä\82ð\8ew\8e¦\82³\82ê\82½
961 // *************************************************************************
962 function        TMachiBBSBoardItem.CreateThread(
963         inSubject                       : string;       // \83X\83\8c\83^\83C
964         inName                          : string;       // \96¼\91O(\83n\83\93\83h\83\8b)
965         inMail                          : string;       // \83\81\81[\83\8b\83A\83h\83\8c\83X
966         inMessage                       : string        // \96{\95
967 ) : TDownloadState;                             // \8f\91\82«\8d\9e\82Ý\82ª\90¬\8c÷\82µ\82½\82©\82Ç\82¤\82©
968 var
969         postURL                         : string;
970         postData                        : string;
971         postResult              : PChar;
972         uri                                             : TIdURI;
973         uriList                         : TStringList;
974 begin
975
976         uri                     := TIdURI.Create( URL );
977         uriList := TStringList.Create;
978         try
979                 ExtractHttpFields(
980                         ['&'], [],
981                         Copy( uri.Params, AnsiPos( '?', uri.Params ) + 1, Length( uri.Params ) ), uriList );
982
983                 postURL         := uri.Protocol + '://' + uri.Host + '/bbs/write.cgi';
984                 postData        :=
985                         'SUBJECT='      + HttpEncode( inSubject ) +
986                         '&NAME='                + HttpEncode( inName ) +
987                         '&MAIL='                + HttpEncode( inMail ) +
988                         '&MESSAGE='     + HttpEncode( inMessage ) +
989                         '&BBS='                 + uriList[ 1 ] +
990                         '&TIME='                + IntToStr( DateTimeToUnix( Now ) ) +
991                         '&submit='      + HttpEncode( '\90V\8bK\8f\91\82«\8d\9e\82Ý' );
992
993                 // \93Æ\8e©\82É\92Ê\90M\82µ\82È\82¢\8fê\8d\87\82Í InternalPost \82É\94C\82¹\82é\82±\82Æ\82ª\8fo\97\88\82é
994                 InternalPost( PChar( postURL ), PChar( postData ), postResult );
995                 DisposeResultString( postResult );
996
997                 Result := dsComplete
998         finally
999                 uri.Free;
1000                 uriList.Free;
1001         end;
1002
1003 end;
1004
1005 // *************************************************************************
1006 // \83X\83\8c\88ê\97\97\82Ì URL \82©\82ç\83X\83\8c\83b\83h\82Ì URL \82ð\93±\82«\8fo\82·
1007 // *************************************************************************
1008 function TMachiBBSBoardItem.ToThreadURL(
1009         inFileName      : string        // \83X\83\8c\83b\83h\83t\83@\83C\83\8b\96¼
1010 ) : string;                                                     // \83X\83\8c\83b\83h\82Ì URL
1011 var
1012         threadURL               : string;
1013         uri                                     : TIdURI;
1014         uriList                 : TStringList;
1015         found                           : Integer;
1016 begin
1017
1018         found := AnsiPos( '.', inFileName );
1019         if found > 0 then
1020                 inFileName := Copy( inFileName, 1, found - 1 );
1021
1022         uri                     := TIdURI.Create( SubjectURL );
1023         uriList := TStringList.Create;
1024         try
1025                 try
1026                         // http://hokkaido.machi.to/hokkaidou/
1027                         // http://hokkaido.machi.to/bbs/read.pl?BBS=hokkaidou&KEY=1061764446&LAST=50
1028                         ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
1029                         threadURL       := uri.Protocol + '://' + uri.Host + '/bbs/read.pl?' +
1030                                 'BBS=' + uriList[ 1 ] + '&KEY=' + inFileName + '&LAST=50';
1031                         Result          := threadURL;
1032                 finally
1033                         uri.Free;
1034                         uriList.Free;
1035                 end;
1036         except
1037                 Result := '';
1038         end;
1039
1040 end;
1041
1042 // *************************************************************************
1043 // \82±\82Ì\94Â\82É\82¢\82­\82Â\82Ì\83X\83\8c\82ª\82 \82é\82©\97v\8b\81\82³\82ê\82½
1044 // *************************************************************************
1045 procedure       TMachiBBSBoardItem.EnumThread(
1046         inCallBack      : TBoardItemEnumThreadCallBack
1047 );
1048 var
1049         uri                                     : TIdURI;
1050         uriList                 : TStringList;
1051 begin
1052
1053         try
1054                 if FDat = nil then begin
1055                         FDat := TStringList.Create;
1056
1057                         uri                     := TIdURI.Create( SubjectURL );
1058                         uriList := TStringList.Create;
1059                         try
1060                                 // \83p\83X\82ð\8eZ\8fo
1061                                 ExtractHttpFields( ['/', '?'], [], uri.Path, uriList );
1062                                 // http://hokkaido.machi.to/hokkaidou/subject.txt
1063                                 FilePath        := MyLogFolder + uriList[ 1 ] + '\' + uri.Document;
1064                                 if FileExists( FilePath ) then
1065                                         // \93Ç\82Ý\8d\9e\82Ý
1066                                         FDat.LoadFromFile( FilePath );
1067                         finally
1068                                 uri.Free;
1069                                 uriList.Free;
1070                         end;
1071                 end;
1072
1073                 // \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é
1074                 inherited EnumThread( inCallBack, CustomStringReplace( FDat.Text, ',', '<>' ) );
1075         except
1076         end;
1077
1078 end;
1079
1080 // *************************************************************************
1081 // \83X\83\8c\88ê\97\97\82Ì URL \82ð\8b\81\82ß\82é
1082 // *************************************************************************
1083 function        TMachiBBSBoardItem.SubjectURL : string;
1084 var
1085         uri                     : TIdURI;
1086         uriList : TStringList;
1087 begin
1088
1089         uri                     := TIdURI.Create( URL );
1090         uriList := TStringList.Create;
1091         try
1092                 if uri.Document <> SUBJECT_NAME then begin
1093                         if Copy( URL, Length( URL ), 1 ) = '/' then
1094                                 Result := URL + SUBJECT_NAME
1095                         else
1096                                 Result := URL + '/' + SUBJECT_NAME;
1097                 end else begin
1098                         // \82±\82±\82É\82Í\97\88\82È\82¢\82Æ\8ev\82¤\82¯\82Ç
1099                         Result := URL;
1100                 end;
1101         finally
1102                 uri.Free;
1103                 uriList.Free;
1104         end;
1105
1106 end;
1107
1108 // *************************************************************************
1109 // TBoardItem \82ª\90\90¬\82³\82ê\82½\8fê\8d\87\82Ì\8f\88\92u(TMachiBBSBoardItem \82ð\90\90¬\82·\82é)
1110 // *************************************************************************
1111 procedure BoardItemOnCreateOfTMachiBBSBoardItem(
1112         inInstance : DWORD
1113 );
1114 var
1115         boardItem : TMachiBBSBoardItem;
1116 begin
1117
1118         boardItem := TMachiBBSBoardItem.Create( inInstance );
1119         BoardItemSetLong( inInstance, bipContext, DWORD( boardItem ) );
1120
1121 end;
1122
1123 // *************************************************************************
1124 // TBoardItem \82ª\94j\8aü\82³\82ê\82½\8fê\8d\87\82Ì\8f\88\92u(TMachiBBSBoardItem \82ð\94j\8aü\82·\82é)
1125 // *************************************************************************
1126 procedure BoardItemOnDisposeOfTMachiBBSBoardItem(
1127         inInstance : DWORD
1128 );
1129 var
1130         boardItem : TMachiBBSBoardItem;
1131 begin
1132
1133         boardItem := TMachiBBSBoardItem( BoardItemGetLong( inInstance, bipContext ) );
1134         boardItem.Free;
1135
1136 end;
1137
1138
1139
1140 // =========================================================================
1141 // \83G\83\93\83g\83\8a\83|\83C\83\93\83g
1142 // =========================================================================
1143 procedure DLLEntry(
1144         ul_reason_for_call : DWORD
1145 );
1146 var
1147         module : HMODULE;
1148 begin
1149
1150         case ul_reason_for_call of
1151                 DLL_PROCESS_ATTACH:
1152                 begin
1153                         Randomize;
1154
1155                         module := GetModuleHandle( nil );
1156
1157                         LoadInternalAPI( module );
1158                         LoadInternalFilePathAPI( module );
1159                         LoadInternalThreadItemAPI( module );
1160                         LoadInternalBoardItemAPI( module );
1161
1162                         // ===== \83C\83\93\83X\83^\83\93\83X\82Ì\8eæ\82è\88µ\82¢\82ð TThreadItem \82©\82ç TMachiBBSThreadItem \82É\95Ï\8dX\82·\82é
1163                         ThreadItemOnCreate      := ThreadItemOnCreateOfTMachiBBSThreadItem;
1164                         ThreadItemOnDispose     := ThreadItemOnDisposeOfTMachiBBSThreadItem;
1165                         // ===== \83C\83\93\83X\83^\83\93\83X\82Ì\8eæ\82è\88µ\82¢\82ð TBoardItem \82©\82ç TMachiBBSBoardItem \82É\95Ï\8dX\82·\82é
1166                         BoardItemOnCreate               := BoardItemOnCreateOfTMachiBBSBoardItem;
1167                         BoardItemOnDispose      := BoardItemOnDisposeOfTMachiBBSBoardItem;
1168                 end;
1169                 DLL_PROCESS_DETACH:
1170                         ;
1171                 DLL_THREAD_ATTACH:
1172                         ;
1173                 DLL_THREAD_DETACH:
1174                         ;
1175         end;
1176
1177 end;
1178
1179 exports
1180         OnVersionInfo,
1181         OnAcceptURL;
1182
1183 begin
1184
1185         try
1186                 DllProc := @DLLEntry;
1187                 DLLEntry( DLL_PROCESS_ATTACH );
1188         except end;
1189
1190 end.