Searching for favourites

Uses TSearchRec to loop through the Explorer favourites, which really are inifiles. Result is beeing placed in HTML and text files.

NOTE: This article is a couple of years old. And while the code still works fine as an example of using inifiles and recursive searches - Internet Explorer has had export possibilities built into the program.



**



Collecting Explorer Favourites



Johan Lindgren



Recently a person at work was leaving for another company. Beeing a journalist, she was very interested in bringing the long list of favourite internet links that she had collected during her time with us. This is really a valueble journalistic tool these days. Well, if she were going to a company also equiped with Windows and Explorer you could simply copy the folder holding the favourites. But since she was going to a MAC-based company using Netscape it was a different situation. There might be a way in Explorer to do this. And there might be programs out there doing this. But I found none so I did a program to do it. What the program does is simply recursively search the folder with the Explorer favourites and adding it all to a textfile and a HTML-file. The big advantage with storing the result in the HTML-format is that you can make the links active and thus the file useful in any browser.



First of all there is an ini-file with settings for the searchpath to the favourites and the searchpath and names of the files where the result is to be stored. The file is named "favoriter.ini" and is placed in the same folder as the exe-file. (Some words you encounter are in Swedish!)



The inifile:

[Favoriter]

WindowsFavoriter=c:\windows\favoriter\

HTMLsave=c:\favoriter.html

TEXTsave=c:\favoriter.txt



It is important to get the search path right for the program to work.



The program consist of a richedit to hold the text result, a button to start, a button to close and a status bar. (Which is not necessary at all.)





The operation is pretty straight forward. When you click the start button the code attached to that button is executed. The search starts and if a subfolder is encountered a separate procedure is called. This procedure is recalled for each subfolder encountered. So the program will search out every subfolder.



This is search block from the click event. The routine in the procedure is very similar. (See the complete program listing.)



    test := FindFirst(sokmapp+'*.*', faAnyFile, SearchRec); //See if we get any result from our first search

    if test = 0 then //if we got a result. Indicated by a 0 in the FindFirst function!!

      while test = 0 do begin //As long as we get 0's from our Searches there are more files or folders to process

        case searchrec.Attr of //Check to see what attribute the searchresult had

          16 : begin //If it was a 16 it is a sub folder

            if (searchrec.name <> '.') and (searchrec.name <> '..') then //Check to see that it is not a . or a .. which are symbols for the folder above and the same folder

              SokIEnMapp (sender,sokmapp+'\'+searchrec.name,searchrec.name); //If it was another folder, call a subroutine to investigate that folder

          end;

          32 : begin //If it was a 32 it is a file

            if ansilowercase(extractfileext(searchrec.name)) = '.url' then begin //if the file name ends with .url it is an explorer favourite

              inifil := tinifile.create (sokmapp+searchrec.name); //Create an inifile object for this file

              try

                temptext :=inifil.readstring ('InternetShortcut','URL',''); //Read the actual link from the file

                richedit1.Lines.Add (stringreplace(searchrec.name,extractfileext(searchrec.name),'')+'='+temptext);//Show the file name and the link in the richedit

                statusbar1.SimpleText := searchrec.name; //Show the filename in the status bar

                statusbar1.Update; //Update the status bar

                application.processmessages; //And give windows a chance to catch up

                grunder.Add ('<li><a href="'+temptext+'">'+stringreplace(searchrec.name,extractfileext(searchrec.name),'')+'</a></li>'); //Add the favourite to our temporary stringlist

              finally

                inifil.Free; //Free the inifile object

              end;

            end;

          end;

        end;

        test := findnext(searchrec); //Call findnext to see if there are more files or folders

      end;

     findclose(searchrec); //Release the search object





The resulting HTML-file contains the name of the link and the actual link in a <A href= tag which makes the file useful.





...

Johan Lindgren is an ex-journalist, now working with technical development for the Swedish News Agency (Tidningarnas Telegrambyrå). It involves work with SGML, XML and XSL. He uses Delphi to produce the various pieces of software that is needed. He can be reached at johan.lindgren@tt.se





Sourcecode:



unit favvo;



interface



uses

  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,

  StdCtrls, ComCtrls,inifiles, ExtCtrls;



type

  Tfavu = class(TForm)

    RichEdit1: TRichEdit;

    Panel1: TPanel;

    startsearch: TButton;

    StatusBar1: TStatusBar;

    Button1: TButton;

    procedure startsearchClick(Sender: TObject);

    procedure Button1Click(Sender: TObject);

    procedure FormCreate(Sender: TObject);

    procedure SokIEnMapp (sender : Tobject;sokpath,katalog : string);

    procedure FormDestroy(Sender: TObject);

  private

    { Private declarations }

  public

    { Public declarations }

    SearchRec: TSearchRec; //The overall search object

    sokmapp, htmlut, textut : string; //Strings for holding the folder to search and the files for the search results

    htmlspar : tstringlist; //String list to hold the HTML file

  end;



  function KollaSlutet (rad,slut : string) : string;

  function StringReplace (text,byt,mot : string ) :string;



var

  favu: Tfavu;



implementation



{$R *.DFM}





//======= When program is launched ========//

procedure Tfavu.FormCreate(Sender: TObject);

var

  inifil : TIniFile; //Inifile-object to read user preferences

  exepath : string; //Searchpath for the application

begin

  exepath := extractfilepath (application.exename); //Extract the searchpath for the application

  exepath := kollaslutet(exepath,'\'); //Call a function that checks that the first string ends with the second string

  inifil := tinifile.create(exepath+'favoriter.ini'); //Create the inifile object with the exepath combined with the inifile name.

  try

    sokmapp := inifil.readstring('Favoriter','WindowsFavoriter','c:\windows\favoriter\'); //Get the searchpath for the folder containing the explorer favourites

    sokmapp := kollaslutet(sokmapp,'\'); //Call the routine "kollaslutet" to make sure that the string ends with a \

    htmlut := inifil.readstring('Favoriter','HTMLsave','c:\favoriter.html'); //Get the name and path to the file where the html result is to be stored

    textut := inifil.readstring('Favoriter','TEXTsave','c:\favoriter.txt'); //Get the name and the path to the file where the text result is to be stored

  finally

    inifil.free; //Free the resources for the inifile object

  end;

  htmlspar := tstringlist.create; //Create the stringlist to hold the HTML result

end;



//====== Clicking the button to start collecting the favourites ========//

procedure Tfavu.startsearchClick(Sender: TObject);

var

  inifil : TIniFile; //Inifile object to get the content of the favourites

  temptext : string; //Temporary string for storing

  test : integer; //Integer for checking the search results

  grunder : TStringList; //STring list to hold searchresult from one folder

begin

  screen.cursor := crHourglass; //Show the hourglass to let the user know we're busy

  grunder := TStringList.create; //Create the stringlist



  htmlspar.add ('<html><head><title>Internet Favourites</title></head><body>');//Set up the first HTML elements in that stringlist

  try

    test := FindFirst(sokmapp+'*.*', faAnyFile, SearchRec); //See if we get any result from our first search

    if test = 0 then //if we got a result. Indicated by a 0 in the FindFirst function!!

      while test = 0 do begin //As long as we get 0's from our Searches there are more files or folders to process

        case searchrec.Attr of //Check to see what attribute the searchresult had

          faDirectory : begin //If it was a 16 it is a sub folder

            if (searchrec.name <> '.') and (searchrec.name <> '..') then //Check to see that it is not a . or a .. which are symbols for the folder above and the same folder

              SokIEnMapp (sender,sokmapp+'\'+searchrec.name,searchrec.name); //If it was another folder, call a subroutine to investigate that folder

          end;

          32 : begin //If it was a 32 it is a file

            if ansilowercase(extractfileext(searchrec.name)) = '.url' then begin //if the file name ends with .url it is an explorer favourite

              inifil := tinifile.create (sokmapp+searchrec.name); //Create an inifile object for this file

              try

                temptext :=inifil.readstring ('InternetShortcut','URL',''); //Read the actual link from the file

                richedit1.Lines.Add (stringreplace(searchrec.name,extractfileext(searchrec.name),'')+'='+temptext);//Show the file name and the link in the richedit

                statusbar1.SimpleText := searchrec.name; //Show the filename in the status bar

                statusbar1.Update; //Update the status bar

                application.processmessages; //And give windows a chance to catch up

                grunder.Add ('<li><a href="'+temptext+'">'+stringreplace(searchrec.name,extractfileext(searchrec.name),'')+'</a></li>'); //Add the favourite to our temporary stringlist

              finally

                inifil.Free; //Free the inifile object

              end; //try finally

            end; //if .url

          end;//case 32

        end; //case

        test := findnext(searchrec); //Call findnext to see if there are more files or folders

      end; //while

     findclose(searchrec); //Release the search object

     htmlspar.Text := htmlspar.text + '<b>Various links</b><ul>'+grunder.text+'</ul>';//Add to the HTML stringlist a header line and the results from this folder

     htmlspar.add ('</body></html>'); //Finally add the closing HTML elements

     htmlspar.SaveToFile (htmlut); //Save the HTML stringlist to the designated name

     richedit1.lines.SaveToFile (textut); //Save the lines of the richedit to the designated file. Make sure to have plaintext=true in the richedit

  finally

    grunder.free; //Free the stringlist

    screen.cursor := crDefault; //Restore the cursor

  end;

end;



//======= Procedure to search in a specific folder =====//

procedure Tfavu.SokIEnMapp (sender : Tobject;sokpath,katalog : string);

var

  undermapp : tsearchrec; //Searchresult for this specific folder

  inifil : tinifile; //Inifile to read content from url-files

  temptext : string; //Temporary string

  test2 : integer; //Integer to see what search result we got

begin

  richedit1.lines.add (katalog); //Start by adding the name of the folder to be searched to the richedit

  statusbar1.SimpleText := katalog; //Do the same with the status bar

  statusbar1.Update; //Update the status bar

  application.processmessages; //Make sure windows get's a chance

  htmlspar.add ('



<b>'+katalog+'</b><ul>'); //Add the name of the folder to the HTML string list

  test2 := findfirst(sokpath+'\*.*',faAnyFile,Undermapp); //Start a search in the sub folder

  if test2 = 0 then //If we get a 0 we scored a hit

    while test2 = 0 do begin //As long as we keep finding new folders or files

      case undermapp.attr of //Check the attribute of the search result

        16 : begin //If it was a 16 it is a subfolder

          if (undermapp.name <> '.') and (undermapp.name <> '..') then //As long as the name is not . or .. we continue our search

            SokIEnMapp (sender,sokpath+'\'+undermapp.name,undermapp.name); //Call the same routine to keep searching subfolders

        end; //16

        32 : begin //32 means a file

          if ansilowercase(extractfileext(undermapp.name)) = '.url' then begin //If the filename ends with .url it is an explorer favourite

            inifil := tinifile.create (sokpath+'\'+undermapp.name); //Create an inifile object for this file

            try

              temptext :=inifil.readstring ('InternetShortcut','URL',''); //Read the link in the file

              richedit1.Lines.Add (stringreplace(undermapp.name,extractfileext(undermapp.name),'')+'='+temptext); //Add this to the richedit

              statusbar1.SimpleText := undermapp.name; //Show the name of the file in the status bar

              statusbar1.Update; //Update the status bar

              application.processmessages; //Let windows do it's business

              htmlspar.Add ('<li><a href="'+temptext+'">'+stringreplace(undermapp.name,extractfileext(undermapp.name),'')+'</a></li>');//Add the filename and the link to the HTML stringlist

            finally

              inifil.Free; //free the inifile object

            end; //try

          end; //if

        end; //32

      end;

      test2 := findnext (undermapp); //call find next to keep searching

    end; //while

    htmlspar.add ('</ul>'); //Add a closing tag to the html string list

    findclose (undermapp); //Call find close to close the search object

end;



//======== When closing the program ==========//

procedure Tfavu.Button1Click(Sender: TObject);

begin

  close; //Close the application

end;



procedure Tfavu.FormDestroy(Sender: TObject);

begin

  htmlspar.free; //Free the resourse for the html string list

end;



//================ Functions ==============//



//========== Check that a string ends with a specific string =============//

function KollaSlutet (rad,slut : string) : string;

begin

  if length(rad)>0 then //Make sure theres something there to check

    if rad[length(rad)] <> slut then rad := rad+slut;//If it does not end with the proper ending - add it

  result := rad; //Return the string

end;



//========== Function to change the first occurance of byt against mot in text ===========//

function StringReplace (text,byt,mot : string ) :string;

var

   plats : integer;

begin

  if pos(byt,text) > 0 then begin //if byt exist in text

    plats := pos(byt,text); //Note where it is

    delete (text,plats,length(byt)); //Remove the part matching byt

    insert (mot,text,plats); //insert mot in the proper place

  end; //if byt existed in text

  result := text; //in any case return the text

end;



end.

 

Share this article!

Follow us!

Find more helpful articles: