OSDN Git Service

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