6 Messages, SysUtils, Classes, Contnrs, ComCtrls, {HttpApp,} YofUtils,
7 GikoSystem{, XMLIntf, XMLDoc}, GikoXMLDoc, BoardGroup, windows;
8 {SAX, SAXHelpers, SAXComps, SAXKW;}
11 TFavoriteFolder = class
14 TFavoriteItem = class(TObject)
19 function GetItemTitle : string; virtual;abstract;
20 property URL : string read FURL write FURL; // Item
\82ª
\8eæ
\93¾
\82Å
\82«
\82È
\82
\82Ä
\82à URL
\82Í
\8fí
\82É
\95Û
\8e\9d\82³
\82ê
\82é
21 property Title : string read FTitle write FTitle;
23 TFavoriteBoardItem = class(TFavoriteItem)
26 function GetItem : TBoard;
28 constructor Create( inURL : string; inTitle : string = ''; inItem : TBoard = nil );
29 constructor CreateWithItem( inItem : TBoard );
31 function GetItemTitle : string; override;
32 property Item : TBoard read GetItem write FItem;
35 TFavoriteThreadItem = class(TFavoriteItem)
38 function GetItem : TThreadItem;
40 constructor Create( inURL : string; inTitle : string = ''; inItem : TThreadItem = nil );
41 constructor CreateWithItem( inItem : TThreadItem );
43 function GetItemTitle : string; override;
44 property Item : TThreadItem read GetItem write FItem;
47 TFavoriteDM = class(TDataModule)
53 procedure ReadNode(Node: IXMLNode; Stack: TStack; TreeView: TTreeView);
54 procedure AddSaveString(Node: TTreeNode; SaveList: TStringList);
58 function GetFavoriteFilePath() : String;
59 function SaveFavoriteFile(FileName: String) : Boolean;
60 procedure SetFavTreeView(TreeView: TTreeView);
61 procedure ReadFavorite;
62 procedure WriteFavorite;
63 procedure URLReplace(oldURLs: TStringList; newURLs: TStringList);
64 property TreeView: TTreeView read FTreeView;
65 property Modified: boolean read FModified write FModified;
66 property AbEnd: Boolean read FAbEnd write FAbEnd;
70 FavoriteDM: TFavoriteDM;
72 FAVORITE_LINK_NAME = '
\83\8a\83\93\83N';
73 FAVORITE_FILE_NAME = 'Favorite.xml';
77 uses ExternalBoardManager, ExternalBoardPlugInMain, MojuUtils;
80 FAVORITE_ROOT_NAME = '
\82¨
\8bC
\82É
\93ü
\82è';
85 constructor TFavoriteBoardItem.Create(
87 inTitle : string = '';
100 constructor TFavoriteBoardItem.CreateWithItem(
105 Create( inItem.URL, inItem.Title, inItem );
108 destructor TFavoriteBoardItem.Destory;
114 //!
\95Û
\8e\9d\82µ
\82Ä
\82¢
\82é
\94Â
\82Ì
\83^
\83C
\83g
\83\8b\82ð
\95Ô
\82·
115 function TFavoriteBoardItem.GetItemTitle : string;
118 //
\88ê
\93x
\82à
\94Â
\82ð
\8aJ
\82¢
\82Ä
\82¢
\82È
\82¢
\82Æ
\82«
\81i
\8bN
\93®
\8e\9e\82É
\83L
\83\83\83r
\83l
\83b
\83g
\82ð
\82¨
\8bC
\82É
\93ü
\82è
\82Æ
\82©
\81j
119 //
\82Ì
\82Æ
\82«
\82ÉFItem
\82ªnil
\82È
\82Ì
\82Å
\82»
\82Ì
\82Æ
\82«
\82Í
\82×
\82Á
\82Æ
\8c\9f\8dõ
120 if FItem = nil then begin
121 FItem := BBSsFindBoardFromURL(URL);
123 if FItem <> nil then begin
125 if not FItem.IsThreadDatRead then begin
126 GikoSys.ReadSubjectFile(FItem);
130 Result := FItem.Title;
133 function TFavoriteBoardItem.GetItem : TBoard;
135 protocol, host, path, document, port, bookmark : string;
140 if FItem = nil then begin
141 FItem := BBSsFindBoardFromURL( URL );
142 if FItem = nil then begin
144 GikoSys.ParseURI( tmpURL, protocol, host, path, document, port, bookmark );
145 if GikoSys.Is2chHost( host ) then begin
146 BBSID := GikoSys.URLToID( tmpURL );
147 FItem := BBSs[ 0 ].FindBBSID( BBSID );
152 //
\81¦
\8dì
\82Á
\82Ä
\82à
\81A
\92Ç
\89Á
\82·
\82é
\83J
\83e
\83S
\83\8a\82ª
\96³
\82¢
\82Ì
\82Å
\8c\83\82µ
\82
\95Û
\97¯
153 FItem := GikoSys.GetUnknownBoard( nil, URL );
154 FItem.Title := Title;
163 constructor TFavoriteThreadItem.Create(
165 inTitle : string = '';
166 inItem : TThreadItem = nil
178 constructor TFavoriteThreadItem.CreateWithItem(
183 Create( inItem.URL, inItem.Title, inItem );
186 destructor TFavoriteThreadItem.Destory;
192 //!
\95Û
\8e\9d\82µ
\82Ä
\82¢
\82é
\83X
\83\8c\82Ì
\83^
\83C
\83g
\83\8b\82ð
\95Ô
\82·
193 function TFavoriteThreadItem.GetItemTitle : string;
196 if FItem = nil then begin
197 FItem := BBSsFindThreadFromURL(URL);
199 if FItem <> nil then begin
200 Result := FItem.Title;
204 function TFavoriteThreadItem.GetItem : TThreadItem;
208 browsableURL : string;
209 protocol, host, path, document, port, bookmark : string;
210 BBSID, BBSKey : string;
215 if FItem = nil then begin
216 browsableURL := GikoSys.GetBrowsableThreadURL( URL );
217 boardURL := GikoSys.GetThreadURL2BoardURL( browsableURL );
218 board := BBSsFindBoardFromURL( boardURL );
220 if board = nil then begin
222 GikoSys.ParseURI( tmpURL, protocol, host, path, document, port, bookmark );
223 if GikoSys.Is2chHost( host ) then begin
224 GikoSys.Parse2chURL( tmpURL, path, document, BBSID, BBSKey );
225 board := BBSs[ 0 ].FindBBSID( BBSID );
228 if board = nil then begin
230 //
\81¦
\8dì
\82Á
\82Ä
\82à
\81A
\92Ç
\89Á
\82·
\82é
\83J
\83e
\83S
\83\8a\82ª
\96³
\82¢
\82Ì
\82Å
\8c\83\82µ
\82
\95Û
\97¯
231 //board := GikoSys.GetUnknownBoard( nil, boardURL )
235 FItem := board.FindThreadFromURL( browsableURL );
237 if FItem = nil then begin
239 GikoSys.ParseURI( tmpURL, protocol, host, path, document, port, bookmark );
240 if GikoSys.Is2chHost( host ) then begin
241 GikoSys.Parse2chURL( tmpURL, path, document, BBSID, BBSKey );
242 FItem := BBSs[ 0 ].FindThreadItem( BBSID, BBSKey + '.dat' );
248 if FItem = nil then begin
249 FItem := TThreadItem.Create( board.BoardPlugIn, board, browsableURL );
251 FItem.Title := Title;
260 procedure TFavoriteDM.Clear;
264 TreeView.Items.BeginUpdate;
265 Node := TreeView.Items.GetFirstNode;
266 while Node <> nil do begin
267 if TObject(Node.Data) <> nil then
268 TObject(Node.Data).Free;
269 Node := Node.GetNext;
271 TreeView.Items.Clear;
272 TreeView.Items.EndUpdate;
274 FavoriteDM.Modified := true;
277 procedure TFavoriteDM.SetFavTreeView(TreeView: TTreeView);
279 FTreeView := TreeView;
282 procedure TFavoriteDM.ReadFavorite;
285 XMLDoc: IXMLDocument;
289 FavFolder: TFavoriteFolder;
295 FavoriteDM.Modified := true;
296 FileName := GikoSys.GetConfigDir + FAVORITE_FILE_NAME;
298 FavFolder := TFavoriteFolder.Create;
299 Node := FTreeView.Items.AddChildObjectFirst(nil, FAVORITE_ROOT_NAME, FavFolder);
300 Node.ImageIndex := 14;
301 Node.SelectedIndex := 14;
303 if FileExists(FileName) then begin
305 XMLDoc := IXMLDocument.Create;
306 //XMLDoc := LoadXMLDocument(FileName);
307 LoadXMLDocument(FileName, XMLDoc);
308 XMLNode := XMLDoc.DocumentElement;
310 Stack := TStack.Create;
314 if XMLNode.NodeName = 'favorite' then begin
315 for i := XMLNode.ChildNodes.Count - 1 downto 0 do begin
316 ReadNode(XMLNode.ChildNodes[i], Stack, FTreeView);
317 if (XMLNode.ChildNodes[i].NodeName = 'folder') and
318 (XMLNode.ChildNodes[i].Attributes['title'] = FAVORITE_LINK_NAME) then begin
323 if not LinkExists then begin
324 FavFolder := TFavoriteFolder.Create;
325 Node := FTreeView.Items.AddChildObjectFirst(Node, FAVORITE_LINK_NAME, FavFolder);
326 Node.ImageIndex := 14;
327 Node.SelectedIndex := 14;
335 on e : Exception do begin
343 procedure TFavoriteDM.ReadNode(Node: IXMLNode; Stack: TStack; TreeView: TTreeView);
347 ParentNode: TTreeNode;
348 CurrentNode: TTreeNode;
349 FavFolder: TFavoriteFolder;
350 FavBoard: TFavoriteBoardItem;
351 FavThread: TFavoriteThreadItem;
353 threadItem : TThreadItem;
355 if Node.NodeName = 'folder' then begin
357 ParentNode := Stack.Peek;
358 if TObject(ParentNode.Data) is TFavoriteFolder then begin
359 FavFolder := TFavoriteFolder.Create;
360 CurrentNode := TreeView.Items.AddChildObjectFirst(ParentNode, Node.Attributes['title'], FavFolder);
361 CurrentNode.ImageIndex := 14;
362 CurrentNode.SelectedIndex := 14;
363 Stack.Push(CurrentNode);
365 for i := Node.ChildNodes.Count - 1 downto 0 do begin
366 ReadNode(Node.ChildNodes[i], Stack, TreeView);
368 if CurrentNode <> nil then
369 CurrentNode.Expanded := Node.Attributes[ 'expanded' ] = 'true';
370 if Stack.Count <> 0 then
372 end else if Node.NodeName = 'favitem' then begin
374 ParentNode := Stack.Peek;
375 if TObject(ParentNode.Data) is TFavoriteFolder then begin
376 if Node.Attributes['favtype'] = 'board' then begin
378 //
\8b\8c\8e®
\82Ì
\82¨
\8bC
\82É
\93ü
\82è
\82Æ
\82Ì
\8cÝ
\8a·
\90«
\82Ì
\82½
\82ß
379 if Length( Node.Attributes[ 'bbs' ] ) > 0 then begin
380 board := BBSsFindBoardFromBBSID( Node.Attributes[ 'bbs' ] );
382 FavBoard := TFavoriteBoardItem.Create(
383 board.URL, MojuUtils.UnSanitize(Node.Attributes[ 'title' ]), board );
385 FavBoard := TFavoriteBoardItem.Create(
386 Node.Attributes[ 'url' ], MojuUtils.UnSanitize(Node.Attributes[ 'title' ]), nil );
388 CurrentNode := TreeView.Items.AddChildObjectFirst(ParentNode, UnSanitize(Node.Attributes['title']), FavBoard);
389 CurrentNode.ImageIndex := 15;
390 CurrentNode.SelectedIndex := 15;
391 end else if Node.Attributes['favtype'] = 'thread' then begin
392 //
\8b\8c\8e®
\82Ì
\82¨
\8bC
\82É
\93ü
\82è
\82Æ
\82Ì
\8cÝ
\8a·
\90«
\82Ì
\82½
\82ß
393 if Length( Node.Attributes[ 'bbs' ] ) > 0 then begin
394 board := BBSsFindBoardFromBBSID( Node.Attributes[ 'bbs' ] );
398 if not board.IsThreadDatRead then
399 GikoSys.ReadSubjectFile( board );
400 threadItem := board.FindThreadFromFileName( Node.Attributes[ 'thread' ] );
401 if threadItem = nil then begin
402 threadItem := TThreadItem.Create(
405 GikoSys.Get2chBoard2ThreadURL( board, ChangeFileExt( Node.Attributes[ 'thread' ], '' ) ) );
406 threadItem.Title := UnSanitize(Node.Attributes[ 'title' ]);
407 board.Add( threadItem );
409 FavThread := TFavoriteThreadItem.Create(
410 threadItem.URL, UnSanitize(Node.Attributes[ 'title' ]), threadItem );
413 FavThread := TFavoriteThreadItem.Create(
414 Node.Attributes[ 'url' ], UnSanitize(Node.Attributes[ 'title' ]), nil );
416 CurrentNode := TreeView.Items.AddChildObjectFirst(ParentNode, UnSanitize(Node.Attributes['title']), FavThread);
417 CurrentNode.ImageIndex := 16;
418 CurrentNode.SelectedIndex := 16;
422 //
\82±
\82Ì
\83A
\83C
\83e
\83\80\82Å
\96â
\91è
\82ª
\8bN
\82«
\82Ä
\82à
\91¼
\82Ì
\83A
\83C
\83e
\83\80\82É
\89e
\8b¿
\82ð
\97^
\82¦
\82½
\82
\82È
\82¢
\82Ì
\82Å
427 procedure TFavoriteDM.WriteFavorite;
429 FileName, tmpFileName, bakFileName: string;
430 SaveList: TStringList;
431 Buffer: array[0..MAX_PATH] of Char; //
\83o
\83b
\83t
\83@
434 FavoriteDM.Modified := true;
435 FileName := GikoSys.GetConfigDir + FAVORITE_FILE_NAME;
436 SaveList := TStringList.Create;
438 //
\8f\91\82«
\8d\9e\82Ý
\97p
\88ê
\8e\9e\83t
\83@
\83C
\83\8b\8eæ
\93¾
439 if GetTempFileName(PChar(GikoSys.GetConfigDir), PChar('fav'), 0, Buffer) <> 0 then begin
440 tmpFileName := Buffer;
443 SaveList.Add('<?xml version="1.0" encoding="Shift_JIS" standalone="yes"?>');
444 SaveList.Add('<favorite>');
445 AddSaveString(TreeView.Items.GetFirstNode.getFirstChild, SaveList);
446 SaveList.Add('</favorite>');
447 //
\88ê
\8e\9e\83t
\83@
\83C
\83\8b\82Æ
\82µ
\82Ä
\95Û
\91¶
448 SaveList.SaveToFile(tmpFileName);
450 //
\91O
\82Ì
\83t
\83@
\83C
\83\8b\82ð
\88Ú
\93®
\82·
\82é
451 if FileExists(FileName) then begin
452 bakFileName := GikoSys.GetConfigDir + '~' + FAVORITE_FILE_NAME;
453 if FileExists(bakFileName) then begin
454 FileRep := SysUtils.DeleteFile(bakFileName); //SysUtils.
\82ð
\82Â
\82¯
\82È
\82¢
\82ÆWinAPI
\82Æ
\8bæ
\95Ê
\82Å
\82«
\82È
\82¢
\82Ì
\82Å
456 if FileRep then begin
457 FileRep := RenameFile(FileName, bakFileName);
460 //
\90³
\8bK
\82Ì
\83t
\83@
\83C
\83\8b\96¼
\82É
\83\8a\83l
\81[
\83\80\82·
\82é
461 if FileRep then begin
462 FileRep := RenameFile(tmpFileName, FileName);
472 procedure TFavoriteDM.AddSaveString(Node: TTreeNode; SaveList: TStringList);
475 FavBoard: TFavoriteBoardItem;
476 FavThread: TFavoriteThreadItem;
479 while Node <> nil do begin
481 if TObject(data) is TFavoriteFolder then begin
482 if Node.Expanded then
483 s := Format('<folder title="%s" expanded="true">', [HtmlEncode(Node.Text)])
485 s := Format('<folder title="%s" expanded="false">', [HtmlEncode(Node.Text)]);
487 AddSaveString(Node.getFirstChild, SaveList);
488 SaveList.Add('</folder>');
489 end else if TObject(data) is TFavoriteBoardItem then begin
490 FavBoard := TFavoriteBoardItem(data);
491 s := Format('<favitem type="2ch" favtype="board" url="%s" title="%s"/>',
492 [HtmlEncode( FavBoard.URL ), HtmlEncode(MojuUtils.Sanitize(Node.Text))]);
494 end else if TObject(data) is TFavoriteThreadItem then begin
495 FavThread := TFavoriteThreadItem(data);
496 s := Format('<favitem type="2ch" favtype="thread" url="%s" title="%s"/>',
497 [HtmlEncode( FavThread.URL ), HtmlEncode(MojuUtils.Sanitize(Node.Text))]);
500 Node := Node.getNextSibling;
504 function TFavoriteDM.SaveFavoriteFile(FileName: String) : Boolean;
506 FavoriteFilePath: string;
507 tempStringList: TStringList;
510 FavoriteFilePath := GikoSys.GetConfigDir + FAVORITE_FILE_NAME;
512 if FileExists( FavoriteFilePath ) then begin
513 tempStringList := TStringList.Create;
515 tempStringList.LoadFromFile( FavoriteFilePath );
516 tempStringList.SaveToFile( FileName );
526 procedure TFavoriteDM.URLReplace(oldURLs: TStringList; newURLs: TStringList);
531 oldBoardName: string;
533 newBoardName: string;
535 favBoard : TFavoriteBoardItem;
536 favThread : TFavoriteThreadItem;
537 favorites : TTreeNodes;
541 //
\96Ê
\93|
\82¾
\82¯
\82Çthread
\82Í
\82»
\82ê
\82¼
\82êURL
\82ð
\83`
\83F
\83b
\83N
\82µ
\82È
\82ª
\82ç
\82â
\82Á
\82Ä
\82©
\82È
\82«
\82á
\82¢
\82¯
\82È
\82¢
\81B
542 favorites := FavoriteDM.FTreeView.Items;
543 for i := 0 to oldURLs.Count - 1 do begin
545 tmpURL := Copy(oldURLs[i], 1, Length(oldURLs[i]) -1);
546 oldHost := Copy(tmpURL, 1, LastDelimiter('/', tmpURL) );
547 oldBoardName := Copy(tmpURL, LastDelimiter('/', tmpURL), Length(tmpURL) ) + '/';
548 tmpURL := Copy(newURLs[i], 1, Length(newURLs[i]) -1);
549 newHost := Copy(tmpURL, 1, LastDelimiter('/', tmpURL) );
550 newBoardName := Copy(tmpURL, LastDelimiter('/', tmpURL), Length(tmpURL) ) + '/';
552 Node := favorites.GetFirstNode.getFirstChild;
553 while Node <> nil do begin
555 if TObject( Node.Data ) is TFavoriteBoardItem then begin
556 favBoard := TFavoriteBoardItem( Node.Data );
557 if favBoard = nil then continue;
558 tempString := favBoard.URL;
559 if ( AnsiPos(oldBoardName, tempString) <> 0 ) and ( AnsiPos(oldHost, tempString ) <> 0 ) then begin
560 tempString := StringReplace(tempString, oldHost, newHost,[]);
561 favBoard.URL := tempString;
563 end else if TObject( Node.Data ) is TFavoriteThreadItem then begin
564 favThread := TFavoriteThreadItem( Node.Data );
565 if favThread = nil then continue;
566 tempString := favThread.URL;
567 if ( AnsiPos(oldBoardName, tempString) <> 0 ) and ( AnsiPos(oldHost, tempString ) <> 0 ) then begin
568 tempString := StringReplace(tempString, oldHost, newHost,[]);
569 favThread.URL := tempString;
574 Node := Node.GetNext;
582 function TFavoriteDM.GetFavoriteFilePath() : String;
584 Result := GikoSys.GetConfigDir + FAVORITE_FILE_NAME;