home *** CD-ROM | disk | FTP | other *** search
- unit FtpSearch;
-
- interface
-
- uses
- Windows, SysUtils, Classes, Forms, WinINet, FtpData, FtpMisc;
-
- {$I mftp.inc}
-
- const
- SearchTypeStr: Array[0..10] of String = (
- 'Case+insensitive+substring+search',
- 'Case+sensitive+substring+search',
- 'Case+insensitive+glob+search',
- 'Case+sensitive+glob+search',
- 'Regular+expression+search',
- 'Exact+search',
- 'Case+insensitive+substring+match',
- 'Case+sensitive+substring+match',
- 'Case+insensitive+glob+match',
- 'Case+sensitive+glob+match',
- 'Regular+expression+match');
-
- type
- { C = case, I = insensitive, N = sensitive,
- G = glob, E = Exact, X = expression,
- S = search, M = match, R = Regular,
- U = substring }
-
- TMFtpSearchType = (mstCIUS, mstCNUS, mstCIGS, mstCNGS,
- mstRXS, mstES, mstCIUM, mstCNUM,
- mstCIGM, mstCNGM, mstEXM);
-
- TMFtpDataEvent = procedure (Data: String) of object;
-
- TMFtpSearchInfo = (searchStart, searchDone, searchFileFound);
- TMFtpSearchInfoEvent = procedure (Sender: TObject; info: TMFtpSearchInfo; addinfo: String) of object;
-
- TMFtpSearchThread = class(TThread)
- private
- FCache: Boolean;
- FData: String;
- FOnData: TMFtpDataEvent;
- FPort: Integer;
- FProxy: Boolean;
- FRFile: String;
- FServer: String;
- FTag: Integer;
- protected
- procedure Execute; override;
-
- property OnData: TMFtpDataEvent read FOnData write FOnData;
- public
- constructor Create(RemoteFile, Server: String; Port: Integer;
- Cache, Proxy: Boolean);
-
- property Tag: Integer read FTag write FTag;
- end;
-
- TMFtpSearch = class(TComponent)
- private
- FBusy: Boolean;
- FCache: Boolean;
- FFile: String;
- FFiles: TMFtpFileInfoList;
- FFromDate: String;
- FMaxHit: Longword;
- FMaxMatch: Longword;
- FMaxSize: Longword;
- FMinSize: Longword;
- FProxy: Boolean;
- FSearchInfoEvent: TMFtpSearchInfoEvent;
- FServer: TStrings;
- FToDate: String;
- FType: TMFtpSearchType;
-
- function BuildURL: String;
-
- procedure Parse(L: TStringList);
- procedure SetServer(S: TStrings);
- procedure ThreadData(Data: String);
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
-
- procedure Search;
-
- property Busy: Boolean read FBusy;
- property Files: TMFtpFileInfoList read FFiles;
- published
- property Cache: Boolean read FCache write FCache;
- property Filename: String read FFile write FFile;
- property MaxHit: Longword read FMaxHit write FMaxHit;
- property MaxMatch: Longword read FMaxMatch write FMaxMatch;
- property MaxSize: Longword read FMaxSize write FMaxSize;
- property MinSize: Longword read FMinSize write FMinSize;
- property Proxy: Boolean read FProxy write FProxy;
- property SearchType: TMFtpSearchType read FType write FType;
- property Server: TStrings read FServer write SetServer;
-
- property OnSearchInfo: TMFtpSearchInfoEvent read FSearchInfoEvent write FSearchInfoEvent;
- end;
-
- implementation
-
- { TMFtpSearchThread }
-
- constructor TMFtpSearchThread.Create;
- begin
- FRFile := RemoteFile;
- FServer := Server;
- FPort := Port;
- FCache := Cache;
- FProxy := Proxy;
- FData := '';
- end;
-
- procedure TMFtpSearchThread.Execute;
- var FHandle, FHttpHandle, FRequest: HINTERNET;
- DataLen: Longword;
- Data: PChar;
- begin
- if FProxy then
- FHandle := InternetOpen('MFtpINet', INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0)
- else
- FHandle := InternetOpen('MFtpINet', INTERNET_OPEN_TYPE_DIRECT, nil, nil, 0);
-
- if FHandle = nil then
- begin
- OnData('');
- Exit;
- end;
-
- FHttpHandle := InternetConnect(FHandle, PChar(FServer), FPort, '', '',
- INTERNET_SERVICE_HTTP, 0, 0);
- if FCache then
- FRequest := HttpOpenRequest(FHttpHandle, nil, PChar(FRFile), nil, nil,
- nil, 0, 0)
- else
- FRequest := HttpOpenRequest(FHttpHandle, nil, PChar(FRFile), nil, nil,
- nil, INTERNET_FLAG_RELOAD, 0);
-
- HttpSendRequest(FRequest, nil, 0, nil, 0);
-
- GetMem(Data, 4097);
-
- while True do
- begin
- if not InternetReadFile(FRequest, Data, 4096, DataLen) then
- begin
- Break;
- end
- else
- begin
- if DataLen = 0 then Break; // No more data to read
-
- Data[DataLen] := Char(0);
- FData := FData + StrPas(Data);
- end;
- end;
-
- if Assigned(FOnData) then FOnData(FData);
-
- FreeMem(Data);
- InternetCloseHandle(FRequest);
- InternetCloseHandle(FHttpHandle);
- InternetCloseHandle(FHandle);
- end;
-
- { TMFtpSearch }
-
- constructor TMFtpSearch.Create;
- begin
- inherited Create(AOwner);
-
- FServer := TStringList.Create;
- FServer.Add('ftpsearch.lycos.com:80');
-
- FFiles := TMFtpFileInfoList.Create;
-
- FCache := True;
-
- FMaxHit := 200;
- FMaxMatch := 200;
- end;
-
- destructor TMFtpSearch.Destroy;
- begin
- FreeAndNil(FServer);
- FFiles.MyFree;
-
- inherited Destroy;
- end;
-
- function TMFtpSearch.BuildURL;
- begin
- Result := '/ftpsearch?query=' + PrepareURL(Trim(FFile)) + '&form=advanced' +
- '&hits=' + IntToStr(FMaxHit) + '&matches=' + IntToStr(FMaxMatch) +
- '&doit=Search&f1=Count&f2=Mode&f3=Len&f4=Date&f5=Time&f6=Name' +
- '&limtime1=' + PrepareURL(Trim(FFromDate)) + '&limtime2=' +
- PrepareURL(Trim(FToDate));
-
- if FMinSize > 0 then
- begin
- Result := Result + '&limsize1=' + IntToStr(FMinSize);
-
- if FMinSize <= FMaxSize then
- Result := Result + '&limsize2=' + IntToStr(FMaxSize);
- end;
- end;
-
- procedure TMFtpSearch.SetServer;
- begin
- if not FBusy then FServer.Assign(S);
- end;
-
- procedure TMFtpSearch.Parse;
- var Attrib, Size, DT, URL, S: String;
- i, j, j1: Integer;
- begin
- for i := 0 to L.Count - 1 do
- begin
- S := Trim(L[i]);
-
- j := Pos('<TT>', S);
- if j > 0 then
- begin
- j1 := Pos('</TT>', S);
- Attrib := Trim(Copy(S, j + 4, j1 - j - 4));
- Delete(S, 1, j1 + 5);
-
- j := Pos('<B>', S );
- j1 := Pos('</B>', S);
- Size := Trim(Copy(S, j + 3, j1 - j - 3));
- Delete(S, 1, j1 + 4);
-
- j := Pos('<A HREF="', S);
- DT := Trim(Copy(S, 1, j - 1));
- Delete(S, 1, j + 8);
-
- j := Pos('">', S);
- URL := Trim(Copy(S, 1, j - 1));
-
- // work arounds here
- if Copy(URL, 1, 6) <> 'ftp://' then
- begin
- j := Pos('oquery=', URL);
- URL := 'ftp://' + Copy(URL, j + 7, 9999);
- end;
-
- j := Pos('type=Navigate&query=', URL);
-
- if j > 0 then
- begin
- URL := 'ftp://' + Copy(URL, j + 20, 9999);
-
- j := Pos('%2', URL);
- while j > 0 do
- begin
- if URL[j + 2] = 'e' then URL := Copy(URL, 1, j - 1) + '.' + Copy(URL, j + 3, 9999) else
- if URL[j + 2] = 'f' then URL := Copy(URL, 1, j - 1) + '/' + Copy(URL, j + 3, 9999);
- j := Pos('%2', URL);
- end;
- end;
-
- if FFiles.IndexOf(URL) < 0 then
- begin
- FFiles.Add(URL, Attrib, DT, Size, '', '', '','');
- if Assigned(FSearchInfoEvent) then FSearchInfoEvent(Self, searchFileFound, URL);
- end;
- end;
-
- if i mod 25 = 0 then Application.ProcessMessages;
- end;
- end;
-
- procedure TMFtpSearch.Search;
- var i, j: Integer;
- RFile: String;
- Port: Integer;
- begin
- if FBusy then Exit;
- if Trim(FFile) = '' then Exit;
-
- FBusy := True;
- RFile := BuildURL;
- FFiles.Clear;
-
- for i := 0 to FServer.Count - 1 do
- begin
- FServer[i] := Trim(FServer[i]);
-
- if Trim(FServer[i]) <> '' then
- begin
- j := Pos(':', FServer[i]);
-
- if j > 0 then
- Port := StrToInt(Copy(FServer[i], j + 1, 999))
- else
- Port := 80;
-
- if Assigned(FSearchInfoEvent) then
- FSearchInfoEvent(Self, searchStart, FServer[i]);
-
- with TMFtpSearchThread.Create(RFile, Copy(FServer[i], 1, j - 1),
- Port, FCache, FProxy) do
- begin
- Tag := i;
- OnData := ThreadData;
- FreeOnTerminate := True;
- Execute;
- end;
- end;
- end;
-
- FBusy := False;
- end;
-
- procedure TMFtpSearch.ThreadData;
- var TS: TStringList;
- begin
- TS := TStringList.Create;
- try
- TS.Text := Data;
- Parse(TS);
- finally
- FreeAndNil(TS);
- end;
-
- if Assigned(FSearchInfoEvent) then
- FSearchInfoEvent(Self, searchDone, FServer[Tag]);
- end;
-
- end.
-
-