OSDN Git Service

動作の最適化(たぶん)
[gikonavigoeson/gikonavi.git] / BoardGroup.pas
1 unit BoardGroup;
2
3 interface
4
5 uses
6         Windows, SysUtils, Classes, ComCtrls, IniFiles, {HTTPApp,} YofUtils, IdGlobal,
7         ExternalBoardManager, ExternalBoardPlugInMain, StrUtils, DateUtils;
8
9 type
10         //\83\8a\83X\83g\82Ì\95\\8e¦\83A\83C\83e\83\80\91I\91ð
11         TGikoViewType = (gvtAll, gvtLog, gvtNew, gvtUser);
12         //\83\8a\83X\83g\82Ì\8eæ\93¾\8c\8f\90\94
13         //TGikoListCount = (glc50, glc100, glc200, glc500, glc1000, glcAll);
14         //\8f\84\89ñ\94Ô\8d\86
15         //TGikoRoundNo = (grnNone, grn1, grn2, grn3, grn4, grn5, grnOnce);
16         //\83\8a\83X\83g\82Ì\8fã\82°\89º\82°
17         TGikoAgeSage = (gasNone, gasAge, gasSage, gasNew);
18
19 {       TFolder = class
20         private
21                 FItemList: TList;       //\8eq\83A\83C\83e\83\80\83\8a\83X\83g
22                 FLeaf: Boolean;         //\89º\82É\83t\83H\83\8b\83_\82ð\8e\9d\82Â\82±\82Æ\82ª\8fo\97\88\82é\82©
23         public
24                 function Add(Item: TFolder): Integer;
25                 procedure Clear;
26                 procedure Delete(Index: Integer);
27                 procedure Exchange(Index1, Index2: Integer);
28                 procedure Insert(Index: Integer; Item: TFolder);
29                 procedure Move(CurIndex, NewIndex: Integer);
30                 function Remove(Item: TFolder): Integer;
31                 procedure Sort(Compare: TListSortCompare);
32                 property Capacity: Integer read FCapacity write SetCapacity;
33                 property Count: Integer read FCount write SetCount;
34                 property Items[Index: Integer]: TFolder read Get write Put; default;
35
36                 property Leaf: Boolean read FLeaf;
37         end;
38
39         TBBS = class(TFolder)
40         end;
41         TCategory class(TFolder)
42         end;
43         TBoard = class(TFolder)
44         end;
45         TThreadItem = class(TFolder)
46         end;
47 }
48
49 {
50         TBBS = class(TBBS)
51         end;
52         TBoard2ch = class(TBoard)
53         end;
54         TThreadItem2ch = class(TThreadItem)
55         end;
56 }
57
58 //      ITest = interface
59 //      end;
60 //      IBBS = interface
61 //      end;
62 //      ICategory = interface
63 //      end;
64 //      IBoard = interface
65 //      end;
66 //      IThreadItem = interface
67 //      end;
68
69         TCategory = class;
70         TBoard = class;
71         TThreadItem = class;
72
73         // BBS \82Ì\83\8b\81[\83g
74         TBBS = class(TList)
75         private
76                 FTitle: string;
77                 FFilePath : string;                                             // \94Â\83\8a\83X\83g\82Ì\83p\83X
78                 FExpand: Boolean;
79                 FKubetsuChk: Boolean;                                   //\8di\8d\9e\82Ý\8e\9e\91å\95\8e\9a\8f¬\95\8e\9a\8bæ\95Ê
80                 FSelectText: string;                                    //\8di\8d\9e\82Ý\95\8e\9a\97ñ
81                 FShortSelectText: string;
82                 FIsBoardFileRead : Boolean;             // \94Â\83\8a\83X\83g\82Í\93Ç\82Ý\8d\9e\82Ü\82ê\82Ä\82¢\82é\82©\81H
83
84                 function GetCategory(index: integer): TCategory;
85                 procedure SetCategory(index: integer; value: TCategory);
86                 procedure SetSelectText(s: string);
87         public
88                 constructor Create( boardFilePath : string );
89                 destructor Destroy; override;
90
91                 function Add(item: TCategory): integer;
92                 procedure Delete(index: integer);
93                 procedure Clear; override;
94                 function Find(key: string): TCategory;
95                 function FindBBSID(const BBSID: string): TBoard;
96                 function FindBoardFromTitle(const Title: string): TBoard;
97                 function FindBoardFromURL(const inURL: string): TBoard;
98                 function FindThreadFromURL(const inURL : string ) : TThreadItem;
99                 function FindThreadItem(const BBSID, FileName: string): TThreadItem;
100                 function FindCategoryFromTitle(const inTitle : string ) : TCategory;
101                 property FilePath : string read FFilePath write FFilePath;
102
103                 property Items[index: integer]: TCategory read GetCategory write SetCategory;
104                 property Title: string read FTitle write FTitle;
105                 property NodeExpand: Boolean read FExpand write FExpand;
106
107                 property KubetsuChk: Boolean read FKubetsuChk write FKubetsuChk;
108                 property SelectText: string read FSelectText write SetSelectText;
109                 property ShortSelectText: string read FShortSelectText write FShortSelectText;
110
111                 property        IsBoardFileRead : Boolean read FIsBoardFileRead write FIsBoardFileRead;
112         end;
113
114         // \83J\83e\83S\83\8a(\94 URL \82Ì\83\8a\83X\83g)
115         TCategory = class(THashedStringList)
116         private
117                 FNo: Integer;
118                 FTitle: string;
119                 FParenTBBS: TBBS;
120                 FExpand: Boolean;
121
122                 function GetBoard(index: integer): TBoard;
123                 procedure SetBoard(index: integer; value: TBoard);
124         public
125                 constructor Create;
126                 destructor Destroy; override;
127
128                 property No: Integer read FNo write FNo;
129                 property Title: string read FTitle write FTitle;
130                 property Items[index: integer]: TBoard read GetBoard write SetBoard;
131                 property ParenTBBS: TBBS read FParenTBBS write FParenTBBS;
132
133                 function Add(item: TBoard): integer;
134                 procedure Delete(index: integer);
135                 procedure Clear; override;
136                 function FindName(const key: string): TBoard;
137                 function FindBBSID(const BBSID: string): TBoard;
138                 function FindBoardFromTitle(const Title: string): TBoard;
139                 function FindBoardFromURL(const inURL: string): TBoard;
140                 function FindThreadFromURL(const inURL : string ) : TThreadItem;
141                 function IsMidoku: Boolean;
142
143                 property NodeExpand: Boolean read FExpand write FExpand;
144         end;
145
146         // \94Â(\83X\83\8c\83b\83h URL \82Ì\83\8a\83X\83g)
147         TBoard = class(THashedStringList)
148         private
149                 FContext: DWORD;                                                        // \83v\83\89\83O\83C\83\93\82ª\8e©\97R\82É\90Ý\92è\82µ\82Ä\82¢\82¢\92l(\8eå\82É\83C\83\93\83X\83^\83\93\83X\82ª\93ü\82é)
150
151                 FNo: Integer;                                                                   //\94Ô\8d\86
152                 FTitle: string;                                                         //\83{\81[\83h\83^\83C\83g\83\8b
153                 FBBSID: string;                                                         //BBSID
154                 FURL: string;                                                                   //\83{\81[\83hURL
155                 FRound: Boolean;                                                        //\83X\83\8c\83b\83h\88ê\97\97\8f\84\89ñ\97\\96ñ
156                 FRoundName: string;                                             //\8f\84\89ñ\96¼
157                 FRoundDate: TDateTime;                          //\83X\83\8c\83b\83h\88ê\97\97\82ð\8eæ\93¾\82µ\82½\93ú\8e\9e\81i\8f\84\89ñ\93ú\8e\9e\81j
158                 FLastModified: TDateTime;                       //\83X\83\8c\83b\83h\88ê\97\97\82ª\8dX\90V\82³\82ê\82Ä\82¢\82é\93ú\8e\9e\81i\83T\81[\83o\91¤\93ú\8e\9e\81j
159                 FLastGetTime: TDateTime;                        //\83X\83\8c\83b\83h\82Ü\82½\82Í\83X\83\8c\83b\83h\88ê\97\97\82ð\8dÅ\8cã\82É\8dX\90V\82µ\82½\93ú\8e\9e\81i\83T\81[\83o\91¤\93ú\8e\9e\81E\8f\91\82«\8d\9e\82Ý\8e\9e\82É\8eg\97p\82·\82é\81j
160                 FIsThreadDatRead: Boolean;              //\83X\83\8c\83b\83h\83\8a\83X\83g\82Í\93Ç\82Ý\8d\9e\82Ü\82ê\82Ä\82¢\82é\82©\81H
161                 FUnRead: Integer;                                                       //\83X\83\8c\83b\83h\96¢\93Ç\90\94
162                 FParentCategory: TCategory;             //\90e\83J\83e\83S\83\8a
163                 FModified: Boolean;                                             //\8fC\90³\83t\83\89\83O
164                 FBoolData: Boolean;                                             //\82¢\82ë\82ñ\82È\97p\93r\82É\8eg\82¤yo
165                 FSPID: string;                                                          //\8f\91\82«\8d\9e\82Ý\97pSPID
166                 FPON: string;                                                                   //\8f\91\82«\8d\9e\82Ý\97pPON
167                 FKotehanName: string;                                   //\83R\83e\83n\83\93\96¼\91O
168                 FKotehanMail: string;                                   //\83R\83e\83n\83\93\83\81\81[\83\8b
169
170                 FUpdate: Boolean;
171                 FExpand: Boolean;
172
173                 FBoardPlugIn    : TBoardPlugIn; // \82±\82Ì\94Â\82ð\83T\83|\81[\83g\82·\82é\83v\83\89\83O\83C\83\93
174                 FFilePath                       : string;                               // \82±\82Ì\83X\83\8c\88ê\97\97\82ª\95Û\91\82³\82ê\82Ä\82¢\82é\83p\83X
175                 FIsLogFile              : Boolean;                      // \83\8d\83O\91\8dÝ\83t\83\89\83O
176                 FIntData                        : Integer;                      // \8dD\82«\82É\82¢\82\82Á\82Ä\82æ\82µ\81B\82¢\82ë\82ñ\82È\97p\93r\82É\8eg\82¤yo
177                 FListData                       : TList;                                // \8dD\82«\82É\82¢\82\82Á\82Ä\82æ\82µ\81B\82¢\82ë\82ñ\82È\97p\93r\82É\8eg\82¤yo
178
179                 function GetThreadItem(index: integer): TThreadItem;
180                 procedure SetThreadItem(index: integer; value: TThreadItem);
181                 procedure SetRound(b: Boolean);
182                 procedure SetRoundName(s: string);
183                 procedure SetLastModified(d: TDateTime);
184                 procedure SetLastGetTime(d: TDateTime);
185                 procedure SetUnRead(i: Integer);
186                 procedure SetKotehanName(s: string);
187                 procedure SetKotehanMail(s: string);
188                 procedure Init;
189         public
190                 constructor Create( inPlugIn : TBoardPlugIn; inURL : string );
191                 destructor Destroy; override;
192
193                 property Context: DWORD read FContext write FContext;
194
195                 property Items[index: integer]: TThreadItem read GetThreadItem write SetThreadItem;
196                 property No: Integer read FNo write FNo;
197                 property Title: string read FTitle write FTitle;
198                 property BBSID: string read FBBSID write FBBSID;
199                 property URL: string read FURL write FURL;
200                 property Round: Boolean read FRound write SetRound;
201                 property RoundName: string read FRoundName write SetRoundName;
202                 property RoundDate: TDateTime read FRoundDate write FRoundDate;
203                 property LastModified: TDateTime read FLastModified write SetLastModified;
204                 property LastGetTime: TDateTime read FLastGetTime write SetLastGetTime;
205                 property UnRead: Integer read FUnRead write SetUnRead;
206                 property Modified: Boolean read FModified write FModified;
207                 property IsThreadDatRead: Boolean read FIsThreadDatRead write FIsThreadDatRead;
208                 property ParentCategory: TCategory read FParentCategory write FParentCategory;
209
210                 property        BoardPlugIn     : TBoardPlugIn  read FBoardPlugIn;
211                 property        FilePath                : string                                read FFilePath write FFilePath;
212                 property        IsLogFile               : Boolean                               read FIsLogFile write FIsLogFile;
213                 property        IntData                 : Integer                               read FIntData write FIntData;
214                 property        ListData                : TList                                 read FListData write FListData;
215                 function        IsBoardPlugInAvailable : Boolean;
216
217                 function Add(item: TThreadItem): integer;
218                 procedure Insert(Index: Integer; Item: TThreadItem);
219                 procedure Delete(index: integer);
220                 procedure DeleteList(index: integer);
221                 procedure Clear; override;
222                 function FindThreadFromFileName(const ItemFileName: string): TThreadItem;
223                 function FindThreadFromURL(const inURL : string ) : TThreadItem;
224                 function GetIndexFromFileName(const ItemFileName: string): Integer;
225                 function GetIndexFromURL(const URL: string): Integer;
226                 procedure LoadSettings;
227                 procedure SaveSettings;
228                 function GetReadCgiURL: string;
229                 function GetSubjectFileName: string;
230                 function GetFolderIndexFileName: string;
231                 function GetSendURL: string;
232
233                 function GetNewThreadCount: Integer;
234                 function GetLogThreadCount: Integer;
235                 function GetUserThreadCount: Integer;
236                 function GetNewThread(Index: Integer): TThreadItem;
237                 function GetLogThread(Index: Integer): TThreadItem;
238                 function GetUserThread(Index: Integer): TThreadItem;
239
240                 procedure BeginUpdate;
241                 procedure EndUpdate;
242                 property NodeExpand: Boolean read FExpand write FExpand;
243                 property BoolData: Boolean read FBoolData write FBoolData;
244                 property SPID: string read FSPID write FSPID;
245                 property PON: string read FPON write FPON;
246                 property KotehanName: string read FKotehanName write SetKotehanName;
247                 property KotehanMail: string read FKotehanMail write SetKotehanMail;
248         end;
249
250         //\83X\83\8c
251         TThreadItem = class(TObject)
252         private
253                 FContext: DWORD;                                        // \83v\83\89\83O\83C\83\93\82ª\8e©\97R\82É\90Ý\92è\82µ\82Ä\82¢\82¢\92l(\8eå\82É\83C\83\93\83X\83^\83\93\83X\82ª\93ü\82é)
254
255                 FNo: Integer;                                                   //\94Ô\8d\86
256                 FFileName: string;                              //\83X\83\8c\83b\83h\83t\83@\83C\83\8b\96¼
257                 FTitle: string;                                         //\83X\83\8c\83b\83h\83^\83C\83g\83\8b
258                 FShortTitle: string;                    //\92Z\82¢\83X\83\8c\83b\83h\83^\83C\83g\83\8b\81i\8c\9f\8dõ\97p\81j
259                 FRoundDate: TDateTime;          //\83X\83\8c\83b\83h\82ð\8eæ\93¾\82µ\82½\93ú\8e\9e\81i\8f\84\89ñ\93ú\8e\9e\81j
260                 FLastModified: TDateTime; //\83X\83\8c\83b\83h\82ª\8dX\90V\82³\82ê\82Ä\82¢\82é\93ú\8e\9e\81i\83T\81[\83o\91¤\93ú\8e\9e\81j
261                 FCount: Integer;                                        //\83X\83\8c\83b\83h\83J\83E\83\93\83g\81i\83\8d\81[\83J\83\8b\81j
262                 FAllResCount: Integer;          //\83X\83\8c\83b\83h\83J\83E\83\93\83g\81i\83T\81[\83o\81j
263                 FNewResCount: Integer;          //\83X\83\8c\83b\83h\90V\92\85\90\94
264                 FSize: Integer;                                         //\83X\83\8c\83b\83h\83T\83C\83Y
265                 FRound: Boolean;                                        //\8f\84\89ñ\83t\83\89\83O
266                 FRoundName: string;                             //\8f\84\89ñ\96¼
267                 FIsLogFile: Boolean;                    //\83\8d\83O\91\8dÝ\83t\83\89\83O
268                 FParentBoard: TBoard;                   //\90e\83{\81[\83h
269                 FKokomade: Integer;                             //\83R\83R\82Ü\82Å\93Ç\82ñ\82¾\94Ô\8d\86
270                 FNewReceive: Integer;           //\83R\83R\82©\82ç\90V\8bK\8eó\90M
271                 FNewArrival: Boolean;                   //\90V\92\85
272                 FUnRead: Boolean;                                       //\96¢\93Ç\83t\83\89\83O
273                 FScrollTop: Integer;                    //\83X\83N\83\8d\81[\83\8b\88Ê\92u
274                 FDownloadHost: string;          //\8d¡\82Ì\83z\83X\83g\82Æ\88á\82¤\8fê\8d\87\82Ì\83z\83X\83g
275                 FAgeSage: TGikoAgeSage;         //\83A\83C\83e\83\80\82Ì\8fã\82°\89º\82°
276 //              FSPID: string;                                          //\8f\91\82«\8d\9e\82Ý\97pSPID
277
278                 FUpdate: Boolean;
279                 FExpand: Boolean;
280                 FURL                                    : string;                               // \82±\82Ì\83X\83\8c\82ð\83u\83\89\83E\83U\82Å\95\\8e¦\82·\82é\8dÛ\82Ì URL
281                 FBoardPlugIn    : TBoardPlugIn; // \82±\82Ì\83X\83\8c\82ð\83T\83|\81[\83g\82·\82é\83v\83\89\83O\83C\83\93
282                 FFilePath                       : string;                               // \82±\82Ì\83X\83\8c\82ª\95Û\91\82³\82ê\82Ä\82¢\82é\83p\83X
283                 FSizeByte                       : Integer;                      // CreateHTML2 \82ð\8eÀ\8ds\82µ\82Ä\82¢\82é\8dÅ\92\86\82É\88ê\8e\9e\93I\82É\95Û\91\82³\82ê\82é\92l
284
285                 procedure SetLastModified(d: TDateTime);
286                 procedure SetRound(b: Boolean);
287                 procedure SetRoundName(const s: string);
288                 procedure SetKokomade(i: Integer);
289                 procedure SetUnRead(b: Boolean);
290                 procedure SetScrollTop(i: Integer);
291                 procedure Init;
292                 function GetCreateDate: TDateTime;
293         public
294                 constructor Create( inPlugIn : TBoardPlugIn; inURL : string );
295                 destructor Destroy; override;
296
297                 function GetDatURL: string;
298                 function GetDatgzURL: string;
299 //              function GetOldDatgzURL: string;
300                 function GetOfflawCgiURL(const SessionID: string): string;
301                 function GetSendURL: string;
302                 procedure DeleteLogFile;
303                 function GetThreadFileName: string;
304                 procedure BeginUpdate;
305                 procedure EndUpdate;
306
307                 property Context: DWORD read FContext write FContext;
308
309                 property No: Integer read FNo write FNo;
310                 property FileName: string read FFileName write FFileName;
311                 property Title: string read FTitle write FTitle;
312                 property ShortTitle: string read FShortTitle write FShortTitle;
313                 property RoundDate: TDateTime read FRoundDate write FRoundDate;
314                 property LastModified: TDateTime read FLastModified write SetLastModified;
315                 property Count: Integer read FCount write FCount;
316                 property AllResCount: Integer read FAllResCount write FAllResCount;
317                 property NewResCount: Integer read FNewResCount write FNewResCount;
318                 property Size: Integer read FSize write FSize;
319                 property Round: Boolean read FRound write SetRound;
320                 property RoundName: string read FRoundName write SetRoundName;
321
322                 property IsLogFile: Boolean read FIsLogFile write FIsLogFile;
323                 property ParentBoard: TBoard read FParentBoard write FParentBoard;
324                 property Kokomade: Integer read FKokomade write SetKokomade;
325                 property NewReceive: Integer read FNewReceive write FNewReceive;
326                 property NewArrival: Boolean read FNewArrival write FNewArrival;
327                 property UnRead: Boolean read FUnRead write SetUnRead;
328                 property ScrollTop: Integer read FScrollTop write SetScrollTop;
329                 property Expand: Boolean read FExpand write FExpand;
330                 property DownloadHost: string read FDownloadHost write FDownloadHost;
331                 property AgeSage: TGikoAgeSage read FAgeSage write FAgeSage;
332 //              property SPID: string read FSPID write FSPID;
333                 property CreateDate: TDateTime read GetCreateDate;
334                 property        URL                                     : string                                read FURL write FURL;
335                 property        BoardPlugIn     : TBoardPlugIn  read FBoardPlugIn;
336                 property        FilePath                : string                                read FFilePath write FFilePath;
337                 property        SizeByte                : Integer                               read FSizeByte write FSizeByte;
338                 function        IsBoardPlugInAvailable : Boolean;
339         end;
340
341
342
343         //\8c\9f\8dõ\8c\8b\89Ê\83\8a\83X\83g
344 {       TSearchList = class(TList)
345         private
346                 function GetThreadItem(index: integer): TThreadItem;
347                 procedure SetThreadItem(index: integer; value: TThreadItem);
348         public
349                 constructor Create;
350                 destructor Destroy; override;
351
352                 property Items[index: integer]: TThreadItem read GetThreadItem write SetThreadItem;
353
354                 function Add(item: TThreadItem): integer;
355                 procedure Delete(index: integer);
356                 procedure Clear; override;
357         end;}
358
359         function        BBSsFindBoardFromBBSID( inBBSID : string ) : TBoard;
360         function        BBSsFindBoardFromURL( inURL : string ) : TBoard;
361         function        BBSsFindBoardFromTitle( inTitle : string ) : TBoard;
362         function        BBSsFindThreadFromURL(const inURL : string ) : TThreadItem;
363     function    ConvertDateTimeString( inDateTimeString : string) : TDateTime;
364     
365 var
366         BBSs            : array of TBBS;
367
368 implementation
369
370 uses
371         GikoSystem, RoundData;
372
373 const
374         BBS2CH_NAME:                                     string = '\82Q\82¿\82á\82ñ\82Ë\82é';
375         BBS2CH_LOG_FOLDER:               string = '2ch';
376         EXTERNAL_LOG_FOLDER:            string  = 'exboard';
377
378         FOLDER_INI_FILENAME:     string = 'Folder.ini';
379         FOLDER_INDEX_FILENAME: string   = 'Folder.idx';
380         SUBJECT_FILENAME:                       string  = 'subject.txt';
381         PATH_DELIM:                                             string  = '\';
382         //DEFAULT_LIST_COUNT:           Integer = 100;
383
384 //      COLUMN_CATEGORY:         array[0..0] of string = ('\83J\83e\83S\83\8a\96¼');
385 //      COLUMN_BOARD:                   array[0..3] of string = ('\94Â\96¼', '\8eæ\93¾\90\94', '\8f\84\89ñ\97\\96ñ', '\91O\89ñ\8f\84\89ñ\93ú\8e\9e');
386 //      COLUMN_THREADITEM: array[0..3] of string = ('\83X\83\8c\83b\83h\96¼', '\83J\83E\83\93\83g', '\8f\84\89ñ\97\\96ñ', '\91O\89ñ\8f\84\89ñ\93ú\8e\9e');
387
388 // BBSID \82ð\97p\82¢\82é 2 \82¿\82á\82ñ\82Ë\82é\82Ì\82Ý\92T\82µ\8fo\82µ\82Ü\82·
389 // BBSID \82Ì\8eg\97p\82Í\8bÉ\97Í\94ð\82¯\82Ä\82­\82¾\82³\82¢\81B
390 // \89Â\94\\82È\8fê\8d\87\82Í URL \82ð\8eg\97p\82µ\82Ä\82­\82¾\82³\82¢\81B
391 function        BBSsFindBoardFromBBSID(
392         inBBSID : string
393 ) : TBoard;
394 begin
395
396         Result := BBSs[ 0 ].FindBBSID( inBBSID );
397
398 end;
399
400 function        BBSsFindBoardFromURL(
401         inURL   : string
402 ) : TBoard;
403 var
404         i                       : Integer;
405 begin
406
407         for i := Length( BBSs ) - 1 downto 0 do begin
408                 Result := BBSs[ i ].FindBoardFromURL( inURL );
409                 if Result <> nil then
410                         Exit;
411         end;
412
413         Result := nil;
414
415 end;
416
417 function        BBSsFindBoardFromTitle(
418         inTitle : string
419 ) : TBoard;
420 var
421         i                               : Integer;
422 begin
423
424         for i := Length( BBSs ) - 1 downto 0 do begin
425                 Result := BBSs[ i ].FindBoardFromTitle( inTitle );
426                 if Result <> nil then
427                         Exit;
428         end;
429
430         Result := nil;
431
432 end;
433
434 function        BBSsFindThreadFromURL(
435         const inURL                     : string
436 ) : TThreadItem;
437 var
438         board                   : TBoard;
439         boardURL        : string;
440 begin
441
442         boardURL        := GikoSys.GetThreadURL2BoardURL( inURL );
443         board                   := BBSsFindBoardFromURL( boardURL );
444         if board = nil then
445                 Result := nil
446         else
447                 Result := board.FindThreadFromURL( inURL );
448
449 end;
450
451 (*************************************************************************
452  *\8b@\94\\96¼\81FTBBS\83R\83\93\83X\83g\83\89\83N\83^
453  *Public
454  *************************************************************************)
455 constructor TBBS.Create( boardFilePath : string );
456 begin
457         inherited Create;
458         Title := BBS2CH_NAME;
459         FFilePath := boardFilePath;
460 end;
461
462 (*************************************************************************
463  *\8b@\94\\96¼\81FTBBS\83f\83X\83g\83\89\83N\83^
464  *Public
465  *************************************************************************)
466 destructor TBBS.Destroy;
467 begin
468         Clear;
469         inherited;
470 end;
471
472 (*************************************************************************
473  *\8b@\94\\96¼\81F
474  *Public
475  *************************************************************************)
476 function TBBS.GetCategory(index: integer): TCategory;
477 begin
478         Result := TCategory(inherited Items[index]);
479 end;
480
481 procedure TBBS.SetCategory(index: integer; value: TCategory);
482 begin
483         inherited Items[index] := value;
484 end;
485
486 function TBBS.Add(item: TCategory): integer;
487 begin
488         Item.ParenTBBS := self;
489         Result := inherited Add(item);
490 end;
491
492 procedure TBBS.Delete(index: integer);
493 begin
494         if Items[index] <> nil then
495                 TCategory(Items[index]).Free;
496         Items[index] := nil;
497         inherited Delete(index);
498 end;
499
500 procedure TBBS.Clear;
501 var
502         i: integer;
503 begin
504         for i := Count - 1 downto 0 do
505                 Delete(i);
506     Capacity := Count;
507 end;
508
509 function TBBS.Find(key: string): TCategory;
510 begin
511         Result := nil;
512 end;
513
514 function TBBS.FindBBSID(const BBSID: string): TBoard;
515 var
516         i       : Integer;
517 begin
518         if not IsBoardFileRead then
519         GikoSys.ReadBoardFile( Self );
520         for i := Count - 1 downto 0 do begin
521                 Result := Items[ i ].FindBBSID(BBSID);
522                 if Result <> nil then
523                         Exit;
524         end;
525         Result := nil;
526 end;
527
528 //*************************************************************************
529 // \83^\83C\83g\83\8b\82Ì\88ê\92v\82·\82é\94Â\82ð\92T\82·
530 //*************************************************************************)
531 function TBBS.FindBoardFromTitle(const Title: string): TBoard;
532 var
533         i: Integer;
534 begin
535         if not IsBoardFileRead then
536         GikoSys.ReadBoardFile( Self );
537         for i := Count - 1 downto 0 do begin
538                 Result := Items[ i ].FindBoardFromTitle(Title);
539                 if Result <> nil then
540                         Exit;
541         end;
542         Result := nil;
543 end;
544
545 //*************************************************************************
546 // URL \82ð\8eó\82¯\95t\82¯\82é\94Â\82ð\92T\82·
547 //*************************************************************************)
548 function TBBS.FindBoardFromURL(const inURL: string): TBoard;
549 var
550         i                                       : Integer;
551 begin
552         if not IsBoardFileRead then
553         GikoSys.ReadBoardFile( Self );
554         for i := Count - 1 downto 0 do begin
555                 Result := Items[ i ].FindBoardFromURL( inURL );
556                 if Result <> nil then
557                         Exit;
558         end;
559         Result := nil;
560 end;
561
562 //*************************************************************************
563 // URL \82ð\8eó\82¯\95t\82¯\82é\83X\83\8c\83b\83h\82ð\92T\82·
564 //*************************************************************************)
565 function TBBS.FindThreadFromURL(const inURL: string): TThreadItem;
566 var
567         board                   : TBoard;
568         boardURL        : string;
569 begin
570
571         boardURL        := GikoSys.GetThreadURL2BoardURL( inURL );
572         board                   := FindBoardFromURL( boardURL );
573         if board = nil then
574                 Result := nil
575         else
576                 Result := board.FindThreadFromURL( inURL );
577
578 end;
579
580 function TBBS.FindThreadItem(const BBSID, FileName: string): TThreadItem;
581 var
582         Board: TBoard;
583 begin
584         Result := nil;
585         Board := FindBBSID(BBSID);
586         if Board = nil then
587                 Exit;
588         Result := Board.FindThreadFromFileName(FileName);
589 end;
590
591 function TBBS.FindCategoryFromTitle(const inTitle : string ) : TCategory;
592 var
593         i : Integer;
594 begin
595
596         for i := Count - 1 downto 0 do begin
597                 if AnsiCompareStr(Items[ i ].Title, inTitle) = 0 then begin
598                         Result := Items[ i ];
599                         Exit;
600                 end;
601         end;
602
603         Result := nil;
604
605 end;
606
607 procedure TBBS.SetSelectText(s: string);
608 begin
609         FSelectText := s;
610         ShortSelectText := GikoSys.ZenToHan(s);
611 end;
612
613 {class function TBBS.GetColumnName(Index: Integer): string;
614 begin
615         Result := COLUMN_CATEGORY[Index];
616 end;
617
618 class function TBBS.GetColumnCount: Integer;
619 begin
620         Result := Length(COLUMN_CATEGORY);
621 end;}
622
623 //===================
624 //TCategory
625 //===================
626 constructor TCategory.Create;
627 begin
628         inherited;
629 end;
630
631 destructor TCategory.Destroy;
632 begin
633         Clear;
634         inherited;
635 end;
636
637 function TCategory.GetBoard(index: integer): TBoard;
638 begin
639         Result := TBoard( Objects[index] );
640 end;
641
642 procedure TCategory.SetBoard(index: integer; value: TBoard);
643 begin
644         Objects[index] := value;
645         Strings[index] := value.URL
646 end;
647
648 function TCategory.Add(item: TBoard): integer;
649 begin
650         Item.ParentCategory := self;
651         Result := AddObject( item.URL, item );
652 end;
653
654 procedure TCategory.Delete(index: integer);
655 begin
656         if Items[index] <> nil then
657                 TBoard(Items[index]).Free;
658         inherited Delete(index);
659 end;
660
661 procedure TCategory.Clear;
662 var
663         i: integer;
664 begin
665         for i := Count - 1 downto 0 do
666                 Delete(i);
667         Capacity := Count;
668 end;
669
670 function TCategory.FindName(const key: string): TBoard;
671 begin
672         Result := nil;
673 end;
674
675 function TCategory.FindBBSID(const BBSID: string): TBoard;
676 var
677         i       : integer;
678 begin
679         for i := Count - 1 downto 0 do begin
680                 if AnsiCompareStr(Items[i].FBBSID, BBSID) = 0 then begin
681                         Result := Items[i];
682                         Exit;
683                 end;
684         end;
685         Result := nil;
686 end;
687
688 //*************************************************************************
689 // \83^\83C\83g\83\8b\82Ì\88ê\92v\82·\82é\94Â\82ð\92T\82·
690 //*************************************************************************)
691 function TCategory.FindBoardFromTitle(const Title: string): TBoard;
692 var
693         i       : integer;
694 begin
695         for i := Count - 1 downto 0 do begin
696                 if AnsiCompareStr(Items[i].FTitle, Title) = 0 then begin
697                         Result := Items[i];
698                         Exit;
699                 end;
700         end;
701         Result := nil;
702 end;
703
704 //*************************************************************************
705 // URL \82ð\8eó\82¯\95t\82¯\82é\94Â\82ð\92T\82·
706 //*************************************************************************)
707 function TCategory.FindBoardFromURL(const inURL: string): TBoard;
708 var
709         i       : Integer;
710 begin
711         i := IndexOf( inURL );
712         if i >= 0 then
713                 Result := TBoard( Objects[ i ] )
714         else
715                 Result := nil;
716 end;
717
718 //*************************************************************************
719 // URL \82ð\8eó\82¯\95t\82¯\82é\83X\83\8c\83b\83h\82ð\92T\82·
720 //*************************************************************************)
721 function TCategory.FindThreadFromURL(const inURL: string): TThreadItem;
722 var
723         board                   : TBoard;
724         boardURL        : string;
725 begin
726
727         boardURL        := GikoSys.GetThreadURL2BoardURL( inURL );
728         board                   := FindBoardFromURL( boardURL );
729         if board = nil then
730                 Result := nil
731         else
732                 Result := board.FindThreadFromURL( inURL );
733
734 end;
735
736 function TCategory.IsMidoku: Boolean;
737 var
738         i: Integer;
739         j: Integer;
740 begin
741         Result := False;
742         for i := 0 to Count - 1 do begin
743                 if Items[i] <> nil then begin
744                         for j := 0 to Items[i].Count - 1 do begin
745                                 if Items[i].Items[j] <> nil then begin
746 //                                      if (Items[i].Items[j].IsLogFile) and (Items[i].Items[j].Count > Items[i].Items[j].Kokomade) then begin
747                                         if (Items[i].Items[j].IsLogFile) and (Items[i].Items[j].UnRead) then begin
748                                                 Result := True;
749                                                 Exit;
750                                         end;
751                                 end;
752                         end;
753                 end;
754         end;
755 end;
756
757 {class function TCategory.GetColumnName(Index: Integer): string;
758 begin
759         Result := COLUMN_BOARD[Index];
760 end;
761
762 class function TCategory.GetColumnCount: Integer;
763 begin
764         Result := Length(COLUMN_BOARD);
765 end;}
766
767 //===================
768 //TBoard
769 //===================
770 procedure TBoard.Init;
771 begin
772         FNo := 0;
773         FTitle := '';
774         FBBSID := '';
775         FURL := '';
776         FRound := False;
777         FRoundDate := ZERO_DATE;
778         FLastModified := ZERO_DATE;
779         FLastGetTime := ZERO_DATE;
780         FIsThreadDatRead := False;
781         FUnRead := 0;
782 //      FListStyle := vsReport;
783 //      FItemNoVisible := True;
784
785         FUpdate := True;
786 end;
787
788 // *************************************************************************
789 // \8aO\95\94\94Â\83v\83\89\83O\83C\83\93\82ð\8ew\92è\82µ\82½\83R\83\93\83X\83g\83\89\83N\83^
790 // *************************************************************************
791 constructor TBoard.Create(
792         inPlugIn        : TBoardPlugIn;
793         inURL                   : string
794 );
795 var
796         protocol, host, path, document, port, bookmark  : string;
797 begin
798
799         inherited Create;
800         Init;
801
802         FBoardPlugIn    := inPlugIn;
803         URL                                             := inURL;
804         BBSID                                   := GikoSys.UrlToID( inURL );
805
806         if inPlugIn = nil then begin
807                 // subject.txt \82Ì\95Û\91\83p\83X\82ð\90Ý\92è
808                 GikoSys.ParseURI( inURL, protocol, host, path, document, port, bookmark );
809                 if GikoSys.Is2chHost( host ) then
810                         FilePath :=
811                                 IncludeTrailingPathDelimiter( GikoSys.Setting.LogFolder ) +
812                                 BBS2CH_LOG_FOLDER + PATH_DELIM + BBSID + PATH_DELIM + SUBJECT_FILENAME
813                 else
814                         FilePath :=
815                                 IncludeTrailingPathDelimiter( GikoSys.Setting.LogFolder ) +
816                                 EXTERNAL_LOG_FOLDER + PATH_DELIM + host + PATH_DELIM + BBSID + PATH_DELIM + SUBJECT_FILENAME
817         end else begin
818                 // \83v\83\89\83O\83C\83\93\82É TBoardItem \82ª\8dì\90¬\82³\82ê\82½\82±\82Æ\82ð\93`\82¦\82é
819                 inPlugIn.CreateBoardItem( DWORD( Self ) );
820         end;
821
822 end;
823
824 // *************************************************************************
825 // \83f\83X\83g\83\89\83N\83^
826 // *************************************************************************
827 destructor TBoard.Destroy;
828 begin
829         if FModified then begin
830                 GikoSys.WriteThreadDat(Self);
831                 SaveSettings;
832         end;
833
834         // \83v\83\89\83O\83C\83\93\82É TBoardItem \82ª\94j\8aü\82³\82ê\82½\82±\82Æ\82ð\93`\82¦\82é
835         if IsBoardPlugInAvailable then
836                 BoardPlugIn.DisposeBoardItem( DWORD( Self ) );
837
838         Clear;
839         inherited;
840 end;
841
842 // *************************************************************************
843 // \8aO\95\94\94Â\83v\83\89\83O\83C\83\93\82ª\8eg\97p\89Â\94\\82©
844 // *************************************************************************
845 function        TBoard.IsBoardPlugInAvailable : Boolean;
846 begin
847
848         repeat
849                 if BoardPlugIn = nil then
850                         Break;
851                         
852                 if not Assigned( Pointer( BoardPlugIn.Module ) ) then
853                         Break;
854
855                 Result := True;
856                 Exit;
857         until True;
858
859         Result := False;
860
861 end;
862
863 function TBoard.GetThreadItem(index: integer): TThreadItem;
864 begin
865         Result := TThreadItem( Objects[index] );
866 end;
867
868 procedure TBoard.SetThreadItem(index: integer; value: TThreadItem);
869 begin
870         Objects[index] := value;
871         Strings[index] := value.URL;
872 end;
873
874 function TBoard.Add(Item: TThreadItem): Integer;
875 begin
876         Item.ParentBoard := Self;
877         Result := inherited AddObject(Item.URL, Item);
878 end;
879
880 procedure TBoard.Insert(Index: Integer; Item: TThreadItem);
881 begin
882         Item.ParentBoard := Self;
883         inherited InsertObject(Index, Item.URL, Item);
884
885 end;
886
887 //Index\82Å\8ew\92è\82³\82ê\82½\83X\83\8c\83b\83h\83I\83u\83W\83F\83N\83g\82ð\94j\8aü
888 procedure TBoard.Delete(index: Integer);
889 begin
890         if Items[index] <> nil then
891                 TThreadItem(Items[index]).Free;
892         inherited Delete(index);
893 end;
894
895 //Index\82Å\8ew\92è\82³\82ê\82½\83X\83\8c\83b\83h\82ð\83\8a\83X\83g\82©\82ç\8dí\8f\9c\81i\83X\83\8c\83I\83u\83W\83F\83N\83g\82Í\82Ì\82±\82·\81j
896 procedure TBoard.DeleteList(index: integer);
897 begin
898         inherited Delete(index);
899 end;
900
901 procedure TBoard.Clear;
902 var
903         i: integer;
904 begin
905 //      FUnRead := 0;
906         for i := Count - 1 downto 0 do
907                 Delete(i);
908          Capacity := Count;
909 end;
910
911 function TBoard.FindThreadFromFileName(const ItemFileName: string): TThreadItem;
912 var
913         i: integer;
914 begin
915         Result := nil;
916         for i := 0 to Count - 1 do begin
917                 if AnsiCompareStr(Items[i].FileName, ItemFileName) = 0 then begin
918                         Result := Items[i];
919                         Exit;
920                 end;
921         end;
922 end;
923
924 function TBoard.GetIndexFromFileName(const ItemFileName: string): Integer;
925 var
926         i: integer;
927 begin
928         Result := -1;
929         for i := 0 to Count - 1 do begin
930                 if Items[i].FileName = ItemFileName then begin
931                         Result := i;
932                         Exit;
933                 end;
934         end;
935 end;
936
937 function TBoard.GetIndexFromURL(const URL: string): Integer;
938 begin
939         Result := IndexOf( URL );
940 end;
941
942 function TBoard.FindThreadFromURL(const inURL : string ) : TThreadItem;
943 var
944         i : Integer;
945 begin
946
947         if not IsThreadDatRead then
948                 GikoSys.ReadSubjectFile( Self );
949
950         i := IndexOf( inURL );
951         if i >= 0 then
952                 Result := TThreadItem( Objects[ i ] )
953         else
954                 Result := nil;
955
956 end;
957
958 {function TBoard.GetMidokuCount: Integer;
959 var
960         i: integer;
961 begin
962         Result := 0;
963         for i := 0 to Count- 1 do begin
964                 if Items[i] <> nil then begin
965                         if (Items[i].IsLogFile) and (Items[i].Count > Items[i].Kokomade) then
966                                 inc(Result);
967                 end;
968         end;
969 end;
970 }
971
972 procedure TBoard.LoadSettings;
973 var
974         ini: TMemIniFile;
975         FileName: string;
976     tmp: string;
977 begin
978         if Length( FilePath ) > 0 then
979                 FileName := ExtractFilePath( FilePath ) + FOLDER_INI_FILENAME
980         else
981                 FileName := IncludeTrailingPathDelimiter( GikoSys.Setting.LogFolder )
982                                                         + BBS2CH_LOG_FOLDER + PATH_DELIM + BBSID + PATH_DELIM + FOLDER_INI_FILENAME;
983
984         if not FileExists(FileName) then
985                 Exit;
986         ini := TMemIniFile.Create(FileName);
987         try
988 //              Round := ini.ReadBool('Status', 'Round', False);
989                 tmp := ini.ReadString('Status', 'RoundDate', DateTimeToStr(ZERO_DATE));
990         FRoundDate := ConvertDateTimeString(tmp);
991         tmp := ini.ReadString('Status', 'LastModified', DateTimeToStr(ZERO_DATE));
992         FLastModified := ConvertDateTimeString(tmp);
993         tmp := ini.ReadString('Status', 'LastGetTime', DateTimeToStr(ZERO_DATE));
994         FLastGetTime := ConvertDateTimeString(tmp);
995
996         {
997                 try
998                         FRoundDate := ini.ReadDateTime('Status', 'RoundDate', ZERO_DATE);
999         except
1000             tmp := ini.ReadString('Status', 'RoundDate', DateTimeToStr(ZERO_DATE));
1001                 FRoundDate := StrToDateTime(ConvertDateTimeString(tmp));
1002         end;
1003         try
1004                 FLastModified := ini.ReadDateTime('Status', 'LastModified', ZERO_DATE);
1005                 except
1006             tmp := ini.ReadString('Status', 'LastModified', DateTimeToStr(ZERO_DATE));
1007                 FLastModified := StrToDateTime(ConvertDateTimeString(tmp));
1008         end;
1009         try
1010                 FLastGetTime := ini.ReadDateTime('Status', 'LastGetTime', ZERO_DATE);
1011         except
1012             tmp := ini.ReadString('Status', 'LastGetTime', DateTimeToStr(ZERO_DATE));
1013                 FLastGetTime := StrToDateTime(ConvertDateTimeString(tmp));
1014         end;
1015         }
1016                 FUnRead := ini.ReadInteger('Status', 'UnRead', 0);
1017                 FSPID := ini.ReadString('Cookie', 'SPID', '');
1018                 FPON := ini.ReadString('Cookie', 'PON', '');
1019                 FKotehanName := ini.ReadString('Kotehan', 'Name', '');
1020                 FKotehanMail := ini.ReadString('Kotehan', 'Mail', '');
1021 //              ListStyle := TViewStyle(Ord(ini.ReadInteger('Status', 'ListStyle', 3)));
1022 //              ItemNoVisible := ini.ReadBool('Status', 'ItemNoVisible', True);
1023 //              ViewType := TGikoViewType(Ord(ini.ReadInteger('Status', 'ViewType', 0)));
1024                 if UnRead < 0 then
1025                         UnRead := 0;
1026         finally
1027                 ini.Free;
1028         end;
1029 end;
1030
1031 procedure TBoard.SaveSettings;
1032 var
1033         ini: TMemIniFile;
1034         FileName: string;
1035 begin
1036         if Length( FilePath ) > 0 then
1037                 FileName := ExtractFilePath( FilePath )
1038         else
1039                 FileName := IncludeTrailingPathDelimiter( GikoSys.Setting.LogFolder )
1040                                                         + BBS2CH_LOG_FOLDER + PATH_DELIM + BBSID + PATH_DELIM;
1041         if not GikoSys.DirectoryExistsEx(FileName) then
1042                 GikoSys.ForceDirectoriesEx(FileName);
1043         FileName := FileName + FOLDER_INI_FILENAME;
1044         ini := TMemIniFile.Create(FileName);
1045         try
1046                 if UnRead < 0 then
1047                         UnRead := 0;
1048 //              ini.WriteBool('Status', 'Round', Round);
1049                 ini.WriteDateTime('Status', 'RoundDate', FRoundDate);
1050                 ini.WriteDateTime('Status', 'LastModified', FLastModified);
1051                 ini.WriteDateTime('Status', 'LastGetTime', FLastGetTime);
1052                 ini.WriteInteger('Status', 'UnRead', FUnRead);
1053                 ini.WriteString('Cookie', 'SPID', FSPID);
1054                 ini.WriteString('Cookie', 'PON', FPON);
1055                 ini.WriteString('Kotehan', 'Name', FKotehanName);
1056                 ini.WriteString('Kotehan', 'Mail', FKotehanMail);
1057 //              ini.WriteInteger('Status', 'ListStyle', Ord(ListStyle));
1058 //              ini.WriteBool('Status', 'ItemNoVisible', ItemNoVisible);
1059 //              ini.WriteInteger('Status', 'ViewType', Ord(ViewType));
1060                 ini.UpdateFile;
1061         finally
1062                 ini.Free;
1063         end;
1064 end;
1065 //\82Æ\82«\82½\82Ü2003 02 08 0:32:13\82±\82ñ\82È\8c`\8e®\82Ì\93ú\95t\82ª\82 \82é\82Ì\82Å\82»\82ê\82ð
1066 //        2003/02/08 0:32:13\82É\95Ï\8a·\82·\82é
1067 function        ConvertDateTimeString( inDateTimeString : string) : TDateTime;
1068 const
1069         ZERO_DATE_STRING : string = '1970/01/01 0:00:00';
1070 var
1071         i : Integer;
1072     y: Integer;
1073     m: Integer;
1074     d: Integer;
1075     hour: Integer;
1076     min: Integer;
1077     sec: Integer;
1078 begin
1079     if inDateTimeString = '' then
1080         inDateTimeString := ZERO_DATE_STRING;
1081
1082     if ( AnsiPos('/', inDateTimeString ) = 0 ) and
1083         ( AnsiCompareStr( DateTimeToStr(ZERO_DATE), inDateTimeString) <> 0 ) then begin
1084                 for i := 0 to 1 do begin
1085                 Insert('/',inDateTimeString, AnsiPos(' ', inDateTimeString) + 1 );
1086                 Delete(inDateTimeString, AnsiPos(' ', inDateTimeString), 1);
1087         end;
1088     end;
1089     try
1090         Result := StrToDateTime( inDateTimeString );
1091     except
1092         if( inDateTimeString[5] = '/' ) and ( inDateTimeString[8] = '/' ) then begin
1093             y := StrToIntDef( Copy(inDateTimeString, 1, 4), 1970 );
1094             m := StrToIntDef( Copy(inDateTimeString, 6, 2), 1 );
1095             d := StrToIntDef( Copy(inDateTimeString, 9, 2), 1 );
1096             hour := 0; min  := 0; sec  := 0;
1097
1098                 if Length(inDateTimeString) > 11 then begin
1099                 if( inDateTimeString[13] = ':' ) and ( inDateTimeString[16] = ':' ) then begin
1100                         hour := StrToIntDef( Copy(inDateTimeString, 12, 1), 0 );
1101                     min  := StrToIntDef( Copy(inDateTimeString, 14, 2), 0 );
1102                     sec  := StrToIntDef( Copy(inDateTimeString, 17, 2), 0 );
1103                 end else if( inDateTimeString[14] = ':' ) and ( inDateTimeString[17] = ':' ) then begin
1104                         hour := StrToIntDef( Copy(inDateTimeString, 12, 2), 0 );
1105                     min  := StrToIntDef( Copy(inDateTimeString, 15, 2), 0 );
1106                     sec  := StrToIntDef( Copy(inDateTimeString, 18, 2), 0 );
1107                 end;
1108             end;
1109             try
1110                 Result := EncodeDateTime(y ,m, d, hour, min, sec, 0);
1111             except
1112                 Result := ZERO_DATE;
1113             end;
1114         end else
1115                 Result := ZERO_DATE;
1116     end;
1117
1118
1119    // Result := inDateTimeString;
1120 end;
1121 // \83T\83u\83W\83F\83N\83gURL\8eæ\93¾
1122 function TBoard.GetReadCgiURL: string;
1123 begin
1124         //Result := URL + SUBJECT_FILENAME;
1125         //Result := GikoSys.UrlToServer(URL)
1126         //                              + 'test/read.cgi/' + BBSID + '/?raw=0.0';
1127         Result := URL + SUBJECT_FILENAME;
1128
1129 end;
1130
1131 // \83T\83u\83W\83F\83N\83g\83t\83@\83C\83\8b\96¼\8eæ\93¾\81i\83p\83X\81{\83t\83@\83C\83\8b\96¼\81j
1132 function TBoard.GetSubjectFileName: string;
1133 begin
1134         if Length( FilePath ) > 0 then
1135                 Result := FilePath
1136         else
1137                 Result := IncludeTrailingPathDelimiter( GikoSys.Setting.LogFolder )
1138                                                 + BBS2CH_LOG_FOLDER + PATH_DELIM + BBSID + PATH_DELIM + SUBJECT_FILENAME;
1139 end;
1140
1141 // \83C\83\93\83f\83b\83N\83X\83t\83@\83C\83\8b\96¼(folder.idx)\8eæ\93¾\81i\83p\83X\81{\83t\83@\83C\83\8b\96¼\81j
1142 function TBoard.GetFolderIndexFileName: string;
1143 begin
1144         if Length( FilePath ) > 0 then
1145                 Result := ExtractFilePath( FilePath ) + FOLDER_INDEX_FILENAME
1146         else
1147                 Result := IncludeTrailingPathDelimiter( GikoSys.Setting.LogFolder )
1148                                                 + BBS2CH_LOG_FOLDER + PATH_DELIM + BBSID + PATH_DELIM + FOLDER_INDEX_FILENAME;
1149 end;
1150
1151 // \83X\83\8c\97§\82Ä\91\97\90MURL
1152 function TBoard.GetSendURL: string;
1153 begin
1154         Result := GikoSys.UrlToServer(URL) + 'test/subbbs.cgi';
1155 end;
1156
1157 procedure TBoard.SetRound(b: Boolean);
1158 begin
1159         if b then
1160                 RoundList.Add(Self)
1161         else
1162                 RoundList.Delete(Self);
1163         if FRound = b then Exit;
1164         FRound := b;
1165         if FUpdate then
1166                 FModified := True;
1167 end;
1168
1169 procedure TBoard.SetRoundName(s: string);
1170 begin
1171         if FRoundName = s then Exit;
1172         FRoundName := s;
1173         if FUpdate then
1174                 FModified := True;
1175 end;
1176
1177 procedure TBoard.SetLastModified(d: TDateTime);
1178 begin
1179         if FLastModified = d then Exit;
1180         FLastModified := d;
1181         if FUpdate then
1182                 FModified := True;
1183 end;
1184
1185 procedure TBoard.SetLastGetTime(d: TDateTime);
1186 begin
1187         if FLastGetTime = d then Exit;
1188         FLastGetTime := d;
1189         if FUpdate then
1190                 FModified := True;
1191 end;
1192
1193 procedure TBoard.SetUnRead(i: Integer);
1194 begin
1195         if FUnRead = i then Exit;
1196         if i < 0 then i := 0;
1197         FUnRead := i;
1198         if FUpdate then
1199                 FModified := True;
1200 end;
1201
1202 procedure TBoard.SetKotehanName(s: string);
1203 begin
1204         if FKotehanName = s then Exit;
1205         FKotehanName := s;
1206         if FUpdate then
1207                 FModified := True;
1208 end;
1209
1210 procedure TBoard.SetKotehanMail(s: string);
1211 begin
1212         if FKotehanMail = s then Exit;
1213         FKotehanMail := s;
1214         if FUpdate then
1215                 FModified := True;
1216 end;
1217
1218 function TBoard.GetNewThreadCount: Integer;
1219 var
1220         i: Integer;
1221 begin
1222         Result := 0;
1223         if Length( ParentCategory.ParenTBBS.ShortSelectText ) = 0 then
1224         begin
1225                 for i := 0 to Count - 1 do begin
1226                         if Items[i].NewArrival then
1227                                 inc(Result);
1228                 end;
1229         end else begin
1230                 for i := 0 to Count - 1 do begin
1231                         if Items[i].NewArrival then
1232                         begin
1233                                 if Items[i].ShortTitle = '' then
1234                                         Items[i].ShortTitle := GikoSys.ZenToHan(Items[i].Title);
1235                                 if AnsiPos(ParentCategory.ParenTBBS.ShortSelectText, Items[i].ShortTitle) <> 0 then
1236                                         inc(Result);
1237                         end;
1238                 end;
1239         end;
1240 end;
1241
1242 function TBoard.GetLogThreadCount: Integer;
1243 var
1244         i: Integer;
1245 begin
1246         Result := 0;
1247         if Length( ParentCategory.ParenTBBS.ShortSelectText ) = 0 then
1248         begin
1249                 for i := 0 to Count - 1 do begin
1250                         if Items[i].IsLogFile then
1251                                 inc(Result);
1252                 end;
1253         end else begin
1254                 for i := 0 to Count - 1 do begin
1255                         if Items[i].IsLogFile then
1256                         begin
1257                                 if Items[i].ShortTitle = '' then
1258                                         Items[i].ShortTitle := GikoSys.ZenToHan(Items[i].Title);
1259                                 if AnsiPos(ParentCategory.ParenTBBS.ShortSelectText, Items[i].ShortTitle) <> 0 then
1260                                         inc(Result);
1261                         end;
1262                 end;
1263         end;
1264 end;
1265
1266 function TBoard.GetUserThreadCount: Integer;
1267 var
1268         i: Integer;
1269 begin
1270         Result := 0;
1271         if Length( ParentCategory.ParenTBBS.ShortSelectText ) = 0 then
1272                 Result := Count
1273         else
1274                 for i := 0 to Count - 1 do begin
1275                         if Items[i].ShortTitle = '' then
1276                                 Items[i].ShortTitle := GikoSys.ZenToHan(Items[i].Title);
1277                         if AnsiPos(ParentCategory.ParenTBBS.ShortSelectText, Items[i].ShortTitle) <> 0 then
1278                                 inc(Result);
1279                 end;
1280 end;
1281
1282 function TBoard.GetNewThread(Index: Integer): TThreadItem;
1283 var
1284         i: Integer;
1285         Cnt: Integer;
1286 begin
1287         Result := nil;
1288         Cnt := 0;
1289         if Length( ParentCategory.ParenTBBS.ShortSelectText ) = 0 then
1290         begin
1291                 for i := 0 to Count - 1 do begin
1292                         if Items[i].NewArrival then
1293                                                                         begin
1294                                 if Index = Cnt then begin
1295                                         Result := Items[i];
1296                                         Exit;
1297                                 end;
1298                                 inc(Cnt);
1299                         end;
1300                 end;
1301         end else begin
1302                 for i := 0 to Count - 1 do begin
1303                         if Items[i].NewArrival then
1304                         begin
1305                                 if Items[i].ShortTitle = '' then
1306                                         Items[i].ShortTitle := GikoSys.ZenToHan(Items[i].Title);
1307                                 if AnsiPos(ParentCategory.ParenTBBS.ShortSelectText, Items[i].ShortTitle) <> 0 then begin
1308                                         if Index = Cnt then begin
1309                                                 Result := Items[i];
1310                                                 Exit;
1311                                         end;
1312                                         inc(Cnt);
1313                                 end;
1314                         end;
1315                 end;
1316         end;
1317 end;
1318
1319 function TBoard.GetLogThread(Index: Integer): TThreadItem;
1320 var
1321         i: Integer;
1322         Cnt: Integer;
1323 begin
1324         Cnt := 0;
1325         if Length( ParentCategory.ParenTBBS.ShortSelectText ) = 0 then
1326         begin
1327                 for i := 0 to Count - 1 do begin
1328                         if Items[i].IsLogFile then
1329                                                                         begin
1330                                 if Index = Cnt then begin
1331                                         Result := Items[i];
1332                                         Exit;
1333                                 end;
1334                                 inc(Cnt);
1335                         end;
1336                 end;
1337         end else begin
1338                 for i := 0 to Count - 1 do begin
1339                         if Items[i].IsLogFile then
1340                                 begin
1341                                         if Items[i].ShortTitle = '' then
1342                                                 Items[i].ShortTitle := GikoSys.ZenToHan(Items[i].Title);
1343                                         if AnsiPos(ParentCategory.ParenTBBS.ShortSelectText, Items[i].ShortTitle) <> 0 then begin
1344                                                 if Index = Cnt then begin
1345                                                         Result := Items[i];
1346                                                         Exit;
1347                                         end;
1348                                         inc(Cnt);
1349                                 end;
1350                         end;
1351                 end;
1352         end;
1353         Result := nil;
1354 end;
1355
1356 function TBoard.GetUserThread(Index: Integer): TThreadItem;
1357 var
1358         i: Integer;
1359         Cnt: Integer;
1360 begin
1361         Result := nil;
1362         Cnt := 0;
1363         if Length( ParentCategory.ParenTBBS.ShortSelectText ) = 0 then
1364         begin
1365                 for i := 0 to Count - 1 do begin
1366                         if Index = Cnt then
1367                         begin
1368                                 Result := Items[ i ];
1369                                 Exit;
1370                         end;
1371                         inc( Cnt );
1372                 end;
1373         end else begin
1374                 for i := 0 to Count - 1 do begin
1375                         if Items[i].ShortTitle = '' then
1376                                 Items[i].ShortTitle := GikoSys.ZenToHan(Items[i].Title);
1377                         if AnsiPos(ParentCategory.ParenTBBS.ShortSelectText, Items[i].ShortTitle) <> 0 then begin
1378                                 if Index = Cnt then begin
1379                                         Result := Items[i];
1380                                         Exit;
1381                                 end;
1382                                 inc(Cnt);
1383                         end;
1384                 end;
1385         end;
1386 end;
1387
1388 procedure TBoard.BeginUpdate;
1389 begin
1390         FUpdate := False;
1391 end;
1392
1393 procedure TBoard.EndUpdate;
1394 begin
1395         FUpdate := True;
1396 end;
1397
1398 {class function TBoard.GetColumnName(Index: Integer): string;
1399 begin
1400         Result := COLUMN_THREADITEM[Index];
1401 end;
1402
1403 class function TBoard.GetColumnCount: Integer;
1404 begin
1405         Result := Length(COLUMN_THREADITEM);
1406 end;}
1407
1408 //constructor TThreadItem.Create(AOwner: TComponent);
1409 procedure TThreadItem.Init;
1410 begin
1411         FNo := 0;
1412         FFileName := '';
1413         FTitle := '';
1414         FRoundDate := ZERO_DATE;
1415         FLastModified := ZERO_DATE;
1416         FCount := 0;
1417         FAllResCount := 0;
1418         FNewResCount := 0;
1419         FSize := 0;
1420         FRound := False;
1421         FIsLogFile := False;
1422         FParentBoard := nil;
1423         FKokomade := -1;
1424         FNewReceive := 0;
1425         FNewArrival := False;
1426
1427         FUpdate := True;
1428         FURL := '';
1429         FBoardPlugIn := nil;
1430 end;
1431
1432 // *************************************************************************
1433 // \8aO\95\94\94Â\83v\83\89\83O\83C\83\93\82ð\8ew\92è\82µ\82½\83R\83\93\83X\83g\83\89\83N\83^
1434 // *************************************************************************
1435 constructor TThreadItem.Create(
1436         inPlugIn        : TBoardPlugIn;
1437         inURL                   : string
1438 );
1439 var
1440         foundPos                        : Integer;
1441         protocol, host, path, document, port, bookmark  : string;
1442         BBSID, BBSKey   : string;
1443 const
1444         READ_PATH                                                       = '/test/read.cgi';
1445 begin
1446
1447         inherited Create;
1448         Init;
1449
1450         FBoardPlugIn    := inPlugIn;
1451         URL                                             := inURL;
1452
1453         if inPlugIn = nil then begin
1454                 foundPos := Pos( READ_PATH, inURL );
1455                 if foundPos > 0 then begin
1456                         // dat \82Ì\95Û\91\83p\83X\82ð\90Ý\92è
1457                         GikoSys.ParseURI( inURL, protocol, host, path, document, port, bookmark );
1458                         GikoSys.Parse2chURL( inURL, path, document, BBSID, BBSKey );
1459                         if GikoSys.Is2chHost( host ) then
1460                                 FilePath :=
1461                                         IncludeTrailingPathDelimiter( GikoSys.Setting.LogFolder ) +
1462                                         BBS2CH_LOG_FOLDER + PATH_DELIM + BBSID + PATH_DELIM + BBSKey + '.dat'
1463                         else
1464                                 FilePath :=
1465                                         IncludeTrailingPathDelimiter( GikoSys.Setting.LogFolder ) +
1466                                         EXTERNAL_LOG_FOLDER + PATH_DELIM + host + PATH_DELIM + BBSID + PATH_DELIM + BBSKey + '.dat';
1467                         FileName        := BBSKey + '.dat';
1468                         IsLogFile       := FileExists( FilePath );
1469                         URL                             := GikoSys.Get2chBrowsableThreadURL( inURL );
1470                 end;
1471         end else begin
1472                 // \83v\83\89\83O\83C\83\93\82É TThreadItem \82ª\8dì\90¬\82³\82ê\82½\82±\82Æ\82ð\93`\82¦\82é
1473                 inPlugIn.CreateThreadItem( DWORD( Self ) );
1474         end;
1475
1476 end;
1477
1478 // *************************************************************************
1479 // \83f\83X\83g\83\89\83N\83^
1480 // *************************************************************************
1481 destructor TThreadItem.Destroy;
1482 begin
1483
1484         // \83v\83\89\83O\83C\83\93\82É TThreadItem \82ª\94j\8aü\82³\82ê\82½\82±\82Æ\82ð\93`\82¦\82é
1485         if IsBoardPlugInAvailable then
1486                 FBoardPlugIn.DisposeThreadItem( DWORD( Self ) );
1487
1488         inherited;
1489
1490 end;
1491
1492 // *************************************************************************
1493 // \8aO\95\94\94Â\83v\83\89\83O\83C\83\93\82ª\8eg\97p\89Â\94\\82©
1494 // *************************************************************************
1495 function        TThreadItem.IsBoardPlugInAvailable : Boolean;
1496 begin
1497
1498         repeat
1499                 if BoardPlugIn = nil then
1500                         Break;
1501
1502                 if not Assigned( Pointer( BoardPlugIn.Module ) ) then
1503                         Break;
1504
1505                 Result := True;
1506                 Exit;
1507         until True;
1508
1509         Result := False;
1510
1511 end;
1512
1513 function TThreadItem.GetDatURL: string;
1514 var
1515         Protocol, Host, Path, Document, Port, Bookmark: string;
1516 begin
1517         Result := ParentBoard.URL
1518                                         + 'dat/'
1519                                         + FileName;
1520         if FDownloadHost <> '' then begin
1521                 GikoSys.ParseURI(Result, Protocol, Host, Path, Document, Port, Bookmark);
1522                 Result := Format('%s://%s%s%s', [Protocol,
1523                                                                                                                                                  FDownloadHost,
1524                                                                                                                                                  Path,
1525                                                                                                                                                  Document]);
1526         end;
1527 //      Result := GikoSys.UrlToServer(ParentBoard.URL)
1528 //                                      + 'test/read.cgi/' + ParentBoard.BBSID + '/'
1529 //                                      + ChangeFileExt(FileName, '') + '/?raw='
1530 //                                      + IntToStr(ResNum) + '.' + IntToStr(ResSize);
1531 end;
1532
1533 function TThreadItem.GetDatgzURL: string;
1534         function isOldKako(s: string): Boolean;
1535         begin
1536                 Result := False;
1537                 if AnsiPos('piza.', s) <> 0 then
1538                         Result := True
1539                 else if AnsiPos('www.bbspink.', s) <> 0 then
1540                         Result := True
1541                 else if AnsiPos('tako.', s) <> 0 then
1542                         Result := True;
1543         end;
1544 var
1545         Protocol, Host, Path, Document, Port, Bookmark: string;
1546         DatNo: string;
1547 begin
1548         if FDownloadHost = '' then begin
1549                 DatNo := ChangeFileExt(FileName, '');
1550                 if isOldKako(ParentBoard.URL) then begin
1551                         Result := Format('%s%s/%.3s/%s.dat', [ParentBoard.URL, 'kako', DatNo, DatNo]);
1552                 end else begin
1553                         if Length(DatNo) > 9 then begin
1554                                 //http://xxx.2ch.net/xxx/kako/9999/99999/999999999.dat.gz
1555                                 Result := Format('%s%s/%.4s/%.5s/%s.dat.gz', [ParentBoard.URL, 'kako', DatNo, DatNo, DatNo]);
1556                         end else begin
1557                                 //http://xxx.2ch.net/xxx/kako/999/999999999.dat.gz
1558                                 Result := Format('%s%s/%.3s/%s.dat.gz', [ParentBoard.URL, 'kako', DatNo, DatNo]);
1559                         end;
1560                 end;
1561         end else begin
1562                 Gikosys.ParseURI(Result, Protocol, Host, Path, Document, Port, Bookmark);
1563                 DatNo := ChangeFileExt(Document, '');
1564                 if isOldKako(DownloadHost) then begin
1565                         Result := Format('%s://%s/%s/kako/%.3s/%s.dat', [Protocol, DownloadHost, ParentBoard.FBBSID, DatNo, DatNo]);
1566                 end else begin
1567                         if Length(DatNo) > 9 then begin
1568                                 Result := Format('%s://%s/%s/kako/%.4s/%.5s/%s.dat.gz', [Protocol, DownloadHost, ParentBoard.FBBSID, DatNo, DatNo, DatNo]);
1569                         end else begin
1570                                 Result := Format('%s://%s/%s/kako/%.3s/%s.dat.gz', [Protocol, DownloadHost, ParentBoard.FBBSID, DatNo, DatNo]);
1571                         end;
1572                 end;
1573         end;
1574 end;
1575
1576 {function TThreadItem.GetOldDatgzURL: string;
1577 var
1578         Protocol, Host, Path, Document, Port, Bookmark: string;
1579 begin
1580         Result := Format('%s%s/%.3s/%s.gz', [ParentBoard.URL,
1581                                                                                                                                                          'kako',
1582                                                                                                                                                          FileName,
1583                                                                                                                                                          FileName]);
1584         if FDownloadHost <> '' then begin
1585                 ParseURI(Result, Protocol, Host, Path, Document, Port, Bookmark);
1586                 Result := Format('%s://%s%s%s', [Protocol,
1587                                                                                                                                                  DownloadHost,
1588                                                                                                                                                  Path,
1589                                                                                                                                                  Document]);
1590
1591         end;
1592 end;}
1593
1594 function TThreadItem.GetOfflawCgiURL(const SessionID: string): string;
1595 //var
1596 //      Protocol, Host, Path, Document, Port, Bookmark: string;
1597 begin
1598 //      Result := GikoSys.UrlToServer(ParentBoard.URL)
1599 //                                      + 'test/offlaw.cgi/' + ParentBoard.BBSID + '/'
1600 //                                      + ChangeFileExt(FileName, '') + '/?raw=.0&sid=' + HttpEncode(SessionID);
1601         if FDownloadHost = '' then begin
1602                 Result := GikoSys.UrlToServer(ParentBoard.URL)
1603                                                 + 'test/offlaw.cgi/' + ParentBoard.BBSID + '/'
1604                                                 + ChangeFileExt(FileName, '') + '/?raw=.0&sid=' + HttpEncode(SessionID);
1605         end else begin
1606                 //http://news.2ch.net/test/offlaw.cgi/newsplus/1014038577/?raw=.196928&sid=
1607                 //GikoSys.ParseURI(Result, Protocol, Host, Path, Document, Port, Bookmark);
1608                 Result := 'http://' + FDownloadHost
1609                                                 + '/test/offlaw.cgi/' + ParentBoard.BBSID + '/'
1610                                                 + ChangeFileExt(FileName, '') + '/?raw=.0&sid=' + HttpEncode(SessionID);
1611 //              Result := Format('%s://%s%s%s', [Protocol,
1612 //                                                                                                                                               DownloadHost,
1613 //                                                                                                                                               Path,
1614 //                                                                                                                                               Document]);
1615         end;
1616 end;
1617
1618 function TThreadItem.GetSendURL: string;
1619 begin
1620         Result := GikoSys.UrlToServer(ParentBoard.URL)
1621                                         + 'test/bbs.cgi';
1622 end;
1623
1624 procedure TThreadItem.DeleteLogFile;
1625 begin
1626         ParentBoard.BeginUpdate;
1627
1628         DeleteFile(GetThreadFileName);
1629                 if FileExists(ChangeFileExt(GetThreadFileName,'.NG')) = true then
1630                         DeleteFile(ChangeFileExt(GetThreadFileName,'.NG'));
1631         FRoundDate := ZERO_DATE;
1632         FLastModified := ZERO_DATE;
1633         FSize := 0;
1634         FIsLogFile := False;
1635         FKokomade := -1;
1636         FNewReceive := 0;
1637         FNewArrival := False;
1638         FUnRead := False;
1639         FScrollTop := 0;
1640         FRound := False;
1641         FDownloadHost := '';
1642         FAgeSage := gasNone;
1643
1644         FCount := 0;
1645         FNewResCount := 0;
1646         FRoundName := '';
1647
1648         ParentBoard.EndUpdate;
1649         ParentBoard.Modified := True;
1650 end;
1651
1652 function TThreadItem.GetThreadFileName: string;
1653 begin
1654         if Length( FilePath ) > 0 then
1655                 Result := FilePath
1656         else
1657                 Result := IncludeTrailingPathDelimiter( GikoSys.Setting.LogFolder )
1658                                                 + BBS2CH_LOG_FOLDER + PATH_DELIM + ParentBoard.BBSID + PATH_DELIM + FileName;
1659 end;
1660
1661 procedure TThreadItem.SetLastModified(d: TDateTime);
1662 begin
1663         if FLastModified = d then Exit;
1664         FLastModified := d;
1665         if FUpdate and (ParentBoard <> nil) then
1666                 ParentBoard.FModified := True;
1667 end;
1668
1669 {procedure TThreadItem.SetRoundNo(i: Integer);
1670 begin
1671         if FRoundNo = i then Exit;
1672         FRoundNo := i;
1673         if FUpdate and (ParentBoard <> nil) then
1674                 ParentBoard.FModified := True;
1675 end;}
1676
1677 procedure TThreadItem.SetRound(b: Boolean);
1678 begin
1679         if b then
1680                 RoundList.Add(Self)
1681         else
1682                 RoundList.Delete(Self);
1683         if FRound = b then Exit;
1684         FRound := b;
1685         if FUpdate and (ParentBoard <> nil) then
1686                 ParentBoard.FModified := True;
1687 end;
1688
1689 procedure TThreadItem.SetRoundName(const s: string);
1690 begin
1691         if FRoundName = s then Exit;
1692         FRoundName := s;
1693         if FUpdate and (ParentBoard <> nil) then
1694                 ParentBoard.FModified := True;
1695 end;
1696
1697 procedure TThreadItem.SetKokomade(i: Integer);
1698 begin
1699         if FKokomade = i then Exit;
1700         FKokomade := i;
1701         if FUpdate and (ParentBoard <> nil) then
1702                 ParentBoard.FModified := True;
1703 end;
1704
1705 procedure TThreadItem.SetUnRead(b: Boolean);
1706 begin
1707         if FUnRead = b then Exit;
1708         FUnRead := b;
1709         if FUpdate and (ParentBoard <> nil) then
1710                 ParentBoard.FModified := True;
1711 end;
1712
1713 procedure TThreadItem.SetScrollTop(i: Integer);
1714 begin
1715         if FScrollTop = i then Exit;
1716         FScrollTop := i;
1717         if FUpdate and (ParentBoard <> nil) then
1718                 ParentBoard.FModified := True;
1719 end;
1720
1721 procedure TThreadItem.BeginUpdate;
1722 begin
1723         FUpdate := False;
1724 end;
1725
1726 procedure TThreadItem.EndUpdate;
1727 begin
1728         FUpdate := True;
1729 end;
1730
1731 {initialization
1732         BBS2ch := TBBS.Create;
1733
1734 finalization
1735         if BBS2ch <> nil then
1736                 BBS2ch.Free;}
1737 function TThreadItem.GetCreateDate: TDateTime;
1738 var
1739         unixtime: Int64;
1740     tmp: string;
1741 begin
1742         // \83t\83@\83C\83\8b\96¼\82©\82ç\83X\83\8c\8dì\90¬\93ú\8e\9e\82ð\8b\81\82ß\82é
1743         try
1744                 if ( GikoSys.Setting.CreationTimeLogs ) and not IsLogFile  then
1745             Result := ZERO_DATE
1746         else begin
1747             // \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
1748                         tmp := ChangeFileExt(FFileName, '');
1749                         if AnsiPos('_', tmp) <> 0 then
1750                                 if AnsiPos('_', tmp) > 9 then
1751                                         tmp := Copy(tmp, 1, AnsiPos('_', tmp)-1)
1752                                 else
1753                                         Delete(tmp, AnsiPos('_', tmp), 1);
1754
1755                         if ( Length(tmp) = 9) and ( tmp[1] = '0' ) then
1756                                 Insert('1', tmp, 1);
1757
1758
1759                         unixtime := StrToInt64(tmp);
1760                 Result := UnixToDateTime(unixtime) + OffsetFromUTC;
1761                         if GikoSys.Setting.FutureThread then begin
1762                         if CompareDateTime(Result, Now) = 1 then
1763                         Result := ZERO_DATE;
1764                 end;
1765         end;
1766
1767         except
1768                 on E: Exception do
1769                         Result := ZERO_DATE;
1770         end;
1771 end;
1772
1773 end.
1774