OSDN Git Service

5cbcdbef3b56827447fee23f57732d2e45a0b836
[gikonavigoeson/gikonavi.git] / GikoSystem.pas
1 unit GikoSystem;
2
3 interface
4
5 uses
6         Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
7         ComCtrls, {IniFiles,} ShellAPI, ActnList, Math,
8 {$IF Defined(DELPRO) }
9         SHDocVw,
10         MSHTML,
11 {$ELSE}
12         SHDocVw_TLB,
13         MSHTML_TLB,
14 {$IFEND}
15         {HttpApp,} URLMon, IdGlobal, IdURI, {Masks,}
16         Setting, BoardGroup, gzip, Dolib, bmRegExp, AbonUnit,
17         ExternalBoardManager, ExternalBoardPlugInMain,
18         GikoBayesian, GikoMessage, Belib;
19
20 type
21         TVerResourceKey = (
22                         vrComments,         //!< \83R\83\81\83\93\83g
23                         vrCompanyName,      //!< \89ï\8eÐ\96¼
24                         vrFileDescription,  //!< \90à\96¾
25                         vrFileVersion,      //!< \83t\83@\83C\83\8b\83o\81[\83W\83\87\83\93
26                         vrInternalName,     //!< \93à\95\94\96¼
27                         vrLegalCopyright,   //!< \92\98\8dì\8c 
28                         vrLegalTrademarks,  //!< \8f¤\95W
29                         vrOriginalFilename, //!< \90³\8e®\83t\83@\83C\83\8b\96¼
30                         vrPrivateBuild,     //!< \83v\83\89\83C\83x\81[\83g\83r\83\8b\83h\8fî\95ñ
31                         vrProductName,      //!< \90»\95i\96¼
32                         vrProductVersion,   //!< \90»\95i\83o\81[\83W\83\87\83\93
33                         vrSpecialBuild);    //!< \83X\83y\83V\83\83\83\8b\83r\83\8b\83h\8fî\95ñ
34
35         //! BBS\83^\83C\83v
36         TGikoBBSType = (gbt2ch);
37         //! \83\8d\83O\83^\83C\83v
38         TGikoLogType = (glt2chNew, glt2chOld);
39         //! \83\81\83b\83Z\81[\83W\83A\83C\83R\83\93
40         TGikoMessageIcon = (gmiOK, gmiSAD, gmiNG, gmiWhat, gmiNone);
41         //! URL\83I\81[\83v\83\93\83u\83\89\83E\83U\83^\83C\83v
42         TGikoBrowserType = (gbtIE, gbtUserApp, gbtAuto);
43
44
45         TStrTokSeparator = set of Char;
46         TStrTokRec = record
47                 Str: string;
48                 Pos: Integer;
49         end;
50
51         //! \83C\83\93\83f\83b\83N\83X\83t\83@\83C\83\8b\83\8c\83R\81[\83h
52         TIndexRec = record
53                 FNo: Integer;
54                 FFileName: string;
55                 FTitle: string;
56                 FCount: Integer;
57                 FSize: Integer;
58 //              FRoundNo: Integer;
59                 FRoundDate: TDateTime;
60                 FLastModified: TDateTime;
61                 FKokomade: Integer;
62                 FNewReceive: Integer;
63                 FMishiyou: Boolean;     //!< \96¢\8eg\97p
64                 FUnRead: Boolean;
65                 FScrollTop: Integer;
66                 //Index Ver 1.01
67                 FAllResCount: Integer;
68                 FNewResCount: Integer;
69                 FAgeSage: TGikoAgeSage;
70         end;
71
72         //! \83T\83u\83W\83F\83N\83g\83\8c\83R\81[\83h
73         TSubjectRec = record
74                 FFileName: string;
75                 FTitle: string;
76                 FCount: Integer;
77         end;
78
79         //! \83\8c\83X\83\8c\83R\81[\83h\82Ö\82Ì\83|\83C\83\93\83^
80         PResRec = ^TResRec;
81
82         //! \83\8c\83X\83\8c\83R\81[\83h
83         TResRec = record
84                 FTitle: string;
85                 FMailTo: string;
86                 FName: string;
87                 FDateTime: string;
88                 FBody: string;
89                 FType: TGikoLogType;
90         end;
91
92         //! URLPath\83\8c\83R\81[\83h
93         TPathRec = record
94                 FBBS: string;                           //!< BBSID
95                 FKey: string;                           //!< ThreadID
96                 FSt: Int64;                               //!< \8aJ\8en\83\8c\83X\94Ô
97                 FTo: Int64;                               //!< \8fI\97¹\83\8c\83X\94Ô
98                 FFirst: Boolean;                //!< >>1\82Ì\95\\8e¦
99                 FStBegin: Boolean;      //!< 1\81`\95\\8e¦
100                 FToEnd: Boolean;                //!< \81`\8dÅ\8cã\82Ü\82Å\95\\8e¦
101                 FDone: Boolean;                 //!< \90¬\8c÷
102                 FNoParam: Boolean;  //!< \83\8c\83X\94Ô\83p\83\89\83\81\81[\83^\82È\82µ
103         end;
104
105         TGikoSys = class(TObject)
106         private
107                 { Private \90é\8c¾ }
108                 FSetting: TSetting;
109                 FDolib: TDolib;
110                 FAWKStr: TAWKStr;
111                 FResRange : Longint;
112                 FBayesian       : TGikoBayesian;        //!< \83x\83C\83W\83A\83\93\83t\83B\83\8b\83^
113                 FVersion : String;                    //!< \83t\83@\83C\83\8b\83o\81[\83W\83\87\83\93
114                 FGikoMessage: TGikoMessage;
115         FBelib: TBelib;
116                 //! \82 \82é\83Z\83p\83\8c\81[\83^\82Å\8bæ\90Ø\82ç\82ê\82½\95\8e\9a\97ñ\82©\82ç\82\8e\94Ô\96Ú\82Ì\95\8e\9a\97ñ\82ð\8eæ\82è\8fo\82·
117                 function ChooseString(const Text, Separator: string; Index: integer): string;
118         //! \88ê\8e\9e\83t\83@\83C\83\8b\82©\82ç\82Ì\95\9c\8b\8c
119         procedure RestoreThreadData(Board: TBoard);
120         public
121                 { Public \90é\8c¾ }
122                 FAbon : TAbon;
123                 FSelectResFilter : TAbon;
124                 //FBoardURLList: TStringList;
125                 constructor Create;
126
127                 destructor Destroy; override;
128                 property ResRange : Longint read FResRange write FResRange;
129                 //! \83o\81[\83W\83\87\83\93\8fî\95ñ
130                 property Version : String read FVersion;
131                 function IsNumeric(s: string): boolean;
132                 function IsFloat(s: string): boolean;
133                 function DirectoryExistsEx(const Name: string): Boolean;
134                 function ForceDirectoriesEx(Dir: string): Boolean;
135
136                 function GetBoardFileName: string;
137                 function GetCustomBoardFileName: string;
138                 function GetHtmlTempFileName: string;
139                 function GetAppDir: string;
140                 function GetTempFolder: string;
141                 function GetSentFileName: string;
142                 function GetConfigDir: string;
143         function GetNGWordsDir: string;
144                 function GetSkinDir: string;
145                 function GetSkinHeaderFileName: string;
146                 function GetSkinFooterFileName: string;
147                 function GetSkinResFileName: string;
148                 function GetSkinNewResFileName: string;
149                 function GetSkinBookmarkFileName: string;
150                 function GetSkinNewmarkFileName: string;
151                 function GetStyleSheetDir: string;
152                 function GetOutBoxFileName: string;
153                 function GetUserAgent: string;
154                                 function GetSambaFileName : string;
155
156                 function GetMainKeyFileName : String;
157                 function GetEditorKeyFileName: String;
158                 function GetInputAssistFileName: String;
159                 procedure ReadSubjectFile(Board: TBoard);
160                 procedure CreateThreadDat(Board: TBoard);
161                 procedure WriteThreadDat(Board: TBoard);
162                 function ParseIndexLine(Line: string): TIndexRec;
163                 procedure GetFileList(Path: string; Mask: string; var List: TStringList; SubDir: Boolean; IsPathAdd: Boolean); overload;
164                 procedure GetFileList(Path: string; Mask: string; var List: TStringList; IsPathAdd: Boolean); overload;//\83T\83u\83t\83H\83\8b\83_\82Í\8c\9f\8dõ\82µ\82È\82¢
165                 procedure GetDirectoryList(Path: string; Mask: string; List: TStringList; SubDir: Boolean);
166
167                 function DivideSubject(Line: string): TSubjectRec;
168                 property Setting: TSetting read FSetting write FSetting;
169                 property Dolib: TDolib read FDolib write FDolib;
170                 property Belib: TBelib read FBelib write FBelib;
171
172                 function UrlToID(url: string): string;
173                 function UrlToServer(url: string): string;
174
175                 function StrTokFirst(const s:string; const sep:TStrTokSeparator; var Rec:TStrTokRec):string;
176                 function StrTokNext(const sep:TStrTokSeparator; var Rec:TStrTokRec): string;
177
178                 function GetFileSize(FileName : string) : longint;
179                 function GetFileLineCount(FileName : string): longint;
180                 function IntToDateTime(val: Int64): TDateTime;
181                 function DateTimeToInt(ADate: TDateTime): Int64;
182
183                 function ReadThreadFile(FileName: string; Line: Integer): string;
184
185                 procedure MenuFont(Font: TFont);
186
187 //              function RemoveToken(var s:string; const delimiter:string):string;
188                 function GetTokenIndex(s: string; delimiter: string; index: Integer): string;
189
190                 function GetShortName(const LongName: string; ALength: integer): string;
191                 function BoolToInt(b: Boolean): Integer;
192                 function IntToBool(i: Integer): Boolean;
193                 function GzipDecompress(ResStream: TStream; ContentEncoding: string): string;
194                 procedure LoadKeySetting(ActionList: TActionList; FileName: String);
195                 procedure SaveKeySetting(ActionList: TActionList; FileName: String);
196                 procedure CreateProcess(const AppPath: string; const Param: string);
197                 procedure OpenBrowser(URL: string; BrowserType: TGikoBrowserType);
198                 function HTMLDecode(const AStr: String): String;
199                 function GetHRefText(s: string): string;
200                 function Is2chHost(Host: string): Boolean;
201                 function Parse2chURL(const url: string; const path: string; const document: string; var BBSID: string; var BBSKey: string): Boolean;
202                 function Parse2chURL2(URL: string): TPathRec;
203                 procedure ParseURI(const URL : string; var Protocol, Host, Path, Document, Port, Bookmark: string);
204                 function GetVersionBuild: Integer;
205                 function        GetBrowsableThreadURL( inURL : string ) : string;
206                 function        GetThreadURL2BoardURL( inURL : string ) : string;
207                 function        Get2chThreadURL2BoardURL( inURL : string ) : string;
208                 function        Get2chBrowsableThreadURL( inURL : string ) : string;
209                 function        Get2chBoard2ThreadURL( inBoard : TBoard; inKey : string ) : string;
210                 procedure ListBoardFile;
211                 procedure ReadBoardFile( bbs : TBBS );
212
213                 function        GetUnknownCategory : TCategory;
214                 function        GetUnknownBoard( inPlugIn : TBoardPlugIn; inURL : string ) : TBoard;
215
216                 procedure GetPopupResNumber(URL : string; var stRes, endRes : Int64);
217
218                 property Bayesian : TGikoBayesian read FBayesian write FBayesian;
219         function CreateResAnchor(var Numbers: TStringList; ThreadItem: TThreadItem; limited: Integer):string;
220                 procedure GetSameIDRes(const AID : string; ThreadItem: TThreadItem;var body: TStringList); overload;
221                 procedure GetSameIDRes(AIDNum : Integer; ThreadItem: TThreadItem;var body: TStringList); overload;
222         function GetResID(AIDNum: Integer; ThreadItem: TThreadItem): String;
223         function ExtructResID(ADateStr: String): String;
224                 //! \92P\8cê\89ð\90Í
225                 procedure SpamCountWord( const text : string; wordCount : TWordCount );
226                 //! \8aw\8fK\83N\83\8a\83A
227                 procedure SpamForget( wordCount : TWordCount; isSpam : Boolean );
228                 //! \83X\83p\83\80\8aw\8fK
229                 procedure SpamLearn( wordCount : TWordCount; isSpam : Boolean );
230                 //! \83X\83p\83\80\93x\90\94
231                 function SpamParse( const text : string; wordCount : TWordCount ) : Extended;
232
233                 //! \88ø\90\94\82É\91\97\82ç\82ê\82Ä\82«\82½\93ú\95t/ID\95\94\82ÉBE\82Ì\95\8e\9a\97ñ\82ª\82 \82Á\82½\82ç\81A\83v\83\8d\83t\83@\83C\83\8b\82Ö\82Ì\83\8a\83\93\83N\82ð\92Ç\89Á
234                 function AddBeProfileLink(AID : string; ANum: Integer): string;
235                 //! \83o\81[\83W\83\87\83\93\8fî\95ñ\82Ì\8eæ\93¾
236                 function GetVersionInfo(KeyWord: TVerResourceKey): string;
237                 //! Plugin\82Ì\8fî\95ñ\82Ì\8eæ\93¾
238                 function GetPluginsInfo(): string;
239                 //! IE\82Ì\83o\81[\83W\83\87\83\93\8fî\95ñ\82Ì\8eæ\93¾
240                 function GetIEVersion: string;
241                 function SetUserOptionalStyle(): string;
242                 //! \83M\83R\83i\83r\82Ì\83\81\83b\83Z\81[\83W\82ð\90Ý\92è\82·\82é
243                 procedure SetGikoMessage;
244                 //! \83M\83R\83i\83r\82Ì\83\81\83b\83Z\81[\83W\82ð\8eæ\93¾\82·\82é
245                 function GetGikoMessage(MesType: TGikoMessageListType): String;
246                 //! GMT\82Ì\8e\9e\8d\8f\82ðTDateTime\82É\95Ï\8a·\82·\82é
247                 function  DateStrToDateTime(const DateStr: string): TDateTime;
248         //! User32.dll\82ª\97\98\97p\82Å\82«\82é\82©
249         function CanUser32DLL: Boolean;
250         //! OE\88ø\97p\95\84\8eæ\93¾
251         function GetOEIndentChar : string;
252         //! \92u\8a·\90Ý\92è\83t\83@\83C\83\8b\8eæ\93¾
253         function GetReplaceFileName: String;
254         //! \83C\83\93\83f\83b\83N\83X\82É\82È\82¢dat\81i\82Í\82®\82êdat\81j\82Ì\92Ç\89Á
255         procedure AddOutofIndexDat(Board: TBoard; DatList: TStringList; AllCreate: boolean = True);
256         //! \83t\83@\83C\83\8b\96¼\82©\82ç\82Ì\83X\83\8c\83b\83h\8dì\90¬\93ú\82Ì\8eæ\93¾
257         function GetCreateDateFromName(FileName: String): TDateTime;
258         function GetExtpreviewFileName: String;
259
260         procedure ShowRefCount(msg: String; unk: IUnknown);
261         //! \96`\8c¯\82Ì\8f\91Cookie\8eæ\93¾
262         function GetBoukenCookie(AURL: String): String;
263         //! \96`\8c¯\82Ì\8f\91Cookie\90Ý\92è
264         procedure SetBoukenCookie(ACookieValue, ADomain: String);
265         //! \96`\8c¯\82Ì\8f\91Cookie\8dí\8f\9c
266         procedure DelBoukenCookie(ADomain: String);
267         //! \96`\8c¯\82Ì\8f\91Domain\88ê\97\97\8eæ\93¾
268         procedure GetBoukenDomain(var ADomain: TStringList);
269         //! \96`\8c¯\82Ì\8f\91\83h\83\81\83C\83\93\96¼Cookie\8eæ\93¾
270         function GetBouken(AURL: String; var Domain: String): String;
271         end;
272
273 var
274         GikoSys: TGikoSys;
275 const
276         //LENGTH_RESTITLE                       = 40;
277         ZERO_DATE: Integer      = 25569;
278         BETA_VERSION_NAME_E = 'beta';
279         BETA_VERSION_NAME_J = 'ÊÞÀ';
280         BETA_VERSION                            = 68;
281         BETA_VERSION_BUILD      = '';                           //!< debug\94Å\82È\82Ç
282         APP_NAME                                                = 'gikoNavi';
283         BE_PHP_URL = 'http://be.2ch.net/test/p.php?i=';
284
285
286 implementation
287
288 uses
289         Giko, RoundData, Favorite, Registry, HTMLCreate, MojuUtils, Sort, YofUtils,
290         IniFiles, DateUtils, SkinFiles;
291
292 const
293         FOLDER_INDEX_VERSION                                    = '1.01';
294         USER_AGENT                                                                              = 'Monazilla';
295         DEFAULT_NGWORD_FILE_NAME : String = 'NGword.txt';
296         NGWORDs_DIR_NAME : String               = 'NGwords';
297
298         READ_PATH: string =                     '/test/read.cgi/';
299     HTML_READ_PATH: string =        '/test/read.html/';
300         OLD_READ_PATH: string =         '/test/read.cgi?';
301         KAKO_PATH: string =                     '/kako/';
302
303         KeyWordStr: array [TVerResourceKey] of String = (
304                   'Comments',
305                   'CompanyName',
306                   'FileDescription',
307                   'FileVersion',
308                   'InternalName',
309                   'LegalCopyright',
310                   'LegalTrademarks',
311                   'OriginalFilename',
312                   'PrivateBuild',
313                   'ProductName',
314                   'ProductVersion',
315                   'SpecialBuild');
316
317 // *************************************************************************
318 //! GikoSys\83R\83\93\83X\83g\83\89\83N\83^
319 // *************************************************************************
320 constructor TGikoSys.Create;
321 begin
322     Inherited;
323         FSetting := TSetting.Create;
324         FDolib := TDolib.Create;
325     FBelib := TBelib.Create;
326         FAWKStr := TAWKStr.Create(nil);
327         if DirectoryExists(GetConfigDir) = false then begin
328                 CreateDir(GetConfigDir);
329         end;
330         FAbon := TAbon.Create;
331     FAbon.IgnoreKana := FSetting.IgnoreKana;
332         FAbon.Setroot(GetConfigDir+NGWORDs_DIR_NAME);
333         FAbon.GoHome;
334         FAbon.ReturnNGwordLineNum := FSetting.ShowNGLinesNum;
335         FAbon.SetNGResAnchor := FSetting.AddResAnchor;
336         FAbon.DeleteSyria := FSetting.DeleteSyria;
337         FAbon.Deleterlo := FSetting.AbonDeleterlo;
338         FAbon.Replaceul := FSetting.AbonReplaceul;
339         FAbon.AbonPopupRes := FSetting.PopUpAbon;
340
341         FSelectResFilter := TAbon.Create;
342     FSelectResFilter.IgnoreKana := True;
343         // \8di\82è\8d\9e\82Þ\82Æ\82«\82Í\8bÉ\97Í\88ê\97\97\82ª\8c©\82ç\82ê\82é\82Ù\82¤\82ª\82¢\82¢\82Ì\82Å\91¼\82Í\8a®\91S\82É\8dí\8f\9c
344         FSelectResFilter.AbonString := '';
345     //
346         ResRange := FSetting.ResRange;
347         FVersion := Trim(GetVersionInfo(vrFileVersion));
348         FBayesian := TGikoBayesian.Create;
349         //FBoardURLList := TStringList.Create;
350         //\83\81\83b\83Z\81[\83W\82Ì\8dì\90¬
351         FGikoMessage := TGikoMessage.Create;
352 end;
353
354 // *************************************************************************
355 //! GikoSys\83f\83X\83g\83\89\83N\83^
356 // *************************************************************************
357 destructor TGikoSys.Destroy;
358 var
359         i: Integer;
360         FileList: TStringList;
361 begin
362         //\83e\83\93\83|\83\89\83\8aHTML\82ð\8dí\8f\9c
363         FileList := TStringList.Create;
364         try
365         FileList.BeginUpdate;
366                 GetFileList(GetTempFolder, '*.html', FileList, False, True);
367         FileList.EndUpdate;
368                 for i := 0 to FileList.Count - 1 do begin
369                         DeleteFile(FileList[i]);
370                 end;
371         finally
372                 FileList.Free;
373         end;
374     FreeAndNil(FGikoMessage);
375         FreeAndNil(FBayesian);
376         FreeAndNil(FSelectResFilter);
377         FreeAndNil(FAbon);
378         FreeAndNil(FAWKStr);
379     FreeAndNil(FBelib);
380         FreeAndNil(FDolib);
381         FreeAndNil(FSetting);
382         inherited;
383 end;
384
385 {!
386 \brief \95\8e\9a\97ñ\90\94\8e\9a\83`\83F\83b\83N
387 \param s \83`\83F\83b\83N\82·\82é\95\8e\9a\97ñ
388 \return s \82ª\95\84\8d\86\95t\82«\90®\90\94\82Æ\82µ\82Ä\94F\8e¯\89Â\94\\82È\82ç True
389 }
390 {$HINTS OFF}
391 function TGikoSys.IsNumeric(s: string): boolean;
392 var
393         e: integer;
394         v: integer;
395 begin
396         Val(s, v, e);
397         Result := e = 0;
398 end;
399 {$HINTS ON}
400
401 {!
402 \brief \95\8e\9a\97ñ\95\82\93®\8f¬\90\94\93_\90\94\8e\9a\83`\83F\83b\83N
403 \param s \83`\83F\83b\83N\82·\82é\95\8e\9a\97ñ
404 \return s \82ª\95\84\8d\86\95t\82«\95\82\93®\8f¬\90\94\82Æ\82µ\82Ä\94F\8e¯\89Â\94\\82È\82ç True
405 }
406 function TGikoSys.IsFloat(s: string): boolean;
407 var
408         v: Extended;
409 begin
410         Result := TextToFloat(PChar(s), v, fvExtended);
411 end;
412
413 // *************************************************************************
414 //! \83{\81[\83h\83t\83@\83C\83\8b\96¼\8eæ\93¾\81i\83p\83X\81{\83t\83@\83C\83\8b\96¼\81j
415 // *************************************************************************
416 function TGikoSys.GetBoardFileName: string;
417 begin
418         Result := Setting.GetBoardFileName;
419 end;
420
421 // *************************************************************************
422 //! \83{\81[\83h\83t\83@\83C\83\8b\96¼\8eæ\93¾\81i\83p\83X\81{\83t\83@\83C\83\8b\96¼\81j
423 // *************************************************************************
424 function TGikoSys.GetCustomBoardFileName: string;
425 begin
426         Result := Setting.GetCustomBoardFileName;
427 end;
428
429 // *************************************************************************
430 //! \83e\83\93\83|\83\89\83\8a\83t\83H\83\8b\83_\81[\96¼\8eæ\93¾
431 // *************************************************************************
432 function TGikoSys.GetHtmlTempFileName: string;
433 begin
434         Result := Setting.GetHtmlTempFileName;
435 end;
436
437
438 // *************************************************************************
439 //! \8eÀ\8ds\83t\83@\83C\83\8b\83t\83H\83\8b\83_\8eæ\93¾
440 // *************************************************************************
441 function TGikoSys.GetAppDir: string;
442 begin
443         Result := Setting.GetAppDir;
444 end;
445
446 // *************************************************************************
447 //! TempHtml\83t\83@\83C\83\8b\96¼\8eæ\93¾\81i\83p\83X\81{\83t\83@\83C\83\8b\96¼\81j
448 // *************************************************************************
449 function TGikoSys.GetTempFolder: string;
450 begin
451         Result := Setting.GetTempFolder;
452 end;
453
454 // *************************************************************************
455 //! sent.ini\83t\83@\83C\83\8b\96¼\8eæ\93¾\81i\83p\83X\81{\83t\83@\83C\83\8b\96¼\81j
456 // *************************************************************************)
457 function TGikoSys.GetSentFileName: string;
458 begin
459         Result := Setting.GetSentFileName;
460 end;
461
462 // *************************************************************************
463 //! outbox.ini\83t\83@\83C\83\8b\96¼\8eæ\93¾\81i\83p\83X\81{\83t\83@\83C\83\8b\96¼\81j
464 // *************************************************************************
465 function TGikoSys.GetOutBoxFileName: string;
466 begin
467         Result := Setting.GetOutBoxFileName;
468 end;
469
470 // *************************************************************************
471 //! Config\83t\83H\83\8b\83_\8eæ\93¾
472 // *************************************************************************
473 function TGikoSys.GetConfigDir: string;
474 begin
475         Result := Setting.GetConfigDir;
476 end;
477
478 function TGikoSys.GetNGWordsDir: string;
479 begin
480         Result := Setting.GetConfigDir + NGWORDs_DIR_NAME;
481 end;
482
483
484 //! \83X\83^\83C\83\8b\83V\81[\83g\83t\83H\83\8b\83_
485 function TGikoSys.GetStyleSheetDir: string;
486 begin
487         Result := Setting.GetStyleSheetDir;
488 end;
489
490 //! \83X\83L\83\93\83t\83H\83\8b\83_
491 function TGikoSys.GetSkinDir: string;
492 begin
493         Result := Setting.GetSkinDir;
494 end;
495
496 //! Skin:\83w\83b\83_\82Ì\83t\83@\83C\83\8b\96¼
497 function TGikoSys.GetSkinHeaderFileName: string;
498 begin
499         Result := Setting.SkinFiles.GetSkinHeaderFileName;
500 end;
501
502 //! Skin:\83t\83b\83^\82Ì\83t\83@\83C\83\8b\96¼
503 function TGikoSys.GetSkinFooterFileName: string;
504 begin
505         Result := Setting.SkinFiles.GetSkinFooterFileName;
506 end;
507
508 //! Skin:\90V\92\85\83\8c\83X\82Ì\83t\83@\83C\83\8b\96¼
509 function TGikoSys.GetSkinNewResFileName: string;
510 begin
511         Result := Setting.SkinFiles.GetSkinNewResFileName;
512 end;
513
514 //! Skin:\94ñ\90V\92\85\83\8c\83X\82Ì\83t\83@\83C\83\8b\96¼
515 function TGikoSys.GetSkinResFileName: string;
516 begin
517         Result := Setting.SkinFiles.GetSkinResFileName;
518 end;
519
520 //! Skin:\82µ\82¨\82è(\82±\82±\82Ü\82Å\93Ç\82ñ\82¾)\82Ì\83t\83@\83C\83\8b\96¼
521 function TGikoSys.GetSkinBookmarkFileName: string;
522 begin
523         Result := Setting.SkinFiles.GetSkinBookmarkFileName;
524 end;
525
526 //! Skin:\82µ\82¨\82è(\90V\92\85\83\8c\83X)\82Ì\83t\83@\83C\83\8b\96¼
527 function TGikoSys.GetSkinNewmarkFileName: string;
528 begin
529         Result := Setting.SkinFiles.GetSkinNewmarkFileName;
530 end;
531
532 //! UserAgent\8eæ\93¾
533 function TGikoSys.GetUserAgent: string;
534 begin
535         if Dolib.Connected then begin
536                 Result := Format('%s %s/%s%d/%s', [
537                                                                 Dolib.UserAgent,
538                                                                 APP_NAME,
539                                                                 BETA_VERSION_NAME_E,
540                                                                 BETA_VERSION,
541                                                                 Version]);
542         end else begin
543                 Result := Format('%s/%s %s/%s%d/%s', [
544                                                                 USER_AGENT,
545                                                                 Dolib.Version,
546                                                                 APP_NAME,
547                                                                 BETA_VERSION_NAME_E,
548                                                                 BETA_VERSION,
549                                                                 Version]);
550         end;
551 end;
552
553 {!
554 \brief \8co\89ß\95b\82ð TDateTime \82É\95Ï\8a·
555 \param val 1970/1/1/ 00:00:00 \82©\82ç\82Ì\8co\89ß\95b
556 \return val \82ð\8e¦\82· TDateTime
557 }
558 function TGikoSys.IntToDateTime(val: Int64): TDateTime;
559 begin
560         Result := ZERO_DATE + val / 86400.0;
561 end;
562
563 {!
564 \brief TDateTime \82ð\8co\89ß\95b\82É\95Ï\8a·
565 \param ADate \95Ï\8a·\82·\82é\8e\9e\8d\8f
566 \return 1970/1/1/ 00:00:00 \82©\82ç\82Ì\8co\89ß\95b
567 }
568 function TGikoSys.DateTimeToInt(ADate: TDateTime): Int64;
569 begin
570         Result := Trunc((ADate - ZERO_DATE) * 86400);
571 end;
572
573
574 {!
575 \brief Subject\83t\83@\83C\83\8bRead
576 \param Board \83X\83\8c\88ê\97\97\82ð\8eæ\93¾\82·\82é\94Â
577 }
578 procedure TGikoSys.ReadSubjectFile(Board: TBoard);
579 var
580         ThreadItem: TThreadItem;
581         FileName: string;
582         FileList: TStringList;
583         Index: Integer;
584         sl: TStringList;
585         i: Integer;
586         Rec: TIndexRec;
587         UnRead: Integer;
588         usePlugIn : Boolean;
589         islog : Boolean;
590     urlHead: String;
591     datFileCheck: Boolean;
592         {*
593         FavoThreadItem : TFavoriteThreadItem;
594         Node: TTreeNode;
595         *}
596 {$IFDEF DEBUG}
597     st, rt: Cardinal;
598 {$ENDIF}
599 begin
600 {$IFDEF DEBUG}
601         st := GetTickCount;
602 {$ENDIF}
603         if Board.IsThreadDatRead then
604                 Exit;
605         Board.Clear;
606         UnRead := 0;
607         usePlugIn := Board.IsBoardPlugInAvailable;
608         //server :=  UrlToServer( Board.URL );
609     // \83X\83\8c\83b\83h\82Å\8b¤\92Ê\82ÌURL\95\94
610     if Board.is2ch then begin
611         urlHead := UrlToServer( Board.URL ) + 'test/read.cgi/' + Board.BBSID + '/';
612     end else begin
613         urlHead := UrlToServer( Board.URL ) + 'test/read.cgi?bbs=' + Board.BBSID + '&key=';
614     end;
615
616         FileName := Board.GetFolderIndexFileName;
617
618     //
619     datFileCheck := (Setting.CheckDatFile) or (not FileExists(FileName));
620     if (datFileCheck) then begin
621         FileList := TStringList.Create;
622         FileList.Sorted := True;
623         FileList.BeginUpdate;
624         //IsLogFile\97pDAT\83t\83@\83C\83\8b\83\8a\83X\83g
625         GetFileList(ExtractFileDir(Board.GetFolderIndexFileName), '*.dat', FileList, False);
626         FileList.EndUpdate;
627     end;
628
629         // \8fd\95¡\82ð\96h\82®
630         Board.BeginUpdate;
631         Board.Sorted := True;
632         sl := TStringList.Create;
633         try
634                 if FileExists(FileName) then begin
635                         sl.LoadFromFile(FileName);
636                         //\82Q\8ds\96Ú\82©\82ç\81i\82P\8ds\96Ú\82Í\83o\81[\83W\83\87\83\93\81j
637                         for i := sl.Count - 1 downto 1 do begin
638                                 Rec := ParseIndexLine(sl[i]);
639                 if (datFileCheck) then begin
640                                 islog := FileList.Find( Rec.FFileName, Index );
641                 end else begin
642                     islog := (Rec.FSize <> 0) and (Rec.FCount <> 0);
643                 end;
644                                 if usePlugIn then
645                                         ThreadItem := TThreadItem.Create(
646                                                         Board.BoardPlugIn,
647                                                         Board,
648                                                         Board.BoardPlugIn.FileName2ThreadURL( DWORD( Board ), Rec.FFileName ) )
649                                 else begin
650                                         if Board.is2ch then begin
651                                                 ThreadItem := TThreadItem.Create(
652                                                         nil,
653                                                         Board,
654                                                         urlHead + ChangeFileExt( Rec.FFileName, '' ) + '/l50',
655                                                         islog,
656                                                         Rec.FFileName
657                                                         );
658                                         end else begin
659                                                 ThreadItem := TThreadItem.Create(
660                                                         nil,
661                                                         Board,
662                                                         urlHead + ChangeFileExt( Rec.FFileName, '' ) + '&ls=50',
663                                                         islog,
664                                                         Rec.FFileName
665                                                         );
666                                         end;
667                                 end;
668
669                                 //ThreadItem.BeginUpdate;
670                                 if (datFileCheck) and (islog) then
671                                         FileList.Delete( Index );
672
673                                 ThreadItem.No := Rec.FNo;
674                                 ThreadItem.FileName := Rec.FFileName;
675                                 ThreadItem.Title := MojuUtils.UnSanitize(Rec.FTitle);
676                                 ThreadItem.Count := Rec.FCount;
677                                 ThreadItem.Size := Rec.FSize;
678                                 ThreadItem.RoundDate := Rec.FRoundDate;
679                                 ThreadItem.LastModified := Rec.FLastModified;
680                                 ThreadItem.Kokomade := Rec.FKokomade;
681                                 ThreadItem.NewReceive := Rec.FNewReceive;
682                                 ThreadItem.UnRead := Rec.FUnRead;
683                                 ThreadItem.ScrollTop := Rec.FScrollTop;
684                                 ThreadItem.AllResCount := Rec.FAllResCount;
685                                 ThreadItem.NewResCount := Rec.FNewResCount;
686                                 ThreadItem.AgeSage := Rec.FAgeSage;
687                                 ThreadItem.ParentBoard := Board;
688                                 {* \82¨\8bC\82É\93ü\82è\91å\97Ê\90\90¬\83R\81[\83h *}
689                                 {*
690                                 FavoThreadItem := TFavoriteThreadItem.Create( ThreadItem.URL, ThreadItem.Title, ThreadItem );
691                                 Node := FavoriteDM.TreeView.Items.AddChildObject( FavoriteDM.TreeView.Items.Item[0], ThreadItem.Title, FavoThreadItem);
692                                 *}
693
694                                 //ThreadItem.EndUpdate;
695                                 Board.Add(ThreadItem);
696
697                                 if (ThreadItem.UnRead) and (ThreadItem.IsLogFile) then
698                                         Inc(UnRead);
699                         end;
700                 end;
701
702                 if UnRead <> Board.UnRead then
703                         Board.UnRead := UnRead;
704
705         if (datFileCheck) then begin
706                     //\83C\83\93\83f\83b\83N\83X\82É\96³\82©\82Á\82½\83\8d\83O\82ð\92Ç\89Á\81i\95\85\82ê\83C\83\93\83f\83b\83N\83X\91Î\89\9e\81j
707             AddOutofIndexDat(Board, FileList);
708         end;
709                 Board.EndUpdate;
710
711         //\91O\89ñ\88Ù\8fí\8fI\97¹\8e\9e\83`\83F\83b\83N
712         RestoreThreadData( Board );
713         finally
714                 sl.Free;
715         if (datFileCheck) then begin
716                 FileList.Free;
717         end;
718                 Board.Sorted := False;
719         end;
720         Board.IsThreadDatRead := True;
721 {$IFDEF DEBUG}
722         rt := GetTickCount - st;
723         Writeln('Read Done.' + Board.Title + ':' + IntToStr(rt) + ' ms');
724 {$ENDIF}
725 end;
726 {!
727 \brief \83C\83\93\83f\83b\83N\83X\82É\82È\82¢dat\81i\82Í\82®\82êdat\81j\82Ì\92Ç\89Á
728 \param Board \92Ç\89Á\82·\82é\94Â
729 \param DatList  dat\83t\83@\83C\83\8b\96¼
730 }
731 procedure TGikoSys.AddOutofIndexDat(Board: TBoard; DatList: TStringList; AllCreate: Boolean = True);
732 var
733     i : Integer;
734     Boardpath,FileName : String;
735     ResRec: TResRec;
736     ThreadItem: TThreadItem;
737     create: Boolean;
738 begin
739     create := False;
740     Boardpath := ExtractFilePath(Board.GetFolderIndexFileName);
741     //\83C\83\93\83f\83b\83N\83X\82É\96³\82©\82Á\82½\83\8d\83O\82ð\92Ç\89Á\81i\95\85\82ê\83C\83\93\83f\83b\83N\83X\91Î\89\9e\81j
742     for i := 0 to DatList.Count - 1 do begin
743         FileName := Boardpath + DatList[i];
744         ThreadItem := nil;
745         if (not AllCreate) then begin
746             create := False;
747             ThreadItem := Board.FindThreadFromFileName(DatList[i]);
748             if (ThreadItem = nil) then begin
749                 create := True;
750             end else begin
751                 if Board.IsBoardPlugInAvailable then begin
752                     THTMLCreate.DivideStrLine(Board.BoardPlugIn.GetDat( DWORD( ThreadItem ), 1 ), @ResRec);
753                 end else begin
754                     THTMLCreate.DivideStrLine(ReadThreadFile(FileName, 1), @ResRec);
755                 end;
756             end;
757         end;
758         if (ThreadItem = nil) then begin
759             if Board.IsBoardPlugInAvailable then begin
760                 ThreadItem := TThreadItem.Create(
761                     Board.BoardPlugIn,
762                     Board,
763                     Board.BoardPlugIn.FileName2ThreadURL( DWORD( Board ), DatList[i] ) );
764                 THTMLCreate.DivideStrLine(Board.BoardPlugIn.GetDat( DWORD( ThreadItem ), 1 ), @ResRec);
765             end else begin
766                 ThreadItem := TThreadItem.Create(
767                     nil,
768                     Board,
769                     Get2chBoard2ThreadURL( Board, ChangeFileExt( DatList[i], '' ) ) );
770                 THTMLCreate.DivideStrLine(ReadThreadFile(FileName, 1), @ResRec);
771             end;
772         end;
773         
774
775         ThreadItem.BeginUpdate;
776         ThreadItem.FileName := DatList[i];
777         //ThreadItem.FilePath := FileName;
778         ThreadItem.No := Board.Count + 1;
779         ThreadItem.Title := ResRec.FTitle;
780         ThreadItem.Count := GetFileLineCount(FileName);
781         ThreadItem.AllResCount := ThreadItem.Count;
782         ThreadItem.NewResCount := ThreadItem.Count;
783         ThreadItem.Size := GetFileSize(FileName) - ThreadItem.Count;//1byte\82¸\82ê\82é\82Æ\82«\82ª\82 \82é\82¯\82Ç\82»\82ê\82Í\82 \82«\82ç\82ß\82é
784         ThreadItem.RoundDate := FileDateToDateTime( FileAge( FileName ) );
785         ThreadItem.LastModified := ThreadItem.RoundDate;
786         ThreadItem.Kokomade := -1;
787         ThreadItem.NewReceive := 0;
788         ThreadItem.ParentBoard := Board;
789         ThreadItem.IsLogFile := True;
790         ThreadItem.Round := False;
791         ThreadItem.UnRead := False;
792         ThreadItem.ScrollTop := 0;
793         ThreadItem.AgeSage := gasNone;
794         ThreadItem.EndUpdate;
795         if (AllCreate) or (create) then begin
796             Board.Add(ThreadItem);
797         end;
798     end;
799 end;
800 {!
801 \brief \83X\83\8c\83b\83h\83C\83\93\83f\83b\83N\83X\83t\83@\83C\83\8b(Folder.idx)\8dì\90¬
802 \param Board Folder.idx \82ð\8dì\90¬\82·\82é\94Â
803 }
804 procedure TGikoSys.CreateThreadDat(Board: TBoard);
805 var
806         i: integer;
807         s: string;
808         SubjectList: TStringList;
809         sl: TStringList;
810         Rec: TSubjectRec;
811         FileName: string;
812         cnt: Integer;
813 begin
814         if not FileExists(Board.GetSubjectFileName) then Exit;
815         FileName := Board.GetFolderIndexFileName;
816
817         SubjectList := TStringList.Create;
818         try
819                 SubjectList.LoadFromFile(Board.GetSubjectFileName);
820                 sl := TStringList.Create;
821                 try
822                         cnt := 1;
823                         sl.BeginUpdate;
824                         sl.Add(FOLDER_INDEX_VERSION);
825                         for i := 0 to SubjectList.Count - 1 do begin
826                                 Rec := DivideSubject(SubjectList[i]);
827
828                                 if (Trim(Rec.FFileName) = '') or (Trim(Rec.FTitle) = '') then
829                                         Continue;
830
831                                 {s := Format('%x', [cnt]) + #1                                  //\94Ô\8d\86
832                                          + Rec.FFileName + #1                                                           //\83t\83@\83C\83\8b\96¼
833                                          + Rec.FTitle + #1                                                                      //\83^\83C\83g\83\8b
834                                          + Format('%x', [Rec.FCount]) + #1      //\83J\83E\83\93\83g
835                                          + Format('%x', [0]) + #1                                               //size
836                                          + Format('%x', [0]) + #1                                               //RoundDate
837                                          + Format('%x', [0]) + #1                                               //LastModified
838                                          + Format('%x', [0]) + #1                                               //Kokomade
839                                          + Format('%x', [0]) + #1                                               //NewReceive
840                                          + '0' + #1                                                                                             //\96¢\8eg\97p
841                                          + Format('%x', [0]) + #1                                               //UnRead
842                                          + Format('%x', [0]) + #1                                               //ScrollTop
843                                          + Format('%x', [Rec.FCount]) + #1      //AllResCount
844                                          + Format('%x', [0]) + #1                                               //NewResCount
845                                          + Format('%x', [0]);                                                           //AgeSage
846                                 }
847                                 s := Format('%x'#1'%s'#1'%s'#1'%x'#1'%x'#1'%x'#1'%x'#1'%x'#1'%x'#1 + 
848                                                         '%s'#1'%x'#1'%x'#1'%x'#1'%x'#1'%x',
849                                         [cnt,                   //\94Ô\8d\86
850                                          Rec.FFileName, //\83t\83@\83C\83\8b\96¼
851                                          MojuUtils.Sanitize(Rec.FTitle),    //\83^\83C\83g\83\8b
852                                          Rec.FCount,     //\83J\83E\83\93\83g
853                                          0,             //size
854                                          0,             //RoundDate
855                                          0,                             //LastModified
856                                          0,                             //Kokomade
857                                          0,                             //NewReceive
858                                          '0',                   //\96¢\8eg\97p
859                                          0,                             //UnRead
860                                          0,                             //ScrollTop
861                                          Rec.FCount,    //AllResCount
862                                          0,                             //NewResCount
863                                          0]             //AgeSage
864                                         );
865
866                                 sl.Add(s);
867                                 inc(cnt);
868                         end;
869                         sl.EndUpdate;
870                         sl.SaveToFile(FileName);
871                 finally
872                         sl.Free;
873                 end;
874         finally
875                 SubjectList.Free;
876         end;
877 end;
878
879 {!
880 \brief \83X\83\8c\83b\83h\83C\83\93\83f\83b\83N\83X(Thread.dat)\8f\91\82«\8d\9e\82Ý
881 \param Thread.dat \82ð\8dì\90¬\82·\82é\94Â
882 }
883 procedure TGikoSys.WriteThreadDat(Board: TBoard);
884 //const
885 //      Values: array[Boolean] of string = ('0', '1');
886 var
887         i: integer;
888         FileName: string;
889         sl: TStringList;
890         s: string;
891         TmpFileList: TStringList;
892 begin
893         if not Board.IsThreadDatRead then
894                 Exit;
895         FileName := Board.GetFolderIndexFileName;
896         ForceDirectoriesEx( ExtractFilePath( FileName ) );
897
898         sl := TStringList.Create;
899         TmpFileList := TStringList.Create;
900         TmpFileList.Sorted := true;
901         try
902         TmpFileList.BeginUpdate;
903                 GetFileList(ExtractFileDir(Board.GetFolderIndexFileName), '*.tmp', TmpFileList, false);
904         TmpFileList.EndUpdate;
905                 sl.BeginUpdate;
906                 sl.Add(FOLDER_INDEX_VERSION);
907
908                 // \83X\83\8c\94Ô\8d\86\95Û\91\82Ì\82½\82ß\83\\81[\83g
909                 Sort.SetSortNoFlag(true);
910                 Sort.SetSortOrder(true);
911                 Sort.SetSortIndex(0);
912                 //Sort.SortNonAcquiredCountFlag := GikoSys.Setting.NonAcquiredCount;
913                 Board.CustomSort(ThreadItemSortProc);
914
915                 for i := 0 to Board.Count - 1 do begin
916                         Board.Items[i].No := i + 1;
917                         s := Format('%x'#1'%s'#1'%s'#1'%x'#1'%x'#1'%x'#1'%x'#1'%x'#1'%x'#1 +
918                                                         '%s'#1'%x'#1'%x'#1'%x'#1'%x'#1'%x',
919                                         [Board.Items[i].No,                     //\94Ô\8d\86
920                                          Board.Items[i].FileName, //\83t\83@\83C\83\8b\96¼
921                      MojuUtils.Sanitize(Board.Items[i].Title),    //\83^\83C\83g\83\8b
922                                          Board.Items[i].Count,     //\83J\83E\83\93\83g
923                                          Board.Items[i].Size,             //size
924                                          DateTimeToInt(Board.Items[i].RoundDate),             //RoundDate
925                                          DateTimeToInt(Board.Items[i].LastModified),                            //LastModified
926                                          Board.Items[i].Kokomade,                               //Kokomade
927                                          Board.Items[i].NewReceive,                             //NewReceive
928                                          '0',                   //\96¢\8eg\97p
929                                          BoolToInt(Board.Items[i].UnRead),                              //UnRead
930                                          Board.Items[i].ScrollTop,                              //ScrollTop
931                                          Board.Items[i].AllResCount,    //AllResCount
932                                          Board.Items[i].NewResCount,                            //NewResCount
933                                          Ord(Board.Items[i].AgeSage)]             //AgeSage
934                                         );
935
936                         sl.Add(s);
937                 end;
938                 sl.EndUpdate;
939                 sl.SaveToFile(FileName);
940
941                 for i := 0 to TmpFileList.Count - 1 do begin
942                         DeleteFile(ExtractFilePath(Board.GetFolderIndexFileName) + TmpFileList[i]);
943                 end;
944
945         finally
946                 TmpFileList.Free;
947                 sl.Free;
948         end;
949 end;
950
951 {!
952 \brief Folder.idx \82ð 1 \8ds\89ð\8eß
953 \param Line Folder.idx \82ð\8d\\90¬\82·\82é 1 \8ds
954 \return \83X\83\8c\83b\83h\8fî\95ñ
955 }
956 function TGikoSys.ParseIndexLine(Line: string): TIndexRec;
957 begin
958         Result.FNo := StrToIntDef('$' + MojuUtils.RemoveToken(Line, #1), 0);
959         Result.FFileName := MojuUtils.RemoveToken(Line, #1);
960         Result.FTitle := MojuUtils.UnSanitize(MojuUtils.RemoveToken(Line, #1));
961         Result.FCount := StrToIntDef('$' + MojuUtils.RemoveToken(Line, #1), 0);
962         Result.FSize := StrToIntDef('$' + MojuUtils.RemoveToken(Line, #1), 0);
963         Result.FRoundDate := IntToDateTime(StrToIntDef('$' + MojuUtils.RemoveToken(Line, #1), ZERO_DATE));
964         Result.FLastModified := IntToDateTime(StrToIntDef('$' + MojuUtils.RemoveToken(Line, #1), ZERO_DATE));
965         Result.FKokomade := StrToIntDef('$' + MojuUtils.RemoveToken(Line, #1), -1);
966         Result.FNewReceive := StrToIntDef('$' + MojuUtils.RemoveToken(Line, #1), 0);
967         MojuUtils.RemoveToken(Line, #1);//9: ;  //\96¢\8eg\97p
968         Result.FUnRead := IntToBool(StrToIntDef('$' + MojuUtils.RemoveToken(Line, #1), 0));
969         Result.FScrollTop := StrToIntDef('$' + MojuUtils.RemoveToken(Line, #1), 0);
970         Result.FAllResCount := StrToIntDef('$' + MojuUtils.RemoveToken(Line, #1), 0);
971         Result.FNewResCount := StrToIntDef('$' + MojuUtils.RemoveToken(Line, #1), 0);
972         Result.FAgeSage := TGikoAgeSage(StrToIntDef('$' + MojuUtils.RemoveToken(Line, #1), 0));
973
974 end;
975
976 {!
977 \brief \8ew\92è\83t\83H\83\8b\83_\93à\82Ì\8ew\92è\83t\83@\83C\83\8b\88ê\97\97\82ð\8eæ\93¾\82·\82é
978 \param Path      \8bN\93_\82Æ\82È\82é\83t\83H\83\8b\83_\83p\83X
979 \param Mask      \83t\83@\83C\83\8b\96¼\82Ì\83}\83X\83N
980 \param List      OUT:\8eæ\93¾\82³\82ê\82½\83t\83@\83C\83\8b\96¼\88ê\97\97\82ª\95Ô\82é
981 \param SubDir    \92\86\82Ì\83t\83H\83\8b\83_\82Ü\82Å\8dÄ\8bA\93I\82É\83\8a\83X\83g\82·\82é\8fê\8d\87\82Í True
982 \param IsPathAdd \83p\83X\95t\82«\82Å\83\8a\83X\83g\83A\83b\83v\82·\82é\8fê\8d\87\82Í True
983
984 Mask \82ð '*.txt' \82Ì\82æ\82¤\82É\8ew\92è\82·\82é\82±\82Æ\82Å\81A
985 \93Á\92è\82Ì\83t\83@\83C\83\8b\96¼\82â\93Á\92è\82Ì\8ag\92£\8eq\82É\8di\82Á\82½\83\8a\83X\83g\83A\83b\83v\82ª\89Â\94\\82Å\82·\81B
986
987 \par \97á:
988 \code
989 GetFileList('c:\', '*.txt', list, True, True);
990 \endcode
991 }
992 procedure TGikoSys.GetFileList(Path: string; Mask: string; var List: TStringList; SubDir: Boolean; IsPathAdd: Boolean);
993 var
994         rc: Integer;
995         SearchRec : TSearchRec;
996         s: string;
997 begin
998         Path := IncludeTrailingPathDelimiter(Path);
999         rc := FindFirst(Path + '*.*', faAnyfile, SearchRec);
1000         try
1001                 while rc = 0 do begin
1002                         if (SearchRec.Name <> '..') and (SearchRec.Name <> '.') then begin
1003                                 s := Path + SearchRec.Name;
1004
1005                                 if (SearchRec.Attr and faDirectory = 0) and (MatchesMask(s, Mask)) then
1006                                                 if IsPathAdd then
1007                                                         List.Add(s)
1008                                                 else
1009                                                         List.Add(SearchRec.Name);
1010                                 if SubDir and (SearchRec.Attr and faDirectory > 0) then
1011                                         GetFileList(s, Mask, List, True, IsPathAdd);
1012                         end;
1013                         rc := FindNext(SearchRec);
1014                 end;
1015         finally
1016                 SysUtils.FindClose(SearchRec);
1017         end;
1018         List.Sort;
1019 end;
1020
1021 {!
1022 \breif \8ew\92è\83t\83H\83\8b\83_\93à\82Ì\8ew\92è\83t\83@\83C\83\8b\88ê\97\97\82ð\8eæ\93¾\82·\82é\81B
1023                          \83T\83u\83t\83H\83\8b\83_\82Í\8c\9f\8dõ\82µ\82È\82¢
1024 \param Path      \8bN\93_\82Æ\82È\82é\83t\83H\83\8b\83_\83p\83X
1025 \param Mask      \83t\83@\83C\83\8b\96¼\82Ì\83}\83X\83N
1026 \param List      OUT:\8eæ\93¾\82³\82ê\82½\83t\83@\83C\83\8b\96¼\88ê\97\97\82ª\95Ô\82é
1027 \param IsPathAdd \83p\83X\95t\82«\82Å\83\8a\83X\83g\83A\83b\83v\82·\82é\8fê\8d\87\82Í True
1028 \note \8dÄ\8bN\8ew\92è\89Â\94\\82È GetFileList() \82ª\82 \82é\82Ì\82Å\82±\82Ì\8aÖ\90\94\82Í\95s\97v?
1029 \par \97á
1030 \code
1031 GetFileList('c:\', '*.txt', list, True);
1032 \endcode
1033 }
1034 procedure TGikoSys.GetFileList(Path: string; Mask: string; var List: TStringList; IsPathAdd: Boolean);
1035 var
1036         rc: Integer;
1037         SearchRec : TSearchRec;
1038 begin
1039         Path := IncludeTrailingPathDelimiter(Path);
1040         rc := FindFirst(Path + Mask, faAnyfile, SearchRec);
1041         try
1042                 while rc = 0 do begin
1043                         if (SearchRec.Name <> '..') and (SearchRec.Name <> '.') then begin
1044                                 if (SearchRec.Attr and faDirectory = 0) then begin
1045                     if IsPathAdd then begin
1046                         List.Add(Path + SearchRec.Name)
1047                     end else begin
1048                         List.Add(SearchRec.Name);
1049                     end;
1050                 end;
1051                         end;
1052                         rc := FindNext(SearchRec);
1053                 end;
1054         finally
1055                 SysUtils.FindClose(SearchRec);
1056         end;
1057         List.Sort;
1058 end;
1059
1060 {!
1061 \brief \8ew\92è\83t\83H\83\8b\83_\93à\82Ì\83f\83B\83\8c\83N\83g\83\8a\88ê\97\97\82ð\8eæ\93¾\82·\82é
1062 \param Path      \8bN\93_\82Æ\82È\82é\83t\83H\83\8b\83_\83p\83X
1063 \param Mask      \83t\83H\83\8b\83_\96¼\82Ì\83}\83X\83N
1064 \param List      OUT:\8eæ\93¾\82³\82ê\82½\83t\83H\83\8b\83_\96¼\88ê\97\97\82ª\95Ô\82é
1065 \param SubDir    \92\86\82Ì\83t\83H\83\8b\83_\82Ü\82Å\8dÄ\8bA\93I\82É\83\8a\83X\83g\82·\82é\8fê\8d\87\82Í True
1066
1067 Mask \82ð '*.txt' \82Ì\82æ\82¤\82É\8ew\92è\82·\82é\82±\82Æ\82Å\81A
1068 \93Á\92è\82Ì\83t\83@\83C\83\8b\96¼\82â\93Á\92è\82Ì\8ag\92£\8eq\82É\8di\82Á\82½\83\8a\83X\83g\83A\83b\83v\82ª\89Â\94\\82Å\82·\81B
1069
1070 \par \97á:
1071 \code
1072 GetDirectoryList('c:\', '*.txt', list, True);
1073 \endcode
1074 }
1075 procedure TGikoSys.GetDirectoryList(Path: string; Mask: string; List: TStringList; SubDir: Boolean);
1076 var
1077         rc: Integer;
1078         SearchRec : TSearchRec;
1079         s: string;
1080 begin
1081         Path := IncludeTrailingPathDelimiter(Path);
1082         rc := FindFirst(Path + '*.*', faDirectory, SearchRec);
1083         try
1084                 while rc = 0 do begin
1085                         if (SearchRec.Name <> '..') and (SearchRec.Name <> '.') then begin
1086                                 s := Path + SearchRec.Name;
1087                                 //if (SearchRec.Attr and faDirectory > 0) then
1088                                 //      s := IncludeTrailingPathDelimiter(s)
1089
1090                                 if (SearchRec.Attr and faDirectory > 0) and (MatchesMask(s, Mask)) then
1091                                         List.Add( IncludeTrailingPathDelimiter( s ) );
1092                                 if SubDir and (SearchRec.Attr and faDirectory > 0) then
1093                                         GetDirectoryList(s, Mask, List, True);
1094                         end;
1095                         rc := FindNext(SearchRec);
1096                 end;
1097         finally
1098                 SysUtils.FindClose(SearchRec);
1099         end;
1100 end;
1101
1102
1103 {!
1104 \brief Subject.txt \88ê\8ds\82ð\89ð\8eß
1105 \param Line Subject.txt \82ð\8d\\90¬\82·\82é 1 \8ds
1106 \return     \83X\83\8c\83b\83h\8fî\95ñ
1107 }
1108 function TGikoSys.DivideSubject(Line: string): TSubjectRec;
1109 var
1110         i: integer;
1111         ws: WideString;
1112         Delim: string;
1113         LeftK: string;
1114         RightK: string;
1115 begin
1116         Result.FCount := 0;
1117
1118         if AnsiPos('<>', Line) = 0 then
1119                 Delim := ','
1120         else
1121                 Delim := '<>';
1122         Result.FFileName := MojuUtils.RemoveToken(Line, Delim);
1123         Result.FTitle := Trim(MojuUtils.RemoveToken(Line, Delim));
1124
1125         ws := Result.FTitle;
1126         if Copy(ws, Length(ws), 1) = ')' then begin
1127                 LeftK := '(';
1128                 RightK := ')';
1129         end else if Copy(ws, Length(ws)-1, 2) = '\81j' then begin
1130                 LeftK := '\81i';
1131                 RightK := '\81j';
1132         end else if Copy(ws, Length(ws), 1) = '>' then begin
1133                 LeftK := '<';
1134                 RightK := '>';
1135         end;
1136         for i := Length(ws) - 1 downto 1 do begin
1137                 if Copy(ws, i, Length(LeftK)) = LeftK then begin
1138                         Result.FTitle := TrimRight(Copy(ws, 1, i - 1));
1139                         ws := Copy(ws, i + Length(LeftK), Length(ws) - i - Length(RightK));
1140                         if IsNumeric(ws) then
1141                                 Result.FCount := StrToInt(ws);
1142                         //Delete(Result.FTitle, i, Length(LeftK) + Length(ws) + Length(RightK));
1143                         break;
1144                 end;
1145         end;
1146 end;
1147
1148 {!
1149 \brief URL\82©\82çBBSID\82ð\8eæ\93¾
1150 \param url BBSID \82ð\8eæ\93¾\82·\82é URL
1151 \return    BBSID
1152 }
1153 function TGikoSys.UrlToID(url: string): string;
1154 var
1155         i: integer;
1156 begin
1157         Result := '';
1158         url := Trim(url);
1159
1160         if url = '' then Exit;
1161         try
1162                 url := Copy(url, 0, Length(url) - 1);
1163                 for i := Length(url) downto 0 do begin
1164                         if url[i] = '/' then begin
1165                                 Result := Copy(url, i + 1, Length(url));
1166                                 Break;
1167                         end;
1168                 end;
1169         except
1170                 Result := '';
1171         end;
1172 end;
1173
1174 {!
1175 \brief URL\82©\82ç\8dÅ\8cã\82Ì\97v\91f\82ð\8dí\8f\9c
1176 \param url \89ð\8eß\82·\82é URL
1177 \return    \90Ø\82è\8eæ\82ç\82ê\82½\8cã\82Ì URL
1178
1179 URL \82©\82ç BBSID\88È\8aO\82Ì\95\94\95ª\82ð\8eæ\93¾\82·\82é\82Ì\82É\8eg\97p\82µ\82Ü\82·\81B
1180 }
1181 function TGikoSys.UrlToServer(url: string): string;
1182 var
1183         i: integer;
1184         wsURL: WideString;
1185 begin
1186         Result := '';
1187         wsURL := url;
1188         wsURL := Trim(wsURL);
1189
1190         if wsURL = '' then exit;
1191
1192         if Copy(wsURL, Length(wsURL), 1) = '/' then
1193                 wsURL := Copy(wsURL, 0, Length(wsURL) - 1);
1194
1195         for i := Length(wsURL) downto 0 do begin
1196                 if wsURL[i] = '/' then begin
1197                         Result := Copy(wsURL, 0, i);
1198                         break;
1199                 end;
1200         end;
1201 end;
1202
1203 {!
1204 \brief \83f\83B\83\8c\83N\83g\83\8a\82ª\91\8dÝ\82·\82é\82©\83`\83F\83b\83N
1205 \param Name \91\8dÝ\82ð\8am\94F\82·\82é\83t\83H\83\8b\83_\83p\83X
1206 \return     \83t\83H\83\8b\83_\82ª\91\8dÝ\82·\82é\82È\82ç True
1207 }
1208 function TGikoSys.DirectoryExistsEx(const Name: string): Boolean;
1209 var
1210         Code: Cardinal;
1211 begin
1212         Code := GetFileAttributes(PChar(Name));
1213         Result := (Code <> Cardinal(-1)) and (FILE_ATTRIBUTE_DIRECTORY and Code <> 0);
1214 end;
1215
1216 {!
1217 \brief \83f\83B\83\8c\83N\83g\83\8a\8dì\90¬\81i\95¡\90\94\8aK\91w\91Î\89\9e\81j
1218 \param Dir \8dì\90¬\82·\82é\83p\83X
1219 \return    \8dì\90¬\82É\90¬\8c÷\82µ\82½\8fê\8d\87\82Í True
1220 }
1221 function TGikoSys.ForceDirectoriesEx(Dir: string): Boolean;
1222 begin
1223         Result := True;
1224         if Length(Dir) = 0 then
1225                 raise Exception.Create('\83t\83H\83\8b\83_\82ª\8dì\90¬\8fo\97\88\82Ü\82¹\82ñ');
1226         Dir := ExcludeTrailingPathDelimiter(Dir);
1227         if (Length(Dir) < 3) or DirectoryExistsEx(Dir)
1228                 or (ExtractFilePath(Dir) = Dir) then Exit; // avoid 'xyz:\' problem.
1229         Result := ForceDirectoriesEx(ExtractFilePath(Dir)) and CreateDir(Dir);
1230 end;
1231
1232 {!
1233 \brief \95\8e\9a\97ñ\82©\82ç\83g\81[\83N\83\93\82Ì\90Ø\82è\8fo\82µ\81i\8f\89\8aú\8f\88\97\9d\81j
1234                          FDelphi\82©\82ç\82Ì\83p\83N\83\8a
1235 \param s   \8c³\82É\82È\82é\83L\83\83\83\89\83N\83^
1236 \param sep \8bæ\90Ø\82è\82É\82È\82é\95\8e\9a\97ñ
1237 \param Rec OUT:\95\8e\9a\97ñ\91\96\8d¸\8fî\95ñ\82ª\95Ô\82é
1238 \return    \90Ø\82è\8fo\82µ\82½\83g\81[\83N\83\93
1239 \todo Split, RemoveToken, GetTokenIndex, NthField \8ds\82«
1240 }
1241 function TGikoSys.StrTokFirst(const s:string; const sep: TStrTokSeparator; var Rec: TStrTokRec): string;
1242 begin
1243         Rec.Str := s;
1244         Rec.Pos := 1;
1245         Result := StrTokNext(sep, Rec);
1246 end;
1247
1248 {!
1249 \brief \95\8e\9a\97ñ\82©\82ç\83g\81[\83N\83\93\82Ì\90Ø\82è\8fo\82µ
1250                          FDelphi\82©\82ç\82Ì\83p\83N\83\8a
1251 \param sep \8bæ\90Ø\82è\82É\82È\82é\83L\83\83\83\89\83N\83^
1252 \param Rec IN/OUT:StrTokFirst\82Å\8dì\90¬\82³\82ê\82½\95\8e\9a\97ñ\91\96\8d¸\8fî\95ñ
1253 \return    \90Ø\82è\8fo\82µ\82½\83g\81[\83N\83\93
1254 \todo Split, RemoveToken, GetTokenIndex, NthField \8ds\82«
1255 }
1256 function TGikoSys.StrTokNext(const sep: TStrTokSeparator; var Rec: TStrTokRec): string;
1257 var
1258         Len, I: Integer;
1259 begin
1260         with Rec do     begin
1261                 Len := Length(Str);
1262                 Result := '';
1263                 if Len >= Pos then begin
1264                         while (Pos <= Len) and (Str[Pos] in sep) do begin
1265                          Inc(Pos);
1266                         end;
1267                         I := Pos;
1268                         while (Pos<= Len) and not (Str[Pos] in sep) do begin
1269                                 if IsDBCSLeadByte(Byte(Str[Pos])) then begin
1270                                         Inc(Pos);
1271                                 end;
1272                                 Inc(Pos);
1273                         end;
1274                         Result := Copy(Str, I, Pos - I);
1275                         while (Pos <= Len) and (Str[Pos] in sep) do begin// \82±\82ê\82Í\82¨\8dD\82Ý
1276                                 Inc(Pos);
1277                         end;
1278                 end;
1279         end;
1280 end;
1281
1282 {!
1283 \brief \83t\83@\83C\83\8b\83T\83C\83Y\8eæ\93¾
1284 \param FileName \83t\83@\83C\83\8b\83T\83C\83Y\82ð\8eæ\93¾\82·\82é\83t\83@\83C\83\8b\83p\83X
1285 \return         \83t\83@\83C\83\8b\83T\83C\83Y(bytes)
1286 }
1287 function TGikoSys.GetFileSize(FileName : string): longint;
1288 var
1289         F : File;
1290 begin
1291         try
1292                 if not FileExists(FileName) then begin
1293                         Result := 0;
1294                         Exit;
1295                 end;
1296                 Assign(F, FileName);
1297                 Reset(F, 1);
1298                 Result := FileSize(F);
1299                 CloseFile(F);
1300         except
1301                 Result := 0;
1302         end;
1303 end;
1304
1305 {!
1306 \brief \83e\83L\83X\83g\83t\83@\83C\83\8b\82Ì\8ds\90\94\82ð\8eæ\93¾
1307 \param FileName \8ds\90\94\82ð\8eæ\93¾\82·\82é\83t\83@\83C\83\8b\83p\83X
1308 \return         \8ds\90\94
1309 \todo \83\81\83\82\83\8a\83}\83b\83v\83h\83t\83@\83C\83\8b\8ds\82«
1310 }
1311 function TGikoSys.GetFileLineCount(FileName : string): longint;
1312 var
1313         sl: TStringList;
1314 begin
1315         sl := TStringList.Create;
1316         try
1317                 try
1318                         sl.LoadFromFile(FileName);
1319                         Result := sl.Count;
1320                 except
1321                         Result := 0;
1322                 end;
1323         finally
1324                 sl.Free;
1325         end;
1326
1327 end;
1328
1329 {!
1330 \brief \83t\83@\83C\83\8b\82©\82ç\8ew\92è\8ds\82ð\8eæ\93¾
1331 \param FileName \83t\83@\83C\83\8b\82Ì\83p\83X
1332 \param Line     \8ew\92è\8ds
1333 \return         \8ew\92è\82³\82ê\82½ 1 \8ds
1334 \todo \83\81\83\82\83\8a\83}\83b\83v\83h\83t\83@\83C\83\8b\8ds\82«
1335 }
1336 function TGikoSys.ReadThreadFile(FileName: string; Line: Integer): string;
1337 var
1338         fileTmp : TStringList;
1339 begin
1340         Result := '';
1341         if FileExists(FileName) then begin
1342                 fileTmp := TStringList.Create;
1343                 try
1344                         try
1345                                 fileTmp.LoadFromFile( FileName );
1346                                 if ( Line       >= 1 ) and ( Line       < fileTmp.Count + 1 ) then begin
1347                                         Result := fileTmp.Strings[ Line-1 ];
1348                                 end;
1349                         except
1350                                 //on EFOpenError do Result := '';
1351                         end;
1352                 finally
1353                         fileTmp.Free;
1354                 end;
1355         end;
1356 end;
1357
1358 {!
1359 \brief \83V\83X\83e\83\80\83\81\83j\83\85\81[\83t\83H\83\93\83g\82Ì\91®\90«\82ð\8eæ\93¾
1360 \param Font OUT:\8eæ\93¾\82µ\82½\83t\83H\83\93\83g\91®\90«\82ª\95Ô\82é
1361 }
1362 procedure TGikoSys.MenuFont(Font: TFont);
1363 var
1364         lf: LOGFONT;
1365         nm: NONCLIENTMETRICS;
1366 begin
1367         nm.cbSize := sizeof(NONCLIENTMETRICS);
1368     SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, @nm, 0);
1369     lf := nm.lfMenuFont;
1370     Font.Name := lf.lfFaceName;
1371     Font.Height := lf.lfHeight;
1372     Font.Style := [];
1373     if lf.lfWeight >= 700 then
1374         Font.Style := Font.Style + [fsBold];
1375     if lf.lfItalic = 1 then
1376         Font.Style := Font.Style + [fsItalic];
1377 end;
1378
1379 {!
1380 \brief \90æ\93ª\82Ì\83g\81[\83N\83\93\82ð\90Ø\82è\8fo\82µ
1381 \param s         IN/OUT:\8c³\82É\82È\82é\95\8e\9a\97ñ\81A\90Ø\82è\8fo\82µ\82½\8cã\82Ì\8ec\82è\82Ì\95\8e\9a\97ñ
1382 \param delimiter \8bæ\90Ø\82è\82É\82È\82é\95\8e\9a\97ñ
1383 \return          \90Ø\82è\8fo\82µ\82½\95\8e\9a\97ñ
1384
1385 \82Ç\82±\82©\82Ì\83T\83C\83g\82©\82ç\82Ì\83p\83N\83\8a
1386 }
1387 {function TGikoSys.RemoveToken(var s: string;const delimiter: string): string;
1388 var
1389         p: Integer;
1390 begin
1391         p := AnsiPos(delimiter, s);
1392         if p = 0 then
1393                 Result := s
1394         else
1395                 Result := Copy(s, 1, p - 1);
1396         Delete(s, 1, Length(Result) + Length(delimiter));
1397 end;
1398 }
1399
1400 {!
1401 \brief n \8cÂ\96Ú\82Ì\83g\81[\83N\83\93\82ð\90Ø\82è\8fo\82µ
1402 \param s     \8c³\82É\82È\82é\95\8e\9a\97ñ
1403 \param index 0 \82©\82ç\8en\82Ü\82é\83C\83\93\83f\83b\83N\83X(n \8cÂ\96Ú\82Ì n)
1404 \return \90Ø\82è\8fo\82µ\82½\83g\81[\83N\83\93
1405
1406 \82Ç\82±\82©\82Ì\83T\83C\83g\82©\82ç\82Ì\83p\83N\83\8a
1407 }
1408 function TGikoSys.GetTokenIndex(s: string; delimiter: string; index: Integer): string;
1409 var
1410         i: Integer;
1411 begin
1412         Result := '';
1413         for i := 0 to index do
1414                 Result := MojuUtils.RemoveToken(s, delimiter);
1415 end;
1416
1417
1418 //\83C\83\93\83f\83b\83N\83X\96¢\8dX\90V\83o\83b\83t\83@\82ð\83t\83\89\83b\83V\83\85\81I
1419 {procedure TGikoSys.FlashExitWrite;
1420 var
1421         i: Integer;
1422 begin
1423         //\83X\83\8c\83b\83h\83f\81[\83^\83t\83@\83C\83\8b\82ð\8dX\90V
1424         for i := 0 to FExitWrite.Count - 1 do
1425                 WriteThreadDat(FExitWrite[i]);
1426         FExitWrite.Clear;
1427 end;}
1428
1429 {!
1430 \brief \83X\83\8c\96¼\82È\82Ç\82ð\92Z\82¢\96¼\91O\82É\95Ï\8a·\82·\82é
1431 \param LongName \8c³\82É\82È\82é\95\8e\9a\97ñ
1432 \param ALength  \8eû\82ß\82é\95\8e\9a\97ñ\92·(bytes)
1433 \return         \95Ï\8a·\82³\82ê\82½\95\8e\9a\97ñ
1434
1435 from HotZonu
1436 }
1437 function TGikoSys.GetShortName(const LongName: string; ALength: integer): string;
1438 const
1439         ERASECHAR : array [1..39] of string =
1440                 ('\81\99','\81\9a','\81¡','\81 ','\81\9f','\81\9e','\81Q','\81\94','\81£','\81¥',
1441                  '\81¢','\81¤','\81\9c','\81\9b','\81\9d','\81y','\81z','\81ô','\81s','\81t',
1442                  '\81g','\81h','\81k','\81l','\81e','\81f','\81\83','\81\84','\81á','\81â',
1443                  '\81o','\81p','\81q','\81r','\81w','\81x','\81¬','\81c', '\81@');
1444 var
1445         Chr : array [0..255]    of      char;
1446         S : string;
1447         i : integer;
1448 begin
1449         s := Trim(LongName);
1450         if (Length(s) <= ALength) then begin
1451                 Result := s;
1452         end else begin
1453                 S := s;
1454                 for i := Low(ERASECHAR) to      High(ERASECHAR) do      begin
1455                         S := CustomStringReplace(S, ERASECHAR[i], '');
1456                 end;
1457                 if (Length(S) <= ALength) then begin
1458                         Result := S;
1459                 end else begin
1460                         Windows.LCMapString(
1461                                         GetUserDefaultLCID(),
1462                                         LCMAP_HALFWIDTH,
1463                                         PChar(S),
1464                                         Length(S) + 1,
1465                                         chr,
1466                                         Sizeof(chr)
1467                                         );
1468                         S := Chr;
1469                         S := Copy(S,1,ALength);
1470                         while true do begin
1471                                 if (ByteType(S, Length(S)) = mbLeadByte ) then begin
1472                                         S := Copy(S, 1, Length(S) - 1);
1473                                 end else begin
1474                                         Break;
1475                                 end;
1476                         end;
1477                         Result := S;
1478                 end;
1479         end;
1480 end;
1481
1482 {!
1483 \brief Boolean \82ð Integer \82É\95Ï\8a·
1484 \return False..0, True..1
1485 }
1486 function TGikoSys.BoolToInt(b: Boolean): Integer;
1487 begin
1488         Result := IfThen(b, 1, 0);
1489 end;
1490
1491 {!
1492 \brief Integer \82ð Boolean \82É\95Ï\8a·
1493 \return 1..True, other..False
1494 \todo 0..False, other..True \82Ì\95û\82ª\82¢\82¢\82Ì\82Å\82Í?
1495                         (\82±\82Ì\8ed\97l\82É\88Ë\91\82µ\82Ä\82¢\82é\82©\82à\82µ\82ê\82È\82¢\82Ì\82Å\96¢\8fC\90³)
1496 }
1497 function TGikoSys.IntToBool(i: Integer): Boolean;
1498 begin
1499         Result := i = 1;
1500 end;
1501
1502 {!
1503 \brief gzip\82Å\88³\8fk\82³\82ê\82½\82Ì\82ð\96ß\82·
1504 \param ResStream       \93Ç\82Ý\8d\9e\82Þ\83X\83g\83\8a\81[\83\80
1505 \param ContentEncoding \83G\83\93\83R\81[\83f\83B\83\93\83O
1506 \return                \93W\8aJ\82³\82ê\82½\95\8e\9a\97ñ
1507 }
1508 function TGikoSys.GzipDecompress(ResStream: TStream; ContentEncoding: string): string;
1509 const
1510         BUF_SIZE = 4096;
1511 var
1512         GZipStream: TGzipDecompressStream;
1513         TextStream: TStringStream;
1514         buf: array[0..BUF_SIZE - 1] of Byte;
1515         cnt: Integer;
1516         s: string;
1517         i, ln: Integer;
1518 begin
1519         Result := '';
1520         TextStream := TStringStream.Create('');
1521         try
1522 //\83m\81[\83g\83\93\83E\83\93\83`\83E\83B\83\8b\83X2003\91Î\8dô(x-gzip\82Æ\82©\82É\82È\82é\82Ý\82½\82¢)
1523 //              if LowerCase(Trim(ContentEncoding)) = 'gzip' then begin
1524                 if AnsiPos('gzip', LowerCase(Trim(ContentEncoding))) > 0 then begin
1525                         ResStream.Position := 0;
1526                         GZipStream := TGzipDecompressStream.Create(TextStream);
1527                         try
1528                                 repeat
1529                                         FillChar(buf, BUF_SIZE, 0);
1530                                         cnt := ResStream.Read(buf, BUF_SIZE);
1531                                         if cnt > 0 then
1532                                                 GZipStream.Write(buf, BUF_SIZE);
1533                                 until cnt = 0;
1534                         finally
1535                                 GZipStream.Free;
1536                         end;
1537                 end else begin
1538                         ResStream.Position := 0;
1539                         repeat
1540                                 FillChar(buf, BUF_SIZE, 0);
1541                                 cnt := ResStream.Read(buf, BUF_SIZE);
1542                                 if cnt > 0 then
1543                                         TextStream.Write(buf, BUF_SIZE);
1544                         until cnt = 0;
1545                 end;
1546
1547                 //NULL\95\8e\9a\82ð"*"\82É\82·\82é
1548                 s := TextStream.DataString;
1549                 i := Length(s);
1550                 ln := i;
1551                 while (i > 0) and (s[i] = #0) do
1552                         Dec(i);
1553                 Delete(s, i + 1, ln - i);
1554
1555                 i := Pos(#0, s);
1556                 while i <> 0 do begin
1557                         s[i] := '*';
1558                         i := Pos(#0, s);
1559                 end;
1560
1561                 Result := s;
1562         finally
1563                 TextStream.Free;
1564         end;
1565 end;
1566
1567 {!
1568 \brief \83A\83N\83V\83\87\83\93\82É\83V\83\87\81[\83g\83J\83b\83g\83L\81[\82ð\90Ý\92è
1569 \param ActionList \90Ý\92è\82·\82é\83A\83N\83V\83\87\83\93\88ê\97\97
1570 \param FileName Ini\83t\83@\83C\83\8b\82Ì\96¼\91O
1571 }
1572 procedure TGikoSys.LoadKeySetting(ActionList: TActionList; FileName: String);
1573 const
1574         STD_SEC = 'KeySetting';
1575 var
1576         i: Integer;
1577         ini: TMemIniFile;
1578         ActionName: string;
1579         ActionKey: Integer;
1580         SecList: TStringList;
1581         Component: TComponent;
1582 begin
1583         if not FileExists(fileName) then
1584                 Exit;
1585         SecList := TStringList.Create;
1586         ini := TMemIniFile.Create(fileName);
1587         try
1588                 ini.ReadSection(STD_SEC, SecList);
1589                 for i := 0 to SecList.Count - 1 do begin
1590                         ActionName := SecList[i];
1591                         ActionKey := ini.ReadInteger(STD_SEC, ActionName, -1);
1592                         if ActionKey <> -1 then begin
1593                                 Component := ActionList.Owner.FindComponent(ActionName);
1594                                 if TObject(Component) is TAction then begin
1595                                         TAction(Component).ShortCut := ActionKey;
1596                                 end;
1597                         end;
1598                 end;
1599         finally
1600                 ini.Free;
1601                 SecList.Free;
1602         end;
1603 end;
1604
1605 {!
1606 \brief \83A\83N\83V\83\87\83\93\82É\90Ý\92è\82³\82ê\82Ä\82¢\82é\83V\83\87\81[\83g\83J\83b\83g\83L\81[\82ð\83t\83@\83C\83\8b\82É\95Û\91
1607 \param ActionList \95Û\91\82·\82é\83A\83N\83V\83\87\83\93\88ê\97\97
1608 \param FileName Ini\83t\83@\83C\83\8b\96¼
1609
1610 ActionList \82É\90Ý\92è\82³\82ê\82Ä\82¢\82é\83V\83\87\81[\83g\83J\83b\83g\83L\81[\82ð FileName \82É\95Û\91\82µ\82Ü\82·\81B
1611 }
1612 procedure TGikoSys.SaveKeySetting(ActionList: TActionList; FileName: String);
1613 const
1614         STD_SEC = 'KeySetting';
1615 var
1616         i: Integer;
1617         ini: TMemIniFile;
1618 begin
1619         ini := TMemIniFile.Create(GetConfigDir + FileName);
1620         try
1621                 for i := 0 to ActionList.ActionCount - 1 do begin
1622                         if ActionList.Actions[i].Tag = -1 then
1623                                 Continue;
1624                         ini.WriteInteger(STD_SEC, ActionList.Actions[i].Name, TAction(ActionList.Actions[i]).ShortCut);
1625                 end;
1626                 ini.UpdateFile;
1627         finally
1628                 ini.Free;
1629         end;
1630 end;
1631
1632
1633 {!
1634 \brief \83v\83\8d\83Z\83X\82Ì\90\90¬
1635 \param AppPath \8bN\93®\82·\82é\83v\83\8d\83Z\83X\82Ì\83t\83@\83C\83\8b\83p\83X
1636 \param Param   AppPath \82É\93n\82·\88ø\90\94
1637 }
1638 procedure TGikoSys.CreateProcess(const AppPath: string; const Param: string);
1639 var
1640         PI: TProcessInformation;
1641         SI: TStartupInfo;
1642         Path: string;
1643 begin
1644         Path := '"' + AppPath + '"';
1645         if Param <> '' then
1646                 Path := Path + ' ' + Param;
1647
1648         SI.Cb := SizeOf(Si);
1649         SI.lpReserved   := nil;
1650         SI.lpDesktop     := nil;
1651         SI.lpTitle               := nil;
1652         SI.dwFlags               := 0;
1653         SI.cbReserved2 := 0;
1654         SI.lpReserved2 := nil;
1655         SI.dwysize               := 0;
1656     if Windows.CreateProcess(nil,
1657                                                                 PChar(Path),
1658                                                                 nil,
1659                                                                 nil,
1660                                                                 False,
1661                                                                 0,
1662                                                                 nil,
1663                                                                 nil,
1664                                                                 SI,
1665                                                                 PI) then
1666     begin
1667         CloseHandle(PI.hProcess);
1668     end;
1669
1670 end;
1671
1672 {!
1673 \brief Web \83u\83\89\83E\83U\82ð\8bN\93®
1674 \param URL         Web \83u\83\89\83E\83U\82Å\95\\8e¦\82·\82é URL
1675 \param BrowserType \83u\83\89\83E\83U\82Ì\83^\83C\83v(IE \82©\82Ç\82¤\82©)
1676 }
1677 procedure TGikoSys.OpenBrowser(URL: string; BrowserType: TGikoBrowserType);
1678 var
1679     i, j : Integer;
1680     path, arg : String;
1681     params : TStringList;
1682 begin
1683         case BrowserType of
1684                 gbtIE:
1685                         HlinkNavigateString(nil, PWideChar(WideString(URL)));
1686                 gbtUserApp, gbtAuto:
1687                         if (Setting.URLApp) then begin
1688                 if (FileExists(Setting.URLAppFile)) then begin
1689                                 GikoSys.CreateProcess(Setting.URLAppFile, URL)
1690                 end else begin
1691                     // \8bN\93®\83p\83\89\83\81\81[\83^\95t\82«\91Î\8dô
1692                     path := '';
1693                     params := TStringList.Create;
1694                     try
1695                         params.Delimiter := ' ';
1696                         params.DelimitedText := Setting.URLAppFile;
1697                         for i := 0 to params.Count - 1 do begin
1698                             path := TrimLeft(path + ' ' + params[i]);
1699                             if (FileExists(path)) then begin
1700                                 arg := '';
1701                                 for j := i + 1 to params.Count - 1 do begin
1702                                     arg := arg + ' ' + params[j];
1703                                 end;
1704                                 break;
1705                             end;
1706                         end;
1707                         if i < params.Count then begin
1708                             GikoSys.CreateProcess(path, arg + ' ' + URL);
1709                         end else begin
1710                             HlinkNavigateString(nil, PWideChar(WideString(URL)));
1711                         end;
1712                     finally
1713                         params.Free;
1714                     end;
1715                 end;
1716                         end else
1717                                 HlinkNavigateString(nil, PWideChar(WideString(URL)));
1718         end;
1719 end;
1720
1721 {!
1722 \brief \95\8e\9a\8eÀ\91Ì\8eQ\8fÆ\82ð\83f\83R\81[\83h
1723 \param AStr \83f\83R\81[\83h\82·\82é\95\8e\9a\97ñ
1724 \return     \83f\83R\81[\83h\82³\82ê\82½\95\8e\9a\97ñ
1725 }
1726 function TGikoSys.HTMLDecode(const AStr: String): String;
1727 var
1728         Sp, Rp, Cp, Tp: PChar;
1729         S: String;
1730         I, Code: Integer;
1731         Num: Boolean;
1732 begin
1733         SetLength(Result, Length(AStr));
1734         Sp := PChar(AStr);
1735         Rp := PChar(Result);
1736         //Cp := Sp;
1737         try
1738                 while Sp^ <> #0 do begin
1739                         case Sp^ of
1740                                 '&': begin
1741                                                          //Cp := Sp;
1742                                                          Inc(Sp);
1743                                                          case Sp^ of
1744                                                                  'a': if AnsiStrPos(Sp, 'amp;') = Sp then
1745                                                                                         begin
1746                                                                                                 Inc(Sp, 3);
1747                                                                                                 Rp^ := '&';
1748                                                                                         end;
1749                                                                  'l',
1750                                                                  'g': if (AnsiStrPos(Sp, 'lt;') = Sp) or (AnsiStrPos(Sp, 'gt;') = Sp) then
1751                                                                                         begin
1752                                                                                                 Cp := Sp;
1753                                                                                                 Inc(Sp, 2);
1754                                                                                                 while (Sp^ <> ';') and (Sp^ <> #0) do
1755                                                                                                         Inc(Sp);
1756                                                                                                 if Cp^ = 'l' then
1757                                                                                                         Rp^ := '<'
1758                                                                                                 else
1759                                                                                                         Rp^ := '>';
1760                                                                                         end;
1761                                                                  'q': if AnsiStrPos(Sp, 'quot;') = Sp then
1762                                                                                         begin
1763                                                                                                 Inc(Sp,4);
1764                                                                                                 Rp^ := '"';
1765                                                                                         end;
1766                                                                  '#': begin
1767                                                                                                 Tp := Sp;
1768                                                                                                 Inc(Tp);
1769                                                                                                 Num := IsNumeric(Copy(Tp, 1, 1));
1770                                                                                                 while (Sp^ <> ';') and (Sp^ <> #0) do begin
1771                                                                                                         if (Num) and (not IsNumeric(Copy(Sp, 1, 1))) then
1772                                                                                                                 Break;
1773                                                                                                         Inc(Sp);
1774                                                                                                 end;
1775                                                                                                 SetString(S, Tp, Sp - Tp);
1776                                                                                                 Val(S, I, Code);
1777                                                                                                 Rp^ := Chr((I));
1778                                                                                         end;
1779                                                          //      else
1780                                                                          //raise EConvertError.CreateFmt(sInvalidHTMLEncodedChar,
1781                                                                                  //[Cp^ + Sp^, Cp - PChar(AStr)])
1782                                                          end;
1783                                          end
1784                         else
1785                                 Rp^ := Sp^;
1786                         end;
1787                         Inc(Rp);
1788                         Inc(Sp);
1789                 end;
1790         except
1791 //              on E:EConvertError do
1792 //                      raise EConvertError.CreateFmt(sInvalidHTMLEncodedChar,
1793 //                              [Cp^ + Sp^, Cp - PChar(AStr)])
1794         end;
1795         SetLength(Result, Rp - PChar(Result));
1796 end;
1797
1798 {!
1799 \brief HTML \82Ì\83A\83\93\83J\81[\83^\83O\82©\82ç URL \82ð\8eæ\93¾
1800 \param s URL \82ð\8eæ\93¾\82·\82é HTML
1801 \return  \8eæ\93¾\82µ\82½ URL
1802 }
1803 function TGikoSys.GetHRefText(s: string): string;
1804 var
1805         Index: Integer;
1806         Index2: Integer;
1807 begin
1808         Result := '';
1809         s := Trim(s);
1810         if s = '' then
1811                 Exit;
1812
1813         Index := AnsiPos('href', LowerCase(s));
1814         if Index = 0 then
1815                 Exit;
1816         s := Trim(Copy(s, Index + 4, Length(s)));
1817         s := Trim(Copy(s, 2, Length(s)));
1818
1819         //\8en\82ß\82Ì\95\8e\9a\82ª'"'\82È\82ç\8eæ\82è\8f\9c\82­
1820         //if Copy(s, 1, 1) = '"' then begin
1821     if s[1]  = '"' then begin
1822                 s := Trim(Copy(s, 2, Length(s)));
1823         end;
1824
1825         Index := AnsiPos('"', s);
1826         if Index <> 0 then begin
1827                 //'"'\82Ü\82ÅURL\82Æ\82·\82é
1828                 s := Copy(s, 1, Index - 1);
1829         end else begin
1830                 //'"'\82ª\96³\82¯\82ê\82Î\83X\83y\81[\83X\82©">"\82Ì\91\81\82¢\95û\82Ü\82Å\82ðURL\82Æ\82·\82é
1831                 Index := AnsiPos(' ', s);
1832                 Index2 := AnsiPos('>', s);
1833                 if Index = 0 then
1834                         Index := Index2;
1835                 if Index > Index2 then
1836                         Index := Index2;
1837                 if Index <> 0 then
1838                         s := Copy(s, 1, Index - 1)
1839                 else
1840                         //\82±\82ê\88È\8fã\82à\82¤\92m\82ç\82ñ\82Ê
1841                         ;
1842         end;
1843         Result := Trim(s);
1844 end;
1845
1846 {!
1847 \brief \83z\83X\83g\96¼\82ª\82Q\82\83\82\88\82©\82Ç\82¤\82©\83`\83F\83b\83N\82·\82é
1848 \param Host \83`\83F\83b\83N\82·\82é\83z\83X\83g\96¼
1849 \return     2\82¿\82á\82ñ\82Ë\82é\82Ì\83z\83X\83g\96¼\82È\82ç True
1850 }
1851 function TGikoSys.Is2chHost(Host: string): Boolean;
1852 const
1853         HOST_NAME: array[0..1] of string = ('.2ch.net', '.bbspink.com');
1854 var
1855         i: Integer;
1856 //      Len: Integer;
1857 begin
1858         Result := False;
1859         if RightStr( Host, 1 ) = '/' then
1860                 Host := Copy( Host, 1, Length( Host ) - 1 );
1861         OutputDebugString(pchar(HOST_NAME[0]));
1862         for i := 0 to Length(HOST_NAME) - 1 do begin
1863 //              Len := Length(HOST_NAME[i]);
1864                 if (AnsiPos(HOST_NAME[i], Host) > 0) and
1865                         (AnsiPos(HOST_NAME[i], Host) = (Length(Host) - Length(HOST_NAME[i]) + 1)) then begin
1866                         Result := True;
1867                         Exit;
1868                 end;
1869         end;
1870 end;
1871
1872 {!
1873 \brief 2\82¿\82á\82ñ\82Ë\82é\8c`\8e®\82Ì URL \82ð\95ª\89ð
1874 \param url      2\82¿\82á\82ñ\82Ë\82é\8c`\8e®\82Ì URL
1875 \param path     test/read.cgi \82È\82Ç\82Ì\92\86\8aÔ\83p\83X(ParseURI \82©\82ç\93¾\82é)
1876 \param document index.html \82È\82Ç\82Ì\83h\83L\83\85\83\81\83\93\83g\96¼(ParseURI \82©\82ç\93¾\82é)
1877 \param BBSID    OUT:BBSID \82ª\95Ô\82é(ex. giko)
1878 \param BBSKey   OUT:\83X\83\8c\83b\83h\83L\81[\82ª\95Ô\82é(ex. 10000000000)
1879 \return 2\82¿\82á\82ñ\82Ë\82é\82Ì URL \82Æ\82µ\82Ä\95ª\89ð\82Å\82«\82½\82È\82ç True
1880 }
1881 function TGikoSys.Parse2chURL(const url: string; const path: string; const document: string; var BBSID: string; var BBSKey: string): Boolean;
1882 var
1883         Index: Integer;
1884         s: string;
1885         SList: TStringList;
1886 begin
1887         BBSID := '';
1888         BBSKey := '';
1889         Result := False;
1890
1891         Index := AnsiPos(READ_PATH, path);
1892         if Index <> 0 then begin
1893                 s := Copy(path, Index + Length(READ_PATH), Length(path));
1894     end else begin
1895         Index := AnsiPos(HTML_READ_PATH, path);
1896         if Index <> 0 then begin
1897             s := Copy(path, Index + Length(HTML_READ_PATH), Length(path));
1898         end;
1899     end;
1900     if Index <> 0 then begin
1901                 if (Length(s) > 0) and (s[1] = '/') then
1902                         Delete(s, 1, 1);
1903                 BBSID := GetTokenIndex(s, '/', 0);
1904                 BBSKey := GetTokenIndex(s, '/', 1);
1905                 if BBSKey = '' then
1906                         BBSKey := Document;
1907                 Result := (BBSID <> '') or (BBSKey <> '');
1908                 Exit;
1909         end;
1910         Index := AnsiPos(KAKO_PATH, path);
1911         if Index <> 0 then begin
1912                 s := Copy(path, 2, Length(path));
1913                 BBSID := GetTokenIndex(s, '/', 0);
1914                 if (BBSID = 'log') and (GetTokenIndex(s, '/', 2) = 'kako') then
1915                         BBSID := GetTokenIndex(s, '/', 1);
1916                 BBSKey := ChangeFileExt(Document, '');
1917                 Result := (BBSID <> '') or (BBSKey <> '');
1918                 Exit;
1919         end;
1920         Index := AnsiPos('read.cgi?', URL);
1921         if Index <> 0 then begin
1922                 SList := TStringList.Create;
1923                 try
1924                         try
1925 //                              s := HTMLDecode(Document);
1926                                 ExtractHTTPFields(['?', '&'], [], PChar(URL), SList, False);
1927                                 BBSID := SList.Values['bbs'];
1928                                 BBSKey := SList.Values['key'];
1929                                 Result := (BBSID <> '') or (BBSKey <> '');
1930                                 Exit;
1931                         except
1932                                 Exit;
1933                         end;
1934                 finally
1935                         SList.Free;
1936                 end;
1937         end;
1938 end;
1939
1940 {!
1941 \brief 2ch \8c`\8e®\82Ì URL \82©\82ç\83\8c\83X\94Ô\82ð\8eæ\93¾
1942 \param URL    2\82¿\82á\82ñ\82Ë\82é\8c`\8e®\82Ì URL
1943 \param stRes  OUT:\8aJ\8en\83\8c\83X\94Ô\82ª\95Ô\82é
1944 \param endRes OUT:\8fI\97¹\83\8c\83X\94Ô\82ª\95Ô\82é
1945
1946 http://2ch.net/\92\86\97ª/32-50 \n
1947 \82Ì\8fê\8d\87 stRef = 32, endRes = 50 \82É\82È\82é
1948 }
1949 procedure TGikoSys.GetPopupResNumber(URL : string; var stRes, endRes : Int64);
1950 const
1951     START_NAME : array[0..1] of String = ('st=', 'start=');
1952     END_NAME : array[0..1] of String = ('to=', 'end=');
1953     RES_NAME : array[0..0] of String = ('res=');
1954 var
1955         buf : String;
1956         convBuf : String;
1957         ps : Int64;
1958         pch : PChar;
1959     bufList : TStringList;
1960     i, j, idx : Integer;
1961 begin
1962         URL := Trim(LowerCase(URL));
1963     for i := 0 to Length(START_NAME) -1 do begin
1964         idx := AnsiPos(START_NAME[i], URL);
1965         if (idx <> 0) then begin
1966             break;
1967         end;
1968         idx := AnsiPos(END_NAME[i], URL);
1969         if (idx <> 0) then begin
1970             break;
1971         end;
1972
1973     end;
1974
1975     if (idx <> 0) then begin
1976         idx := AnsiPos('?', URL);
1977         if (idx = 0) then begin
1978             idx := LastDelimiter('/', URL);
1979         end;
1980         stRes := 0;
1981         endRes := 0;
1982         bufList := TStringList.Create();
1983         try
1984             bufList.Delimiter := '&';
1985             bufList.DelimitedText := Copy(URL, idx + 1, Length(URL));
1986             for  i := 0 to bufList.Count - 1 do begin
1987                 convBuf := '';
1988                 // \8aJ\8en\83\8c\83X\94Ô\82Ì\8c\9f\8dõ
1989                 if (stRes = 0) then begin
1990                     for j := 0 to Length(START_NAME) - 1 do begin
1991                         idx := AnsiPos(START_NAME[j], bufList[i]);
1992                         if (idx = 1) then begin
1993                             convBuf := Copy(bufList[i], idx + Length(START_NAME[j]), Length(bufList[i]));
1994                             stRes := StrToInt64Def( convBuf, 0 );
1995                             break;
1996                         end;
1997                     end;
1998                 end;
1999                 // \8fI\97¹\83\8c\83X\94Ô\82Ì\8c\9f\8dõ
2000                 if (convBuf = '') and (endRes = 0) then begin
2001                     for j := 0 to Length(END_NAME) - 1 do begin
2002                         idx := AnsiPos(END_NAME[j], bufList[i]);
2003                         if (idx = 1) then begin
2004                             convBuf := Copy(bufList[i], idx + Length(END_NAME[j]), Length(bufList[i]));
2005                             endRes := StrToInt64Def( convBuf, 0 );
2006                             break;
2007                         end;
2008                     end;
2009                 end;
2010                 // \83\8c\83X\94Ô\82Ì\8c\9f\8dõ
2011                 if ((stRes = 0) and (endRes = 0) and (convBuf = '')) then begin
2012                   for j := 0 to Length(RES_NAME) - 1 do begin
2013                       idx := AnsiPos(RES_NAME[j], bufList[i]);
2014                       if (idx = 1) then begin
2015                           convBuf := Copy(bufList[i], idx + Length(RES_NAME[j]), Length(bufList[i]));
2016                           stRes := StrToInt64Def( convBuf, 0 );
2017                           endRes := stRes;
2018                           break;
2019                       end;
2020                   end;
2021                 end;
2022             end;
2023
2024             if (stRes <> 0) and (endRes = 0) then begin
2025                         endRes := stRes + MAX_POPUP_RES;
2026                 end else if (stRes = 0) and (endRes <> 0) then begin
2027                 stRes := endRes - MAX_POPUP_RES;
2028                         if stRes < 1 then begin
2029                                 stRes := 1;
2030                 end;
2031             end;
2032         finally
2033             bufList.clear;
2034             bufList.free;
2035         end;
2036     end else if ( AnsiPos('.html',URL) <> Length(URL) -4 ) and ( AnsiPos('.htm',URL) <> Length(URL) -3 ) then begin
2037                 buf := Copy(URL, LastDelimiter('/',URL)+1,Length(URL)-LastDelimiter('/',URL)+1);
2038                 if  Length(buf) > 0 then begin
2039                         if AnsiPos('-', buf) = 1 then begin
2040                                 stRes := 0;
2041                                 Delete(buf,1,1);
2042                                 ps := 0;
2043                                 pch := PChar(buf);
2044                                 while  ( ps < Length(buf) )and ( pch[ps] >= '0' ) and ( pch[ps] <= '9' ) do Inc(ps);
2045                 convBuf := Copy( buf, 1, ps );
2046                 if convBuf <> '' then begin
2047                     endRes := StrToInt64Def(convBuf, 0);
2048                 end;
2049                                 if endRes <> 0 then begin
2050                                         stRes := endRes - MAX_POPUP_RES;
2051                                         if stRes < 1 then
2052                                                 stRes := 1;
2053                                 end;
2054                         end else begin
2055                                 ps := 0;
2056                                 pch := PChar(buf);
2057                                 while  ( ps < Length(buf) )and ( pch[ps] >= '0' ) and ( pch[ps] <= '9' ) do Inc(ps);
2058                                 try
2059                                         convBuf := Copy( buf, 1, ps );
2060                                         if convBuf <> '' then begin
2061                                                 stRes := StrToInt64(convBuf);
2062                                                 Delete(buf,1,ps+1);
2063                                                 ps := 0;
2064                                                 pch := PChar(buf);
2065                                                 while  ( ps < Length(buf) )and ( pch[ps] >= '0' ) and ( pch[ps] <= '9' ) do Inc(ps);
2066                         convBuf := Copy( buf, 1, ps );
2067                         if convBuf <> '' then begin
2068                             endRes := StrToInt64Def(convBuf, 0);
2069                         end;
2070                                         end else begin
2071                                                 stRes := 0;
2072                                         end;
2073                                 except
2074                                         stRes := 0;
2075                                         endRes := 0;
2076                                 end;
2077                         end;
2078                 end;
2079         end;
2080 end;
2081
2082 {!
2083 \brief 2\82¿\82á\82ñ\82Ë\82é\8c`\8e®\82Ì URL \82ð\95ª\89ð
2084 \param URL 2\82¿\82á\82ñ\82Ë\82é\8c`\8e®\82Ì URL
2085 \return    \95ª\89ð\82³\82ê\82½\97v\91f
2086 }
2087 function TGikoSys.Parse2chURL2(URL: string): TPathRec;
2088 var
2089         i: Integer;
2090         s: string;
2091 //      buf : String;
2092 //      convBuf : String;
2093         wk: string;
2094         wkMin: Integer;
2095         wkMax: Integer;
2096         wkInt: Integer;
2097         RStart: Integer;
2098         RLength: Integer;
2099 //      ps : Integer;
2100 //      pch : PChar;
2101         SList: TStringList;
2102 begin
2103         URL := Trim(LowerCase(URL));
2104         Result.FBBS := '';
2105         Result.FKey := '';
2106         Result.FSt := 0;
2107         Result.FTo := 0;
2108         Result.FFirst := False;
2109         Result.FStBegin := False;
2110         Result.FToEnd := False;
2111         Result.FDone := False;
2112         Result.FNoParam := False;
2113
2114         wkMin := 0;
2115         wkMax := 1;
2116         if URL[length(URL)] = '\' then
2117                 URL := URL + 'n';
2118         FAWKStr.RegExp := 'http://.+\.(2ch\.net|bbspink\.com)/';
2119         if FAWKStr.Match(FAWKStr.ProcessEscSeq(URL), RStart, RLength) <> 0 then begin
2120                 s := Copy(URL, RStart + RLength - 1, Length(URL));
2121
2122                 //\95W\8f\80\8f\91\8e®
2123                 //\8dÅ\8cã\82Íl50, 10, 10-20, 10n, 10-20n, -10, 10-, 10n- \82È\82Ç
2124                 //http://xxx.2ch.net/test/read.cgi/bbsid/1000000000/
2125                 FAWKStr.RegExp := '/test/read.(cgi|html)/.+/[0-9]+/?.*';
2126                 if FAWKStr.Match(FAWKStr.ProcessEscSeq(s), RStart, RLength) > 0 then begin
2127                         s := Copy(s, 15, Length(s));
2128
2129                         SList := TStringList.Create;
2130                         try
2131                                 SList.Clear;
2132                                 FAWKStr.RegExp := '/';
2133                                 if FAWKStr.Split(FAWKStr.ProcessEscSeq(s), SList) >= 3 then begin
2134                                         Result.FBBS := SList[1];
2135                                         Result.FKey := SList[2];
2136                                         if SList.Count >= 4 then
2137                                                 s := SList[3]
2138                                         else begin
2139                                                 s := '';
2140                                                 Result.FNoParam := true;
2141                                         end;
2142                                 end else
2143                                         Exit;
2144
2145                                 SList.Clear;
2146                                 FAWKStr.LineSeparator := mcls_CRLF;
2147                                 FAWKStr.RegExp := '-';
2148                                 if FAWKStr.Split(FAWKStr.ProcessEscSeq(s), SList) = 0 then begin
2149                                         Result.FFirst := True;
2150                                 end else begin
2151                                         FAWKStr.RegExp := 'l[0-9]+';
2152                                         if FAWKStr.Match(FAWKStr.ProcessEscSeq(s), RStart, RLength) > 0 then begin
2153                                                 Result.FFirst := True;
2154                                         end else begin
2155                                                 for i := 0 to SList.Count - 1 do begin
2156                                                         if Trim(SList[i]) = '' then begin
2157                                                                 if i = 0 then
2158                                                                         Result.FStBegin := True;
2159                                                                 if i = (SList.Count - 1) then
2160                                                                         Result.FToEnd := True;
2161                                                         end else if IsNumeric(SList[i]) then begin
2162                                                                 wkInt := StrToInt(SList[i]);
2163                                                                 wkMax := Max(wkMax, wkInt);
2164                                                                 if wkMin = 0 then
2165                                                                         wkMin := wkInt
2166                                                                 else
2167                                                                         wkMin := Min(wkMin, wkInt);
2168                                                         end else if Trim(SList[i]) = 'n' then begin
2169                                                                 Result.FFirst := True;
2170                                                         end else begin
2171                                                                 FAWKStr.RegExp := '^n[0-9]+$|^[0-9]+n$';
2172                                                                 if FAWKStr.Match(FAWKStr.ProcessEscSeq(SList[i]), RStart, RLength) > 0 then begin
2173                                                                         if Copy(SList[i], 1, 1) = 'n' then
2174                                                                                 wkInt := StrToInt(Copy(SList[i], 2, Length(SList[i])))
2175                                                                         else
2176                                                                                 wkInt := StrToInt(Copy(SList[i], 1, Length(SList[i]) - 1));
2177                                                                         Result.FFirst := True;
2178                                                                         wkMax := Max(wkMax, wkInt);
2179                                                                         if wkMin = 1 then
2180                                                                                 wkMin := wkInt
2181                                                                         else
2182                                                                                 wkMin := Min(wkMin, wkInt);
2183                                                                 end;
2184                                                         end;
2185                                                 end;
2186                                                 if Result.FStBegin and (not Result.FToEnd) then
2187                                                         Result.FSt := wkMin
2188                                                 else if (not Result.FStBegin) and Result.FToEnd then
2189                                                         Result.FTo := wkMax
2190                                                 else if (not Result.FStBegin) and (not Result.FToEnd) then begin
2191                                                         Result.FSt := wkMin;
2192                                                         Result.FTo := wkMax;
2193                                                 end;
2194                                                 //Result.FSt := wkMin;
2195                                                 //Result.FTo := wkMax;
2196                                         end;
2197                                 end;
2198                         finally
2199                                 SList.Free;
2200                         end;
2201                         Result.FDone := True;
2202                         Exit;
2203                 end;
2204
2205                 //\90Vkako\8f\91\8e®
2206                 //http://server.2ch.net/ITA_NAME/kako/1000/10000/1000000000.html
2207                 FAWKStr.RegExp := '/.+/kako/[0-9]+/[0-9]+/[0-9]+\.html';
2208                 if FAWKStr.Match(FAWKStr.ProcessEscSeq(s), RStart, RLength) > 0 then begin
2209                         SList := TStringList.Create;
2210                         try
2211                                 SList.Clear;
2212                                 FAWKStr.RegExp := '/';
2213                                 if FAWKStr.Split(FAWKStr.ProcessEscSeq(s), SList) >= 6 then begin
2214                                         Result.FBBS := SList[1];
2215                                         Result.FKey := ChangeFileExt(SList[5], '');
2216                                         Result.FFirst := True;
2217                                 end else
2218                                         Exit;
2219                         finally
2220                                 SList.Free;
2221                         end;
2222                         Result.FDone := True;
2223                         Exit;
2224                 end;
2225
2226                 //\8b\8ckako\8f\91\8e®
2227                 //http://server.2ch.net/ITA_NAME/kako/999/999999999.html
2228                 FAWKStr.RegExp := '/.+/kako/[0-9]+/[0-9]+\.html';
2229                 if FAWKStr.Match(FAWKStr.ProcessEscSeq(s), RStart, RLength) > 0 then begin
2230                         SList := TStringList.Create;
2231                         try
2232                                 SList.Clear;
2233                                 FAWKStr.RegExp := '/';
2234                                 if FAWKStr.Split(FAWKStr.ProcessEscSeq(s), SList) >= 5 then begin
2235                                         Result.FBBS := SList[1];
2236                                         Result.FKey := ChangeFileExt(SList[4], '');
2237                                         Result.FFirst := True;
2238                                 end else
2239                                         Exit;
2240                         finally
2241                                 SList.Free;
2242                         end;
2243                         Result.FDone := True;
2244                         Exit;
2245                 end;
2246
2247                 //log\8by\82Ñlog2\8f\91\8e®
2248                 //http://server.2ch.net/log/ITA_NAME/kako/999/999999999.html
2249                 //http://server.2ch.net/log2/ITA_NAME/kako/999/999999999.html
2250                 FAWKStr.RegExp := '/log2?/.+/kako/[0-9]+/[0-9]+\.html';
2251                 if FAWKStr.Match(FAWKStr.ProcessEscSeq(s), RStart, RLength) > 0 then begin
2252                         SList := TStringList.Create;
2253                         try
2254                                 SList.Clear;
2255                                 FAWKStr.RegExp := '/';
2256                                 if FAWKStr.Split(FAWKStr.ProcessEscSeq(s), SList) >= 6 then begin
2257                                         Result.FBBS := SList[2];
2258                                         Result.FKey := ChangeFileExt(SList[5], '');
2259                                         Result.FFirst := True;
2260                                 end else
2261                                         Exit;
2262                         finally
2263                                 SList.Free;
2264                         end;
2265                         Result.FDone := True;
2266                         Exit;
2267                 end;
2268
2269
2270                 //\8b\8cURL\8f\91\8e®
2271                 //http://server.2ch.net/test/read.cgi?bbs=ITA_NAME&key=1000000000&st=1&to=5&nofirst=true
2272                 FAWKStr.RegExp := '/test/read\.cgi\?';
2273                 if FAWKStr.Match(FAWKStr.ProcessEscSeq(s), RStart, RLength) > 0 then begin
2274                         s := Copy(s, 16, Length(s));
2275                         SList := TStringList.Create;
2276                         try
2277                                 SList.Clear;
2278                                 FAWKStr.RegExp := '&';
2279                                 if FAWKStr.Split(FAWKStr.ProcessEscSeq(s), SList) >= 2 then begin
2280                                         Result.FFirst := True;
2281                                         for i := 0 to SList.Count - 1 do begin
2282                                                 if Pos('bbs=', SList[i]) = 1 then begin
2283                                                         Result.FBBS := Copy(SList[i], 5, Length(SList[i]));
2284                                                 end else if Pos('key=', SList[i]) = 1 then begin
2285                                                         Result.FKey := Copy(SList[i], 5, Length(SList[i]));
2286                                                 end else if Pos('st=', SList[i]) = 1 then begin
2287                                                         wk := Copy(SList[i], 4, Length(SList[i]));
2288                                                         if IsNumeric(wk) then
2289                                                                 Result.FSt := StrToInt(wk)
2290                                                         else if wk = '' then
2291                                                                 Result.FStBegin := True;
2292                                                 end else if Pos('to=', SList[i]) = 1 then begin
2293                                                         wk := Copy(SList[i], 4, Length(SList[i]));
2294                                                         if IsNumeric(wk) then
2295                                                                 Result.FTo := StrToInt(wk)
2296                                                         else if wk = '' then
2297                                                                 Result.FToEnd := True;
2298                                                 end else if Pos('nofirst=', SList[i]) = 1 then begin
2299                                                         Result.FFirst := False;
2300                                                 end;
2301                                         end;
2302                                 end else
2303                                         Exit;
2304                         finally
2305                                 SList.Free;
2306                         end;
2307
2308                         if (Result.FBBS <> '') and (Result.FKey <> '') then begin
2309                                 Result.FDone := True;
2310                         end;
2311                         Exit;
2312                 end;
2313         end;
2314 end;
2315
2316 {!
2317 \brief URI \82ð\95ª\89ð
2318 \param URL      \95ª\89ð\82·\82é URI
2319 \param Protocol OUT:\83v\83\8d\83g\83R\83\8b\82ª\95Ô\82é(ex. http)
2320 \param Host     OUT:\83z\83X\83g\82ª\95Ô\82é(ex. hoge.com)
2321 \param Path     OUT:\92\86\8aÔ\83p\83X\82ª\95Ô\82é(ex. test/read.cgi)
2322 \param Document OUT:\83h\83L\83\85\83\81\83\93\83g\96¼\82ª\95Ô\82é(ex. index.html)
2323 \param Port     OUT:\83|\81[\83g\82ª\95Ô\82é(ex. 8080)
2324 \param Bookmark OUT:\83u\83b\83N\83}\81[\83N(?)\82ª\95Ô\82é
2325 }
2326 procedure TGikoSys.ParseURI(const URL : string; var Protocol, Host, Path, Document, Port, Bookmark: string);
2327 var
2328         URI: TIdURI;
2329 begin
2330         Protocol := '';
2331         Host := '';
2332         Path := '';
2333         Document := '';
2334         Port := '';
2335         Bookmark := '';
2336         URI := TIdURI.Create(URL);
2337         try
2338                 Protocol := URI.Protocol;
2339                 Host := URI.Host;
2340                 Path := URI.Path;
2341                 Document := URI.Document;
2342                 Port := URI.Port;
2343                 Bookmark := URI.Bookmark;
2344         finally
2345                 URI.Free;
2346         end;
2347 end;
2348
2349 {!
2350 \brief \83M\83R\83i\83r\82Ì\83o\81[\83W\83\87\83\93\82ð\8eæ\93¾
2351 \return \83o\81[\83W\83\87\83\93\82Ì\89º 2 \8c\85(dwFileVersionLS)
2352 }
2353 function TGikoSys.GetVersionBuild: Integer;
2354 var
2355         FixedFileInfo: PVSFixedFileInfo;
2356         VersionHandle, VersionSize: DWORD;
2357         pVersionInfo: Pointer;
2358         ItemLen : UInt;
2359         AppFile: string;
2360 begin
2361         Result := 0;
2362         AppFile := Application.ExeName;
2363         VersionSize := GetFileVersionInfoSize(pChar(AppFile), VersionHandle);
2364         if VersionSize = 0 then
2365                 Exit;
2366         GetMem(pVersionInfo, VersionSize);
2367         try
2368                 if GetFileVersionInfo(PChar(AppFile),VersionHandle,VersionSize, pVersionInfo) then
2369                         if VerQueryValue(pVersionInfo, '\', Pointer(FixedFileInfo), ItemLen) then
2370                                 Result := LOWORD(FixedFileInfo^.dwFileVersionLS);
2371         finally
2372                 FreeMem(pVersionInfo, VersionSize);
2373         end;
2374 end;
2375
2376 {!
2377 \brief \83X\83\8c\83b\83h URL \82Ì\90³\8bK\89»
2378 \param inURL \90³\8bK\89»\82·\82é\83X\83\8c\83b\83h URL
2379 \return      \90³\8bK\89»\82³\82ê\82½\83X\83\8c\83b\83h URL
2380
2381 \83X\83\8c\83b\83h URL \82ð\83M\83R\83i\83r\82Ì\92\86\82Å\88ê\88Ó\82È\82à\82Ì\82É\90³\8bK\89»\82µ\82Ü\82·\81B
2382 \88ê\88Ó\82È URL \82É\82·\82é\8e\96\82Å\81AURL \82©\82ç\83X\83\8c\83b\83h\82ð\93±\82«\8fo\82·\8dì\8bÆ\82ð\8dÅ\93K\89»\82µ\82Ü\82·\81B\n
2383 \90³\8bK\89»\82Ì\95û\90j\82Æ\82µ\82Ä\81A\83T\83C\83g\82ª\90\84\8f§\82·\82é\83f\83t\83H\83\8b\83g\82Ì URL \82É\82È\82é\82æ\82¤\82É\90S\82ª\82¯\82Ü\82·\81B
2384 (1-1000 \82Ì\82æ\82¤\82È\95\89\89×\82ð\82©\82¯\82é\82à\82Ì\82É\82Í\82µ\82È\82¢\82±\82Æ)
2385
2386 \97á(\90³\8bK\89»\91O):\n
2387 http://\92\86\97ª/ \n
2388 http://\92\86\97ª/20-100
2389
2390 (\90³\8bK\89»\8cã):\n
2391 http://\92\86\97ª/l50
2392 }
2393 function        TGikoSys.GetBrowsableThreadURL(
2394         inURL : string
2395 ) : string;
2396 var
2397         threadItem      : TThreadItem;
2398         boardPlugIn     : TBoardPlugIn;
2399     board               : TBoard;
2400         i                                               : Integer;
2401 begin
2402
2403         //===== \83v\83\89\83O\83C\83\93
2404         try
2405                 for i := Length( BoardGroups ) - 1 downto 1 do begin
2406                         if Assigned( Pointer( BoardGroups[i].BoardPlugIn.Module ) ) then begin
2407                                 if BoardGroups[i].BoardPlugIn.AcceptURL( inURL ) = atThread then begin
2408                     board := BBSsFindBoardFromURL( BoardGroups[i].BoardPlugIn.ExtractBoardURL(inURL) );
2409                                         if board <> nil then begin
2410                                                 boardPlugIn := BoardGroups[i].BoardPlugIn;
2411                                                 threadItem      := TThreadItem.Create( boardPlugIn, board, inURL );
2412                                                 Result                  := threadItem.URL;
2413                                                 threadItem.Free;
2414
2415                                         end;
2416                                         Exit;
2417                                 end;
2418                         end;
2419                 end;
2420         except
2421                 // exception \82ª\94­\90\82µ\82½\8fê\8d\87\82Í\93à\95\94\8f\88\97\9d\82É\94C\82¹\82½\82¢\82Ì\82Å\82±\82±\82Å\82Í\89½\82à\82µ\82È\82¢
2422         end;
2423
2424         if Length( Result ) = 0 then
2425                 Result := GikoSys.Get2chBrowsableThreadURL( inURL );
2426
2427 end;
2428
2429 {!
2430 \brief \83X\83\8c\83b\83h URL \82ð\94 URL \82É\95Ï\8a·
2431 \param inURL \83X\83\8c\83b\83h URL
2432 \return      \94 URL
2433 }
2434 function        TGikoSys.GetThreadURL2BoardURL(
2435         inURL : string
2436 ) : string;
2437 var
2438         threadItem      : TThreadItem;
2439         boardPlugIn     : TBoardPlugIn;
2440     board               : TBoard;
2441         i                                               : Integer;
2442 begin
2443
2444         //===== \83v\83\89\83O\83C\83\93
2445         try
2446                 for i := Length( BoardGroups ) - 1 downto 1 do begin
2447                         if Assigned( Pointer( BoardGroups[i].BoardPlugIn.Module ) ) then begin
2448                                 if BoardGroups[i].BoardPlugIn.AcceptURL( inURL ) = atThread then begin
2449                     board               := BBSsFindBoardFromURL(BoardGroups[i].BoardPlugIn.ExtractBoardURL(inURL));
2450                                         boardPlugIn := BoardGroups[i].BoardPlugIn;
2451                                         threadItem      := TThreadItem.Create( boardPlugIn, board, inURL );
2452                                         Result                  := BoardGroups[i].BoardPlugIn.GetBoardURL( Longword( threadItem ) );
2453                                         threadItem.Free;
2454
2455                                         Break;
2456                                 end;
2457                         end;
2458                 end;
2459         except
2460                 // exception \82ª\94­\90\82µ\82½\8fê\8d\87\82Í\93à\95\94\8f\88\97\9d\82É\94C\82¹\82½\82¢\82Ì\82Å\82±\82±\82Å\82Í\89½\82à\82µ\82È\82¢
2461         end;
2462
2463         if Length( Result ) = 0 then
2464                 Result := GikoSys.Get2chThreadURL2BoardURL( inURL );
2465
2466 end;
2467
2468 {!
2469 \brief 2ch\97p:\83X\83\8c\83b\83h URL \82ð\94 URL \82É\95Ï\8a·
2470 \param inURL \83X\83\8c\83b\83h URL
2471 \return      \94 URL
2472 \see TGikoSys.GetThreadURL2BoardURL
2473 }
2474 function        TGikoSys.Get2chThreadURL2BoardURL(
2475         inURL : string
2476 ) : string;
2477 var
2478         Protocol, Host, Path, Document, Port, Bookmark : string;
2479         BBSID, BBSKey : string;
2480         foundPos                        : Integer;
2481 begin
2482
2483         ParseURI( inURL, Protocol, Host, Path, Document, Port, Bookmark );
2484         Parse2chURL( inURL, Path, Document, BBSID, BBSKey );
2485
2486         foundPos := Pos( '/test/read.cgi', inURL );
2487         if {(Is2chHost(Host)) and} (foundPos > 0) then
2488                 Result := Copy( inURL, 1, foundPos ) + BBSID + '/'
2489         else
2490                 Result := Protocol + '://' + Host + '/' + BBSID + '/';
2491
2492 end;
2493
2494 {!
2495 \brief 2ch\97p:\83X\83\8c\83b\83h URL \82Ì\90³\8bK\89»
2496 \param inURL \90³\8bK\89»\82·\82é\83X\83\8c\83b\83h URL
2497 \return      \90³\8bK\89»\82³\82ê\82½\83X\83\8c\83b\83h URL
2498 \see TGikoSys.GetBrowsableThreadURL
2499 }
2500 function        TGikoSys.Get2chBrowsableThreadURL(
2501         inURL                   : string
2502 ) : string;
2503 var
2504         Protocol, Host, Path, Document, Port, Bookmark : string;
2505         BBSID, BBSKey : string;
2506         foundPos        : Integer;
2507 begin
2508
2509 //      if Pos( KAKO_PATH, inURL ) > 0 then begin
2510 //              Result := inURL;
2511 //      end else begin
2512                 ParseURI( inURL, Protocol, Host, Path, Document, Port, Bookmark );
2513                 Parse2chURL( inURL, Path, Document, BBSID, BBSKey );
2514                 foundPos := Pos( '/test/read.cgi', inURL ) - 1;
2515
2516                 if Is2chHost( Host ) then begin
2517                         Result := Protocol + '://' + Host +
2518                                 READ_PATH + BBSID + '/' + BBSKey + '/l50';
2519                 end else begin
2520                         if foundPos > 0 then
2521                                 Result := Copy( inURL, 1, foundPos ) +
2522                                         OLD_READ_PATH + 'bbs=' + BBSID + '&key=' + BBSKey + '&ls=50'
2523                         else
2524                                 Result := Protocol + '://' + Host +
2525                                         OLD_READ_PATH + 'bbs=' + BBSID + '&key=' + BBSKey + '&ls=50';
2526                 end;
2527 //      end;
2528
2529 end;
2530
2531 {!
2532 \brief 2ch\97p:\94 URL \82©\82ç\83X\83\8c\83b\83h URL \82ð\8dì\90¬
2533 \param inBoard \94 URL
2534 \param inKey   \83X\83\8c\83b\83h\83L\81[(ex. 1000000000)
2535 \return        \83X\83\8c\83b\83h URL
2536 }
2537 function        TGikoSys.Get2chBoard2ThreadURL(
2538         inBoard : TBoard;
2539         inKey           : string
2540 ) : string;
2541 var
2542         server  : string;
2543 begin
2544
2545         server := UrlToServer( inBoard.URL );
2546         //if Is2chHost( server ) then
2547         if inBoard.Is2ch then
2548                 Result := server + 'test/read.cgi/' + inBoard.BBSID + '/' + inKey + '/l50'
2549         else
2550                 Result := server + 'test/read.cgi?bbs=' + inBoard.BBSID + '&key=' + inKey + '&ls=50';
2551
2552 end;
2553
2554 {!
2555 \brief \83{\81[\83h\83t\83@\83C\83\8b\97ñ\8b\93
2556
2557 \97ñ\8b\93\82³\82ê\82½ BBS(\83{\81[\83h) \82Í BBSs \82É\93ü\82è\82Ü\82·\81B
2558 }
2559 procedure TGikoSys.ListBoardFile;
2560 var
2561         boardFileList   : TStringList;
2562         i, l                    : Integer;
2563     sCategory       : TCategory;
2564 begin
2565         // BBS \82Ì\8aJ\95ú
2566         try
2567           for i := 0 to Length( BBSs ) - 1 do
2568                 BBSs[ i ].Free;
2569         except
2570         end;
2571         SetLength( BBSs, 0 );
2572
2573         l := 0;
2574         // \94Â\83\8a\83X\83g\82Ì\97ñ\8b\93
2575         if FileExists( GikoSys.GetBoardFileName ) then begin
2576           SetLength( BBSs, l + 1 );
2577           BBSs[ l ]                             := TBBS.Create( GikoSys.GetBoardFileName );
2578           BBSs[ l ].Title       := '\82Q\82¿\82á\82ñ\82Ë\82é';
2579                   Inc( l );
2580         end;
2581
2582         if FileExists( GikoSys.GetCustomBoardFileName ) then begin
2583           SetLength( BBSs, l + 1 );
2584           BBSs[ l ]                             := TBBS.Create( GikoSys.GetCustomBoardFileName );
2585           BBSs[ l ].Title       := '\82»\82Ì\91¼';
2586                   Inc( l );
2587         end;
2588
2589         // Board \83t\83H\83\8b\83_
2590         if DirectoryExists( GikoSys.Setting.GetBoardDir ) then begin
2591           BoardFileList := TStringList.Create;
2592           try
2593         BoardFileList.BeginUpdate;
2594                 GikoSys.GetFileList( GikoSys.Setting.GetBoardDir, '*.txt', BoardFileList, True, True );
2595         BoardFileList.EndUpdate;
2596         SetLength( BBSs, l + BoardFileList.Count );
2597                 for i := BoardFileList.Count - 1 downto 0 do begin
2598                   BBSs[ l ]                             := TBBS.Create( BoardFileList[ i ] );
2599                   BBSs[ l ].Title       := ChangeFileExt( ExtractFileName( BoardFileList[ i ] ), '' );
2600                   Inc( l );
2601                 end;
2602           finally
2603                 BoardFileList.Free;
2604           end;
2605         end;
2606
2607     // \93Á\8eê\97p\93rBBS\90\90¬
2608     // \8aù\82É\91\8dÝ\82·\82é\8fê\8d\87\82Í\8dí\8f\9c\82·\82é
2609     DestorySpecialBBS(BoardGroup.SpecialBBS);
2610     SpecialBBS := TBBS.Create('');
2611     SpecialBBS.Title := '\93Á\8eê\97p\93r(\94ñ\95\\8e¦)';
2612     sCategory := TCategory.Create;
2613     sCategory.No := 1;
2614     sCategory.Title := '\93Á\8eê\97p\93r(\94ñ\95\\8e¦)';
2615     SpecialBBS.Add(sCategory);
2616     BoardGroup.SpecialBoard := TSpecialBoard.Create(nil, 'http://localhost/gikonavi/special/index.html');
2617     BoardGroup.SpecialBoard.Title := '\83^\83u\88ê\97\97';
2618     BoardGroup.SpecialBoard.IsThreadDatRead := True;
2619     sCategory.Add(BoardGroup.SpecialBoard);
2620 end;
2621
2622 {!
2623 \brief \83{\81[\83h\83t\83@\83C\83\8b\93Ç\82Ý\8d\9e\82Ý
2624 \param bbs \83{\81[\83h\83t\83@\83C\83\8b\82ð\93Ç\82Ý\8d\9e\82Þ BBS
2625 }
2626 procedure TGikoSys.ReadBoardFile( bbs : TBBS );
2627 var
2628 //      idx                                             : Integer;
2629         ini                                             : TMemIniFile;
2630         p : Integer;
2631         boardFile                       : TStringList;
2632         CategoryList    : TStringList;
2633         BoardList                       : TStringList;
2634         Category                        : TCategory;
2635         Board                                   : TBoard;
2636         inistr                          : string;
2637         tmpstring                       : string;
2638 //      RoundItem                       : TRoundItem;
2639
2640         i, iBound                       : Integer;
2641         j, jBound                       : Integer;
2642         k, kBound                       : Integer;
2643 begin
2644
2645         if not FileExists( bbs.FilePath ) then
2646                 Exit;
2647
2648         bbs.Clear;
2649         ini := TMemIniFile.Create('');
2650         boardFile := TStringList.Create;
2651
2652         try
2653                 boardFile.LoadFromFile( bbs.FilePath );
2654
2655                 ini.SetStrings( boardFile );
2656                 CategoryList    := TStringList.Create;
2657                 BoardList                       := TStringList.Create;
2658                 try
2659                         ini.ReadSections( CategoryList );
2660
2661                         iBound := CategoryList.Count - 1;
2662                         for i := 0 to iBound do begin
2663                                 ini.ReadSection( CategoryList[i], BoardList );
2664                                 Category                                := TCategory.Create;
2665                                 Category.No                     := i + 1;
2666                                 Category.Title  := CategoryList[i];
2667
2668                                 jBound := BoardList.Count - 1;
2669                                 for j := 0 to jBound do begin
2670                                         Board := nil;
2671                                         inistr := ini.ReadString(CategoryList[i], BoardList[j], '');
2672                                         //'http://'\82ð\8aÜ\82Ü\82È\82¢\95\8e\9a\97ñ\82Ì\8e\9e\82Í\96³\8e\8b\82·\82é
2673                                         if (AnsiPos('http://', AnsiLowerCase(inistr)) = 0) then Continue;
2674                                         //===== \83v\83\89\83O\83C\83\93
2675                                         try
2676                                                 kBound := Length(BoardGroups) - 1;
2677                                                 for k := 1 to kBound do begin  //0\82Í\81A2\82¿\82á\82ñ
2678                                                         if Assigned( Pointer( BoardGroups[k].BoardPlugIn.Module ) ) then begin
2679                                                                 if BoardGroups[k].BoardPlugIn.AcceptURL( inistr ) = atBoard then begin
2680                                                                         if not BoardGroups[k].Find(inistr, p) then begin
2681                                                                                 tmpstring := BoardGroups[k].BoardPlugIn.ExtractBoardURL( inistr );
2682                                                                                 if AnsiCompareStr(tmpString, inistr) <> 0 then begin
2683                                                                                         if not BoardGroups[k].Find(tmpstring, p) then begin
2684                                                                                                 try
2685                                                                                                         Board := TBoard.Create( BoardGroups[k].BoardPlugIn, tmpstring );
2686                                                                                                         BoardGroups[k].AddObject(tmpstring, Board);
2687                                                                                                         Category.Add(Board);
2688                                                                                                 except
2689                                                                                                         //\82±\82±\82É\97\88\82é\82Æ\82µ\82½\82çBoard\82Ì\8dì\90¬\82É\8e¸\94s\82µ\82½\82Æ\82«\82¾\82©\82çBoard\82ðnil\82É\82·\82é
2690                                                                                                         Board := nil;
2691                                                                                                 end;
2692                                                                                         end else begin
2693                                                                                                 Board := TBoard(BoardGroups[k].Objects[p]);
2694                                                                                                 if Board.ParentCategory <> Category then
2695                                                                                                         Category.Add(Board);
2696                                                                                         end;
2697                                                                                 end else begin
2698                                                                                         try
2699                                                                                                 Board := TBoard.Create( BoardGroups[k].BoardPlugIn, tmpstring );
2700                                                                                                 BoardGroups[k].AddObject(tmpstring, Board);
2701                                                                                                 Category.Add(Board);
2702                                                                                         except
2703                                                                                                 //\82±\82±\82É\97\88\82é\82Æ\82µ\82½\82çBoard\82Ì\8dì\90¬\82É\8e¸\94s\82µ\82½\82Æ\82«\82¾\82©\82çBoard\82ðnil\82É\82·\82é
2704                                                                                                 Board := nil;
2705                                                                                         end;
2706                                                                                 end;
2707                                                                         end else begin
2708                                                                                 Board := TBoard(BoardGroups[k].Objects[p]);
2709                                                                                 if Board.ParentCategory <> Category then
2710                                                                                         Category.Add(Board);
2711                                                                         end;
2712                                                                         Break;
2713                                                                 end;
2714                                                         end;
2715                                                 end;
2716                                         except
2717                                                 // exception \82ª\94­\90\82µ\82½\8fê\8d\87\82Í\93à\95\94\8f\88\97\9d\82É\94C\82¹\82½\82¢\82Ì\82Å\82±\82±\82Å\82Í\89½\82à\82µ\82È\82¢
2718                                         end;
2719                                         try
2720                                                 if (Board = nil) then begin
2721                                                         if not BoardGroups[0].Find(inistr,p) then begin
2722                                                                 Board := TBoard.Create( nil, inistr );
2723                                                                 BoardGroups[0].AddObject(inistr, Board);
2724                                                                 Category.Add(Board);
2725                                                         end else begin
2726                                                                 Board := TBoard(BoardGroups[0].Objects[p]);
2727                                                                 if Board.ParentCategory <> Category then
2728                                                                         Category.Add(Board);
2729                                                         end;
2730                                                 end;
2731
2732                                                 if (Board.Multiplicity = 0) then begin
2733                                                         Board.BeginUpdate;
2734                                                         Board.No := j + 1;
2735                             Board.Multiplicity := 1;
2736                                                         Board.Title := BoardList[j];
2737                                                         Board.RoundDate := ZERO_DATE;
2738                                                         Board.LoadSettings;
2739                                                         Board.EndUpdate;
2740                                                 end else begin
2741                                                         Board.No := j + 1;
2742                                                         Board.Multiplicity := Board.Multiplicity + 1;
2743                                                 end;
2744                                         except
2745                                         end;
2746                                 end;
2747                                 bbs.Add( Category );
2748                         end;
2749
2750
2751                   //end;
2752                   bbs.IsBoardFileRead := True;
2753           finally
2754                 BoardList.Free;
2755                 CategoryList.Free;
2756           end;
2757   finally
2758         boardFile.Free;
2759         ini.Free;
2760   end;
2761
2762 end;
2763
2764 {!
2765 \brief \96¼\8fÌ\82ª\95s\96¾\82È\83J\83e\83S\83\8a\82Ì\90\90¬
2766 \return \90\90¬\82³\82ê\82½\83J\83e\83S\83\8a
2767 }
2768 function        TGikoSys.GetUnknownCategory : TCategory;
2769 const
2770         UNKNOWN_CATEGORY = '(\96¼\8fÌ\95s\96¾)';
2771 begin
2772
2773         if Length( BBSs ) < 2 then begin
2774                 Result := nil;
2775                 Exit;
2776         end;
2777
2778         Result := BBSs[ 1 ].FindCategoryFromTitle( UNKNOWN_CATEGORY );
2779         if Result = nil then begin
2780                 Result                          := TCategory.Create;
2781                 Result.Title    := UNKNOWN_CATEGORY;
2782                 BBSs[ 1 ].Add( Result );
2783         end;
2784
2785 end;
2786
2787 {!
2788 \brief \96¼\8fÌ\82ª\95s\96¾\82È BBS \82Ì\90\90¬
2789 \return \90\90¬\82³\82ê\82½ BBS
2790 }
2791 function        TGikoSys.GetUnknownBoard( inPlugIn : TBoardPlugIn; inURL : string ) : TBoard;
2792 var
2793         category : TCategory;
2794 const
2795         UNKNOWN_BOARD = '(\96¼\8fÌ\95s\96¾)';
2796 begin
2797
2798         category := GetUnknownCategory;
2799         if category = nil then begin
2800                 Result := nil;
2801         end else begin
2802                 Result := category.FindBoardFromTitle( UNKNOWN_BOARD );
2803                 if Result = nil then begin
2804                         Result                          := TBoard.Create( inPlugIn, inURL );
2805                         Result.Title    := UNKNOWN_BOARD;
2806                         category.Add( Result );
2807                 end;
2808         end;
2809
2810 end;
2811
2812 //! Samba.ini
2813 function TGikoSys.GetSambaFileName : string;
2814 begin
2815         Result := Setting.GetSambaFileName;
2816 end;
2817 {!
2818 \brief \97ñ\8b\93\82³\82ê\82½\83\8c\83X\94Ô\8d\86\82Ö\82Ì\83A\83\93\83J\81[\97pHTML\8dì\90¬
2819 \param Numbers    \97ñ\8b\93\82³\82ê\82½\83\8c\83X\94Ô\8d\86
2820 \param ThreadItem \97ñ\8b\93\82·\82é\83X\83\8c\83b\83h
2821 \param limited    \97ñ\8b\93\82·\82é\90\94\82ð\90§\8cÀ\82·\82é\82È\82ç1\88È\8fã
2822 \return           \97ñ\8b\93\82³\82ê\82½\83\8c\83X\83A\83\93\83J\81[
2823 }
2824 function TGikoSys.CreateResAnchor(
2825     var Numbers: TStringList; ThreadItem: TThreadItem;
2826     limited: Integer):string;
2827 var
2828         i: integer;
2829     Res: TResRec;
2830     ResLink : TResLinkRec;
2831 begin
2832     // body\88È\8aO\82Í\8eg\97p\82µ\82È\82¢\82Ì\82Å\8f\89\8aú\89»\82µ\82È\82¢
2833     Res.FBody := '';
2834     Res.FType := glt2chNew;
2835
2836         Result := '';
2837         if (Numbers <> nil) and (Numbers.Count > 0) then begin
2838         if (limited > 0) and (Numbers.Count > limited) then begin
2839             for i := Numbers.Count - limited to Numbers.Count - 1 do begin
2840                 Res.FBody := Res.FBody + '&gt;' + Numbers[i] + ' ';
2841             end;
2842         end else begin
2843             for i := 0 to Numbers.Count - 1 do begin
2844                 Res.FBody := Res.FBody + '&gt;' + Numbers[i] + ' ';
2845             end;
2846         end;
2847         ResLink.FBbs := ThreadItem.ParentBoard.BBSID;
2848         ResLink.FKey := ChangeFileExt(ThreadItem.FileName, '');
2849         HTMLCreater.ConvRes(@Res, @ResLink, false);
2850         Result := Res.FBody;
2851     end;
2852 end;
2853
2854 {!
2855 \brief \93¯\82\93\8a\8de ID \82ð\8e\9d\82Â\83\8c\83X\82ð\97ñ\8b\93
2856 \param AID        \8cÂ\90l\82ð\93Á\92è\82·\82é\93\8a\8de ID
2857 \param ThreadItem \97ñ\8b\93\82·\82é\83X\83\8c\83b\83h
2858 \param body       OUT:\97ñ\8b\93\82³\82ê\82½\83\8c\83X\94Ô\8d\86\82ª\95Ô\82é
2859 }
2860 procedure TGikoSys.GetSameIDRes(const AID : string; ThreadItem: TThreadItem;var body: TStringList);
2861 var
2862         i: integer;
2863         ReadList: TStringList;
2864         Res: TResRec;
2865         boardPlugIn : TBoardPlugIn;
2866
2867     procedure CheckSameID(const AID:String; const Target: String; no: Integer);
2868     var
2869         pos: Integer;
2870     begin
2871         pos := AnsiPos('id:', LowerCase(Target));
2872         if (pos > 0) then begin
2873             if(AnsiPos(AID, Copy(Target, pos-1, Length(Target))) > 0) then begin
2874                 body.Add(IntToStr(no));
2875             end;
2876         end else begin
2877             if(AnsiPos(AID, Target) > 0) then begin
2878                 body.Add(IntToStr(no));
2879             end;
2880         end;
2881     end;
2882 begin
2883         if (not IsNoValidID(AID)) and
2884         (ThreadItem <> nil) and (ThreadItem.IsLogFile) then begin
2885                 //if ThreadItem.IsBoardPlugInAvailable then begin
2886         if ThreadItem.ParentBoard.IsBoardPlugInAvailable then begin
2887                         //===== \83v\83\89\83O\83C\83\93\82É\82æ\82é\95\\8e¦
2888                         //boardPlugIn           := ThreadItem.BoardPlugIn;
2889             boardPlugIn         := ThreadItem.ParentBoard.BoardPlugIn;
2890
2891                         for i := 0 to threadItem.Count - 1 do begin
2892                                 // \83\8c\83X
2893                                 THTMLCreate.DivideStrLine(boardPlugIn.GetDat(DWORD( threadItem ), i + 1), @Res);
2894                 CheckSameID(AID, Res.FDateTime, i+1);
2895                         end;
2896                 end else begin
2897                         ReadList := TStringList.Create;
2898                         try
2899                                 ReadList.LoadFromFile(ThreadItem.GetThreadFileName);
2900                                 for i := 0 to ReadList.Count - 1 do begin
2901                                         THTMLCreate.DivideStrLine(ReadList[i], @Res);
2902                     CheckSameID(AID, Res.FDateTime, i+1);
2903                                 end;
2904                         finally
2905                                 ReadList.Free;
2906                         end;
2907                 end;
2908         end;
2909 end;
2910
2911 {!
2912 \brief \93¯\82\93\8a\8de ID \82ð\8e\9d\82Â\83\8c\83X\82ð\97ñ\8b\93
2913 \param AIDNum     \8cÂ\90l\82ð\93Á\92è\82·\82é\93\8a\8de ID
2914 \param ThreadItem \97ñ\8b\93\82·\82é\83X\83\8c\83b\83h
2915 \param body       OUT:\97ñ\8b\93\82³\82ê\82½\83\8c\83X\94Ô\8d\86\82ª\95Ô\82é
2916 }
2917 procedure TGikoSys.GetSameIDRes(AIDNum : Integer; ThreadItem: TThreadItem;var body: TStringList);
2918 var
2919         AID : String;
2920 begin
2921     AID := GetResID(AIDNum, ThreadItem);
2922     if not IsNoValidID(AID) then begin
2923             GetSameIDRes(AID, ThreadItem, body);
2924         end;
2925 end;
2926 {!
2927 \brief \93\8a\8de ID \8eæ\93¾
2928 \param AIDNum     \93\8a\8d\83\8c\83X\94Ô\8d\86
2929 \param ThreadItem \93\8a\8de\83X\83\8c\83b\83h
2930 \param body       OUT:\93\8a\8deID
2931 }
2932 function TGikoSys.GetResID(AIDNum: Integer; ThreadItem: TThreadItem): String;
2933 var
2934         Res: TResRec;
2935         boardPlugIn : TBoardPlugIn;
2936 begin
2937     Result := '';
2938         if (ThreadItem <> nil) and (ThreadItem.IsLogFile)
2939                 and (AIDNum > 0) and (AIDNum <= ThreadItem.Count) then begin
2940                 //if ThreadItem.IsBoardPlugInAvailable then begin
2941         if ThreadItem.ParentBoard.IsBoardPlugInAvailable then begin
2942                         //===== \83v\83\89\83O\83C\83\93\82É\82æ\82é\95\\8e¦
2943                         //boardPlugIn           := ThreadItem.BoardPlugIn;
2944             boardPlugIn         := ThreadItem.ParentBoard.BoardPlugIn;
2945                         THTMLCreate.DivideStrLine(boardPlugIn.GetDat(DWORD( threadItem ), AIDNum), @Res);
2946                 end else begin
2947                         THTMLCreate.DivideStrLine( ReadThreadFile(ThreadItem.GetThreadFileName, AIDNum), @Res);
2948                 end;
2949                 Result := ExtructResID(Res.FDateTime);
2950         end;
2951 end;
2952 {!
2953 \brief \83\8c\83X\82Ì\8e\9e\8d\8f\95\94\82©\82çID\82ð\92\8a\8fo\82·\82é
2954 \param ADateStr \8e\9e\8d\8f\95\94\82Ì\95\8e\9a\97ñ
2955 \return     ID(ID\82Æ\82Ý\82È\82¹\82é\95\94\95ª\82ª\82È\82¢\82Æ\82«\82Í\8bó\95\8e\9a\97ñ)
2956 }
2957 function TGikoSys.ExtructResID(ADateStr: String): String;
2958 var
2959     stlist : TStringList;
2960 begin
2961     Result := '';
2962     if AnsiPos('id', AnsiLowerCase(ADateStr)) > 0 then begin
2963         Result := Copy(ADateStr, AnsiPos('id', AnsiLowerCase(ADateStr)), Length(ADateStr));
2964         if AnsiPos(' ', Result) > 0 then begin
2965             Result := Copy(Result, 1, AnsiPos(' ', Result) - 1);
2966         end;
2967         Result := ' ' + Result;
2968     end else begin
2969         stlist := TStringList.Create;
2970         try
2971             stList.Delimiter := ' ';
2972             stList.DelimitedText := ADateStr;
2973             // \93ú\95\8e\9e\8d\8f ID \91¼\81@\82Æ\8cÅ\92è\82Å\8dl\82¦\82é
2974             if (stList.Count >= 3) then begin
2975                 if Length(stList[3 - 1]) >= 7 then begin
2976                     Result := stList[3 - 1];
2977                 end;
2978             end;
2979         finally
2980             stList.Free;
2981         end;
2982     end;
2983 end;
2984
2985 {!
2986 \brief \83X\83p\83\80:\8cê\90\94\82ð\83J\83E\83\93\83g
2987 \param text      \8c³\82É\82È\82é\95\8fÍ
2988 \param wordCount OUT:\83J\83E\83\93\83g\82³\82ê\82½\92P\8cê\82Ì\88ê\97\97\82ª\95Ô\82é
2989 }
2990 procedure TGikoSys.SpamCountWord( const text : string; wordCount : TWordCount );
2991 begin
2992
2993         if Setting.SpamFilterAlgorithm = gsfaNone then Exit;
2994         Bayesian.CountWord( text, wordCount );
2995
2996 end;
2997
2998 {!
2999 \brief \83X\83p\83\80:\8aw\8fK\8c\8b\89Ê\82ð\95ú\8aü
3000 \param wordCount \95ú\8aü\82·\82é\92P\8cê\82Ì\88ê\97\97
3001 \param isSpam    wordCount \82ª\83X\83p\83\80\82Æ\82µ\82Ä\8aw\8fK\82³\82ê\82Ä\82¢\82½\82È\82ç True
3002 \warning        \8aw\8fK\8dÏ\82Ý\82Ì\95\8fÍ\82©\82Ç\82¤\82©\82Í\8am\94F\8fo\97\88\82Ü\82¹\82ñ\81B\n
3003                                         Learn \82µ\82Ä\82¢\82È\82¢\95\8fÍ\82â isSpam \82ð\8aÔ\88á\82¦\82Ä\8ew\92è\82·\82é\82Æ
3004                                         \83f\81[\83^\83x\81[\83X\82ª\94j\91¹\82µ\82Ü\82·\81B\n
3005                                         \8aw\8fK\8dÏ\82Ý\82©\82Ç\82¤\82©\82Í\93Æ\8e©\82É\8aÇ\97\9d\82µ\82Ä\82­\82¾\82³\82¢\81B
3006
3007 \91S\82Ä\82Ì\8aw\8fK\8c\8b\89Ê\82ð\83N\83\8a\83A\82·\82é\82í\82¯\82Å\82Í\82 \82è\82Ü\82¹\82ñ\81B\n
3008 wordCount \82ð\93¾\82½\95\8fÍ\82Ì\8aw\8fK\8c\8b\89Ê\82Ì\82Ý\83N\83\8a\83A\82µ\82Ü\82·\81B
3009
3010 \8eå\82É\83X\83p\83\80\82Æ\83n\83\80\82ð\90Ø\82è\91Ö\82¦\82é\82½\82ß\82É Forget -> Learn \82Ì\8f\87\82Å\8eg\97p\82µ\82Ü\82·\81B
3011 }
3012 procedure TGikoSys.SpamForget( wordCount : TWordCount; isSpam : Boolean );
3013 begin
3014
3015         if Setting.SpamFilterAlgorithm = gsfaNone then Exit;
3016         Bayesian.Forget( wordCount, isSpam );
3017
3018 end;
3019
3020 {!
3021 \brief \83X\83p\83\80:\8aw\8fK
3022 \param wordCount \8aw\8fK\82·\82é\92P\8cê\82Ì\88ê\97\97
3023 \param isSpam    \83X\83p\83\80\82Æ\82µ\82Ä\8aw\8fK\82·\82é\82È\82ç True
3024 }
3025 procedure TGikoSys.SpamLearn( wordCount : TWordCount; isSpam : Boolean );
3026 begin
3027
3028         if Setting.SpamFilterAlgorithm = gsfaNone then Exit;
3029         Bayesian.Learn( wordCount, isSpam );
3030
3031 end;
3032
3033 {!
3034 \brief \83X\83p\83\80:\95\8fÍ\82ð\89ð\90Í\82µ\81A\83X\83p\83\80\93x\90\94\82ð\93¾\82é
3035 \param text      \8c³\82É\82È\82é\95\8fÍ
3036 \param wordCount OUT:\83J\83E\83\93\83g\82³\82ê\82½\92P\8cê\82Ì\88ê\97\97\82ª\95Ô\82é(SpamCountWord \82Æ\93¯\93\99)
3037 \return          0\81`1 \82Ì\83X\83p\83\80\93x\90\94
3038 }
3039 function TGikoSys.SpamParse( const text : string; wordCount : TWordCount ) : Extended;
3040 begin
3041
3042         case Setting.SpamFilterAlgorithm of
3043         gsfaNone:                                                               Result := 0;
3044         gsfaPaulGraham:                                 Result := Bayesian.Parse( text, wordCount, gbaPaulGraham );
3045         gsfaGaryRobinson:                               Result := Bayesian.Parse( text, wordCount, gbaGaryRobinson );
3046         gsfaGaryRobinsonFisher: Result := Bayesian.Parse( text, wordCount, gbaGaryRobinsonFisher );
3047         else                                                                            Result := 0;
3048         end;
3049
3050 end;
3051
3052 {!
3053 \brief \83\86\81[\83U\90Ý\92è\82Ì CSS \82ð\90\90¬
3054 \return \90\90¬\82³\82ê\82½ CSS
3055
3056 [\83c\81[\83\8b]\83\81\83j\83\85\81[-[\83I\83v\83V\83\87\83\93]-[CSS \82Æ\83X\83L\83\93]\83^\83u\82Ì
3057 [\83t\83H\83\93\83g\82ð\8ew\92è], [\94w\8ci\90F\82ð\8ew\92è] \82É\89\88\82Á\82½ CSS \82ð\90\90¬\82µ\82Ü\82·\81B
3058 }
3059 function TGikoSys.SetUserOptionalStyle(): string;
3060 begin
3061                 Result := '';
3062         if Length( GikoSys.Setting.BrowserFontName ) > 0 then
3063                 Result := 'font-family:"' + GikoSys.Setting.BrowserFontName + '";';
3064         if GikoSys.Setting.BrowserFontSize <> 0 then
3065                 Result := Result + 'font-size:' + IntToStr( GikoSys.Setting.BrowserFontSize ) + 'pt;';
3066         if GikoSys.Setting.BrowserFontColor <> -1 then
3067                 Result := Result + 'color:#' + IntToHex( GikoSys.Setting.BrowserFontColor, 6 ) + ';';
3068         if GikoSys.Setting.BrowserBackColor <> -1 then
3069                 Result := Result + 'background-color:#' + IntToHex( GikoSys.Setting.BrowserBackColor, 6 ) + ';';
3070         case GikoSys.Setting.BrowserFontBold of
3071                 -1: Result := Result + 'font-weight:normal;';
3072                 1:  Result := Result + 'font-weight:bold;';
3073         end;
3074         case GikoSys.Setting.BrowserFontItalic of
3075                 -1: Result := Result + 'font-style:normal;';
3076                 1:  Result := Result + 'font-style:italic;';
3077         end;
3078 end;
3079
3080 {!
3081 \brief Be \83v\83\8d\83t\83@\83C\83\8b\82Ö\82Ì\83A\83\93\83J\81[\83^\83O\82ð\90\90¬
3082 \param AID  \91Î\8fÛ\82Æ\82È\82é\93ú\95tID\95\8e\9a\97ñ
3083 \param ANum \83\8c\83X\94Ô
3084 \param AURL \82»\82Ì\83X\83\8c\83b\83h\82ÌURL
3085 \return     \90\90¬\82³\82ê\82½\83A\83\93\83J\81[\83^\83O
3086 }
3087 function TGikoSys.AddBeProfileLink(AID : string; ANum: Integer):string ;
3088 var
3089         p : integer;
3090         BNum, BMark : string;
3091 begin
3092         p := AnsiPos('BE:', AnsiUpperCase(AID));
3093         if p > 0 then begin
3094                 BNum := Copy(AID, p, Length(AID));
3095                 AID := Copy(AID, 1, p - 1);
3096                 p := AnsiPos('-', BNum);
3097                 if p > 0 then begin
3098                         BMark := '?' + Trim(Copy(BNum, p + 1, Length(BNum)));
3099                         BNum := Copy(BNum, 1, p - 1);
3100                 end;
3101                 BNum := Trim(BNum);
3102                 Result := AID + ' <a href="'  + BNum + '/' + IntToStr(ANum)
3103                         + '" target=_blank>' + BMark + '</a>';
3104         end else
3105                 Result := AID;
3106 end;
3107
3108 {!
3109 \brief \83o\81[\83W\83\87\83\93\8fî\95ñ\82ð\8eæ\93¾
3110 \param KeyWord \8eæ\93¾\82·\82é\8d\80\96Ú
3111 \return        \83o\81[\83W\83\87\83\93\95\8e\9a\97ñ
3112 }
3113 function TGikoSys.GetVersionInfo(KeyWord: TVerResourceKey): string;
3114 const
3115         Translation = '\VarFileInfo\Translation';
3116         FileInfo = '\StringFileInfo\%0.4s%0.4s\';
3117 var
3118         BufSize, HWnd: DWORD;
3119         VerInfoBuf: Pointer;
3120         VerData: Pointer;
3121         VerDataLen: Longword;
3122         PathLocale: String;
3123 begin
3124         // \95K\97v\82È\83o\83b\83t\83@\82Ì\83T\83C\83Y\82ð\8eæ\93¾
3125         BufSize := GetFileVersionInfoSize(PChar(Application.ExeName), HWnd);
3126         if BufSize <> 0 then begin
3127                 // \83\81\83\82\83\8a\82ð\8am\95Û
3128                 GetMem(VerInfoBuf, BufSize);
3129                 try
3130                         GetFileVersionInfo(PChar(Application.ExeName), 0, BufSize, VerInfoBuf);
3131                         // \95Ï\90\94\8fî\95ñ\83u\83\8d\83b\83N\93à\82Ì\95Ï\8a·\83e\81[\83u\83\8b\82ð\8ew\92è
3132                         VerQueryValue(VerInfoBuf, PChar(Translation), VerData, VerDataLen);
3133
3134                         if not (VerDataLen > 0) then
3135                                 raise Exception.Create('\8fî\95ñ\82Ì\8eæ\93¾\82É\8e¸\94s\82µ\82Ü\82µ\82½');
3136
3137                         // 8\8c\85\82Ì\82P\82U\90i\90\94\82É\95Ï\8a·
3138                         // \81¨'\StringFileInfo\027382\FileDescription'
3139                         PathLocale := Format(FileInfo + KeyWordStr[KeyWord],
3140                         [IntToHex(Integer(VerData^) and $FFFF, 4),
3141                         IntToHex((Integer(VerData^) shr 16) and $FFFF, 4)]);
3142                         VerQueryValue(VerInfoBuf, PChar(PathLocale), VerData, VerDataLen);
3143
3144                         if VerDataLen > 0 then begin
3145                                 // VerData\82Í\83[\83\8d\82Å\8fI\82í\82é\95\8e\9a\97ñ\82Å\82Í\82È\82¢\82±\82Æ\82É\92\8d\88Ó
3146                                 result := '';
3147                                 SetLength(result, VerDataLen);
3148                                 StrLCopy(PChar(result), VerData, VerDataLen);
3149                         end;
3150                 finally
3151                         // \89ð\95ú
3152                         FreeMem(VerInfoBuf);
3153                 end;
3154         end;
3155 end;
3156
3157 {!
3158 \brief Load \82³\82ê\82Ä\82¢\82é\83v\83\89\83O\83C\83\93\82Ì\83o\81[\83W\83\87\83\93\82ð\97ñ\8b\93
3159 \return 1\8ds1plugin
3160 }
3161 function TGikoSys.GetPluginsInfo(): String;
3162 var
3163         i : Integer;
3164         major, minor, revision : Cardinal;
3165         agent, release : String;
3166 begin
3167         //\8c\8b\89Ê\82ð\83N\83\8a\83A\82µ\82Ä\82¨\82­
3168         Result := '';
3169
3170         //BoardGroups\8co\97R\82ÅPlugin\82É\83A\83N\83Z\83X\82·\82é
3171         for  i := 0 to Length(BoardGroups) - 1 do begin
3172                 //BoardGroups\82Ì\92\86\82É\82Í\81APlugin\82ð\8e\9d\82Á\82Ä\82¢\82È\82¢\82Ì\81i2\82¿\82á\82ñ\81j\82ª
3173                 //\82¢\82é\82Ì\82Å\82»\82ê\82ð\8f\9c\82­
3174                 if BoardGroups[i].BoardPlugIn <> nil then begin
3175                         BoardGroups[i].BoardPlugIn.VersionInfo(agent, major, minor, release, revision);
3176
3177
3178                         //"Plugin\82Ì\96¼\91O(major.minor.revision)"
3179                         Result := Result +
3180                                 Format('%s(%d.%d.%d)', [agent, major, minor, revision]) + #13#10;
3181                 end;
3182         end;
3183 end;
3184
3185
3186 //! IE\82Ì\83o\81[\83W\83\87\83\93\82ð\8eæ\93¾\82·\82é
3187 function TGikoSys.GetIEVersion: string;
3188 var
3189         R: TRegistry;
3190 begin
3191         R := TRegistry.Create;
3192         try
3193                 //\93Ç\82Ý\8eæ\82è\90ê\97p\82É\82µ\82È\82¢\82Æ\81A\90§\8cÀUSER\82Æ\82©\82Ì\8fê\8d\87\81A\8aJ\82¯\82È\82¢\82Ý\82½\82¢
3194                 R.Access := KEY_EXECUTE;
3195                 R.RootKey := HKEY_LOCAL_MACHINE;
3196                 R.OpenKey('Software\Microsoft\Internet Explorer', False);
3197                 try
3198                         Result := R.ReadString('version');
3199                 except
3200                         Result := '\83o\81[\83W\83\87\83\93\82Ì\8eæ\93¾\82É\8e¸\94s\82µ\82Ü\82µ\82½\81B';
3201                 end;
3202                 R.CloseKey;
3203         finally
3204                 R.Free;
3205         end;
3206 end;
3207 //! main\83t\83H\81[\83\80\82Ì\83V\83\87\81[\83g\83J\83b\83g\83L\81[\82ÌIni\83t\83@\83C\83\8b\96¼
3208 function TGikoSys.GetMainKeyFileName : String;
3209 begin
3210         Result := Setting.GetMainKeyFileName;
3211 end;
3212 //! Editor\83t\83H\81[\83\80\82Ì\83V\83\87\81[\83g\83J\83b\83g\83L\81[\82ÌIni\83t\83@\83C\83\8b\96¼
3213 function TGikoSys.GetEditorKeyFileName: String;
3214 begin
3215         Result := Setting.GetEditorKeyFileName;
3216 end;
3217 //! \93ü\97Í\83A\83V\83X\83g\82Ì\90Ý\92è\83t\83@\83C\83\8b\96¼
3218 function TGikoSys.GetInputAssistFileName: String;
3219 begin
3220         Result := Setting.GetInputAssistFileName;
3221 end;
3222 //! \83M\83R\83i\83r\82Ì\83\81\83b\83Z\81[\83W\82ð\90Ý\92è\82·\82é
3223 procedure TGikoSys.SetGikoMessage;
3224 begin
3225         if FGikoMessage = nil then begin
3226                 FGikoMessage := TGikoMessage.Create;
3227         end else begin
3228                 FGikoMessage.Clear;
3229         end;
3230
3231         if (Setting.GengoSupport) then begin
3232                 try
3233                         if (FileExists(Setting.GetLanguageFileName)) then begin
3234                                 FGikoMessage.LoadFromFile(Setting.GetLanguageFileName);
3235                         end;
3236                 except
3237                         FGikoMessage.Clear;
3238                 end;
3239         end;
3240 end;
3241 //! \83M\83R\83i\83r\82Ì\83\81\83b\83Z\81[\83W\82ð\8eæ\93¾\82·\82é
3242 function TGikoSys.GetGikoMessage(MesType: TGikoMessageListType): String;
3243 begin
3244     Result := '';
3245         if FGikoMessage <> nil then begin
3246                 Result := FGikoMessage.GetMessage(MesType);
3247         end;
3248 end;
3249
3250 //Tue, 17 Dec 2002 12:18:07 GMT \81¨ TDateTime\82Ö
3251 //MonaUtils\82©\82ç\88Ú\93®
3252 function  TGikoSys.DateStrToDateTime(const DateStr: string): TDateTime;
3253         function  StrMonthToMonth(const s: string): integer;
3254         const
3255                 m: array[1..12] of string = ('Jan','Feb','Mar','Apr','May','Jun', 'Jul','Aug','Sep','Oct','Nov','Dec');
3256         var
3257                 i: integer;
3258         begin
3259                 Result  :=  -1;
3260                 for i :=  Low(m)  to  High(m) do  begin
3261                         if  (SameText(s, m[i]))  then  begin
3262                                 Result  :=  i;
3263                                 Break;
3264                         end;
3265                 end;
3266         end;
3267 var
3268         wDay, wMonth, wYear: word;
3269         wHour, wMinute, wSecond: word;
3270         sTime: string;
3271         d: TDateTime;
3272 begin
3273         wDay    :=  StrToIntDef(ChooseString(DateStr, ' ', 1), 0);
3274         wMonth  :=  StrMonthToMonth(ChooseString(DateStr, ' ', 2));
3275         wYear   :=  StrToIntDef(ChooseString(DateStr, ' ', 3), 0);
3276         sTime   :=  ChooseString(DateStr, ' ', 4);
3277         wHour   :=  StrToIntDef(ChooseString(sTime, ':', 0), 0);
3278         wMinute :=  StrToIntDef(ChooseString(sTime, ':', 1), 0);
3279         wSecond :=  StrToIntDef(ChooseString(sTime, ':', 2), 0);
3280         d :=  EncodeDateTime(wYear, wMonth, wDay, wHour, wMinute, wSecond, 0);
3281         Result  :=  d;
3282 end;
3283 //MonaUtils\82©\82ç\88Ú\93®
3284 //! \82 \82é\83Z\83p\83\8c\81[\83^\82Å\8bæ\90Ø\82ç\82ê\82½\95\8e\9a\97ñ\82©\82ç\82\8e\94Ô\96Ú\82Ì\95\8e\9a\97ñ\82ð\8eæ\82è\8fo\82·
3285 function TGikoSys.ChooseString(const Text, Separator: string; Index: integer): string;
3286 var
3287         S : string;
3288         i, p : integer;
3289 begin
3290         S :=  Text;
3291         for i :=  0 to  Index - 1 do  begin
3292                 if  (AnsiPos(Separator, S) = 0) then  S :=  ''
3293                 else  S :=  Copy(S, AnsiPos(Separator, S) + Length(Separator), Length(S));
3294         end;
3295         p :=  AnsiPos(Separator, S);
3296         if  (p > 0) then  Result  :=  Copy(S, 1, p - 1) else Result :=  S;
3297 end;
3298 //! \88ê\8e\9e\83t\83@\83C\83\8b\82©\82ç\82Ì\95\9c\8b\8c
3299 procedure TGikoSys.RestoreThreadData(Board : TBoard);
3300 const
3301     SECTION = 'Setting';
3302 var
3303     TmpFileList : TStringList;
3304     i : Integer;
3305     ini : TMemIniFile;
3306     ThreadItem : TThreadItem;
3307     Boardpath, tmpStr : string;
3308 begin
3309     Boardpath := ExtractFilePath(Board.GetFolderIndexFileName);
3310
3311         TmpFileList := TStringList.Create;
3312         TmpFileList.Sorted := True;
3313         TmpFileList.BeginUpdate;
3314     try
3315         //\91O\89ñ\88Ù\8fí\8fI\97¹\8e\9e\97pTmp\83t\83@\83C\83\8b\83\8a\83X\83g
3316             GetFileList(Boardpath, '*.tmp', TmpFileList, False);
3317             TmpFileList.EndUpdate;
3318                 //\91O\89ñ\88Ù\8fí\8fI\97¹\8e\9e\83`\83F\83b\83N
3319                 for i := TmpFileList.Count - 1 downto 0 do begin
3320                         ThreadItem := Board.FindThreadFromFileName(ChangeFileExt(TmpFileList[i], '.dat'));
3321                         if ThreadItem <> nil then begin
3322                                 ini := TMemIniFile.Create(Boardpath + TmpFileList[i]);
3323                                 try
3324                                         tmpStr := ini.ReadString(SECTION, 'RoundDate', DateTimeToStr(ZERO_DATE));
3325                                         ThreadItem.RoundDate := ConvertDateTimeString(tmpStr);
3326
3327                                         tmpStr := ini.ReadString(SECTION, 'LastModified', DateTimeToStr(ZERO_DATE));
3328                                         ThreadItem.LastModified := ConvertDateTimeString(tmpStr);
3329                                         ThreadItem.Count := ini.ReadInteger(SECTION, 'Count', 0);
3330                                         ThreadItem.NewReceive := ini.ReadInteger(SECTION, 'NewReceive', 0);
3331
3332                                         ThreadItem.Size := ini.ReadInteger(SECTION, 'Size', 0);
3333                     ThreadItem.IsLogFile := FileExists(ThreadItem.GetThreadFileName);
3334                                         if(ThreadItem.Size = 0) and (ThreadItem.IsLogFile) then begin
3335                                                 try
3336                                                         ThreadItem.Size := GetFileSize(ThreadItem.GetThreadFileName) - ThreadItem.Count;
3337                                                 except
3338                                                 end;
3339                                         end;
3340
3341                     //\8f\84\89ñ\82Ì\90Ý\92è\82ÍRoundData\82Ì\95û\82ª\82â\82é\82©\82ç\8f\9f\8eè\82É\90Ý\92è\82µ\82Ä\82Í\83_\83\81\81I\81@by \82à\82\82ã
3342                                         //ThreadItem.Round := ini.ReadBool('Setting', 'Round', False);
3343                                         //ThreadItem.RoundName := ini.ReadString('Setting', 'RoundName', ThreadItem.RoundName);
3344                                         ThreadItem.UnRead := False;//ini.ReadBool('Setting', 'UnRead', False);
3345                                         ThreadItem.ScrollTop := ini.ReadInteger(SECTION, 'ScrollTop', 0);
3346                                         ThreadItem.AllResCount := ini.ReadInteger(SECTION, 'AllResCount', ThreadItem.Count);
3347                                         ThreadItem.NewResCount := ini.ReadInteger(SECTION, 'NewResCount', 0);
3348                                         ThreadItem.AgeSage := TGikoAgeSage(ini.ReadInteger(SECTION, 'AgeSage', Ord(gasNone)));
3349                                 finally
3350                                         ini.Free;
3351                                 end;
3352                                 DeleteFile(Boardpath + TmpFileList[i]);
3353                         end;
3354                 end;
3355     finally
3356         TmpFileList.Clear;
3357         TmpFileList.Free;
3358     end;
3359 end;
3360 {
3361 \brief User32.dll\82ª\97\98\97p\82Å\82«\82é\82©
3362 \return Boolean \97\98\97p\82Å\82«\82é\8fê\8d\87\82ÍTrue
3363 }
3364 function TGikoSys.CanUser32DLL: Boolean;
3365 var
3366     hUser32 : HINST;
3367 begin
3368     Result := False;
3369         hUser32 := 0;
3370         try
3371                 try
3372                         hUser32 := LoadLibrary('User32.dll');
3373                         if hUser32 <> 0 then begin
3374                                 Result := True;
3375             end;
3376                 except
3377                 Result := false;
3378                 end;
3379         finally
3380                 FreeLibrary(hUser32);
3381         end;
3382 end;
3383 {
3384 \brief  OE\88ø\97p\95\84\8eæ\93¾
3385 \return OE\82Ì\88ø\97p\95\84\81i\90Ý\92è\82³\82ê\82Ä\82¢\82È\82¢\8fê\8d\87\82Í'>')
3386 }
3387 function TGikoSys.GetOEIndentChar : string;
3388 var
3389         regKey                  : TRegistry;
3390         Identities      : string;
3391         IndentChar      : DWORD;
3392 const
3393         DEFAULT_CHAR    = '> ';
3394         OE_MAIL_PATH    = '\Software\Microsoft\Outlook Express\5.0\Mail';
3395         INDENT_CHAR             = 'Indent Char';
3396 begin
3397
3398         Result  := DEFAULT_CHAR;
3399         regKey  := TRegistry.Create;
3400         try
3401                 try
3402                         regKey.RootKey  := HKEY_CURRENT_USER;
3403                         if not regKey.OpenKey( 'Identities', False ) then
3404                                 Exit;
3405                         Identities                      := regKey.ReadString( 'Default User ID' );
3406                         if Identities = '' then
3407                                 Exit;
3408                         if not regKey.OpenKey( Identities + OE_MAIL_PATH, False ) then
3409                                 Exit;
3410                         IndentChar := regKey.ReadInteger( INDENT_CHAR );
3411                         Result := Char( IndentChar ) + ' ';
3412                 except
3413                 end;
3414         finally
3415                 regKey.Free;
3416         end;
3417
3418 end;
3419 //! \92u\8a·\90Ý\92è\83t\83@\83C\83\8b\8eæ\93¾
3420 function TGikoSys.GetReplaceFileName: String;
3421 begin
3422     Result := Setting.GetReplaceFileName;
3423 end;
3424 //! \83v\83\8c\83r\83\85\81[\8ag\92£\82Ì\90Ý\92è\83t\83@\83C\83\8b\8eæ\93¾
3425 function TGikoSys.GetExtpreviewFileName: String;
3426 begin
3427     Result := Setting.GetExtprevieFileName;
3428 end;
3429
3430 //! \83t\83@\83C\83\8b\96¼\82©\82ç\82Ì\83X\83\8c\83b\83h\8dì\90¬\93ú\82Ì\8eæ\93¾
3431 function TGikoSys.GetCreateDateFromName(FileName: String): TDateTime;
3432 var
3433     tmp : String;
3434     unixtime: Int64;  
3435 begin
3436     // \83\8d\83O\83t\83@\83C\83\8b\82Ì\8ag\92£\8eq\82ð\82Í\82¸\82µ\82½\82à\82Ì\82ª\83X\83\8c\8dì\90¬\93ú\8e\9e
3437     tmp := ChangeFileExt(FileName, '');
3438     if AnsiPos('_', tmp) <> 0 then
3439         if AnsiPos('_', tmp) > 9 then
3440             tmp := Copy(tmp, 1, AnsiPos('_', tmp)-1)
3441         else
3442             Delete(tmp, AnsiPos('_', tmp), 1);
3443
3444     if ( Length(tmp) = 9) and ( tmp[1] = '0' ) then
3445         Insert('1', tmp, 1);
3446
3447     unixtime := StrToInt64Def(tmp, ZERO_DATE);
3448     Result := UnixToDateTime(unixtime) + OffsetFromUTC;
3449 end;
3450
3451 procedure TGikoSys.ShowRefCount(msg: String; unk: IUnknown);
3452 {$IFDEF DEBUG}
3453 var
3454     count : integer;
3455 {$ENDIF}
3456 begin
3457     if not Assigned(unk) then
3458         Exit;
3459
3460 {$IFDEF DEBUG}
3461     try
3462         unk._AddRef;
3463         count := unk._Release;
3464
3465                 Writeln(msg + ' RefCount=' + IntToStr(count));
3466     except
3467                 Writeln(msg + ' RefCount=exception!!');
3468         end;
3469 {$ENDIF}
3470 end;
3471 function TGikoSys.GetBoukenCookie(AURL: String): String;
3472 var
3473         Protocol, Host, Path, Document, Port,Bookmark : String;
3474 begin
3475     Result := '';
3476     GikoSys.ParseURI(AURL, Protocol, Host, Path, Document, Port,Bookmark);
3477     if ( Length(Host) > 0 ) then begin
3478         Result := Setting.GetBoukenCookie(Host);
3479     end;
3480 end;
3481 procedure TGikoSys.SetBoukenCookie(ACookieValue, ADomain: String);
3482 begin
3483     if ( Length(ADomain) > 0 ) then begin
3484         Setting.SetBoukenCookie(ACookieValue, ADomain);
3485     end;
3486 end;
3487 //! \96`\8c¯\82Ì\8f\91Domain\88ê\97\97\8eæ\93¾
3488 procedure TGikoSys.GetBoukenDomain(var ADomain: TStringList);
3489 var
3490     i : Integer;
3491 begin
3492     ADomain.Clear;
3493     for i := 0 to Setting.BoukenCookieList.Count - 1 do begin
3494         ADomain.Add( Setting.BoukenCookieList.Names[i] );
3495     end;
3496 end;
3497 //! \96`\8c¯\82Ì\8f\91Cookie\8dí\8f\9c
3498 procedure TGikoSys.DelBoukenCookie(ADomain: String);
3499 var
3500     i : Integer;
3501 begin
3502     for i := 0 to Setting.BoukenCookieList.Count - 1 do begin
3503         if ( Setting.BoukenCookieList.Names[i] = ADomain ) then begin
3504             Setting.BoukenCookieList.Delete(i);
3505             Break;
3506         end;
3507     end;
3508 end;
3509 function TGikoSys.GetBouken(AURL: String; var Domain: String): String;
3510 var
3511         Protocol, Host, Path, Document, Port,Bookmark : String;
3512     Cookie : String;
3513 begin
3514     Domain := '';
3515     Cookie := '';
3516     GikoSys.ParseURI(AURL, Protocol, Host, Path, Document, Port,Bookmark);
3517     if ( Length(Host) > 0 ) then begin
3518         Setting.GetBouken(Host, Domain, Cookie);
3519         Result := Cookie;
3520     end;
3521 end;
3522
3523 initialization
3524         GikoSys := TGikoSys.Create;
3525
3526 finalization
3527         if GikoSys <> nil then begin
3528                 FreeAndNil(GikoSys);
3529         end;
3530 end.