Filefilter hook question [solved]

6 posts / 0 new
Last post
OldFart
OldFart's picture
Offline
Last seen: 3 months 1 week ago
Joined: 2010-11-30 14:09
Filefilter hook question [solved]

Hi,

In a program I'm applying, or trying to at least, a filefilter hook.

Here follow the code parts involved:
Allocating the hook structure.

  1. if ((__GD->gd_FileFilter = IExec->AllocSysObjectTags(ASOT_HOOK, ASOHOOK_Entry, FilterHook, TAG_END)))
  2. {

Next the ReAction specs:

  1. LAYOUT_GetFile(GOID_FILENAME, NULL, CATTEXT(CTID_SelFile), 500),
  2. GETFILE_Drawer , GETFILE_INITIALDIRECTORY,
  3. GETFILE_FilePartOnly, TRUE,
  4. GETFILE_ReadOnly , TRUE,
  5. GETFILE_RejectIcons , TRUE,
  6. GETFILE_FilterFunc , __GD->gd_FileFilter,
  7. LAYOUT_GetFileEnd,

Then the FilterHook function:

  1. BOOL FilterHook(struct Hook *hk UNUSED, struct FileRequester *fr, struct ExamineData *ed)
  2. {
  3. BOOL Acceptable = FALSE;
  4.  
  5. if (EXD_IS_DIRECTORY(ed))
  6. {
  7. BPTR NewLock = IDOS->Lock(fr->fr_Drawer, ACCESS_READ),
  8. OldLock = IDOS->SetCurrentDir(NewLock),
  9. File = IDOS->Open(ed->Name, MODE_OLDFILE);
  10.  
  11. if (File)
  12. {
  13. Acceptable = Verify_IFF_Format(File, 0, 0);
  14.  
  15. IDOS->Close(File);
  16. }
  17.  
  18. IDOS->SetCurrentDir(OldLock);
  19. IDOS->UnLock(NewLock);
  20. }
  21. else
  22. {
  23. Acceptable = TRUE;
  24. }
  25.  
  26. return Acceptable;
  27. }

And last the function that might cause the problem, but I don't see why it should:

  1. BOOL Verify_IFF_Format(BPTR File, uint32 Form, uint32 Type)
  2. {
  3. INFO_ENTER
  4. BOOL Acceptable = FALSE;
  5.  
  6. char Buff[12];
  7.  
  8. if (IDOS->Read(File, Buff, 12) == 12)
  9. {
  10. if (Form == 0)
  11. {
  12. if (
  13. (*((uint32 *)&Buff[0]) == ID_FORM)
  14. ||
  15. (*((uint32 *)&Buff[0]) == ID_LIST)
  16. ||
  17. (*((uint32 *)&Buff[0]) == ID_CAT )
  18. ||
  19. (*((uint32 *)&Buff[0]) == ID_PROP)
  20. )
  21. {
  22. if (Type == 0)
  23. {
  24. Acceptable = TRUE;
  25. }
  26. else
  27. {
  28. if (*((uint32 *)&Buff[8]) == Type)
  29. {
  30. Acceptable = TRUE;
  31. }
  32. }
  33. }
  34. }
  35. else
  36. {
  37. if (
  38. (*((uint32 *)&Buff[0]) == Form) &&
  39. (*((uint32 *)&Buff[8]) == Type)
  40. )
  41. {
  42. Acceptable = TRUE;
  43. }
  44. }
  45. }
  46.  
  47. INFO_VACATE
  48. return Acceptable;
  49. }

It seems like the filter is passing ALL files it get thrown to.
Why?

OldFart

OldFart
OldFart's picture
Offline
Last seen: 3 months 1 week ago
Joined: 2010-11-30 14:09
Re: Filefilter hook question

Looking at the code after pressing the [ Save ] button, I noticed my error:

  1. BOOL FilterHook(struct Hook *hk UNUSED, struct FileRequester *fr, struct ExamineData *ed)
  2. {
  3. BOOL Acceptable = FALSE;
  4.  
  5. if (EXD_IS_DIRECTORY(ed))
  6. {
  7. BPTR NewLock = IDOS->Lock(fr->fr_Drawer, ACCESS_READ),
  8. OldLock = IDOS->SetCurrentDir(NewLock),
  9. File = IDOS->Open(ed->Name, MODE_OLDFILE);
  10.  
  11. if (File)
  12. {
  13. Acceptable = Verify_IFF_Format(File, 0, 0);
  14.  
  15. IDOS->Close(File);
  16. }
  17.  
  18. IDOS->SetCurrentDir(OldLock);
  19. IDOS->UnLock(NewLock);
  20. }
  21. else
  22. {
  23. Acceptable = TRUE;
  24. }
  25.  
  26. return Acceptable;
  27. }

This filter passes everything which is not a directory, so I changed it.

  1. BOOL FilterHook(struct Hook *hk UNUSED, struct FileRequester *fr, struct ExamineData *ed)
  2. {
  3. BOOL Acceptable = FALSE;
  4.  
  5. BPTR NewLock = IDOS->Lock(fr->fr_Drawer, ACCESS_READ),
  6. OldLock = IDOS->SetCurrentDir(NewLock),
  7. File = IDOS->Open(ed->Name, MODE_OLDFILE);
  8.  
  9. if (File)
  10. {
  11. Acceptable = Verify_IFF_Format(File, 0, 0);
  12.  
  13. IDOS->Close(File);
  14. }
  15.  
  16. IDOS->SetCurrentDir(OldLock);
  17. IDOS->UnLock(NewLock);
  18.  
  19. return Acceptable;
  20. }

The problem should have been solved now, or? Now no file is passed at all...

OldFart

OldFart
OldFart's picture
Offline
Last seen: 3 months 1 week ago
Joined: 2010-11-30 14:09
Re: Filefilter hook question

Changed it back again to the first version, only with a slight alteration, as I changed from applying EXD_IS_DIRECTORY() to EXD_IS_FILE():

  1. BOOL FilterHook(struct Hook *hk UNUSED, struct FileRequester *fr, struct ExamineData *ed)
  2. {
  3. BOOL Acceptable = FALSE;
  4.  
  5. if (EXD_IS_FILE(ed))
  6. {
  7. BPTR NewLock = IDOS->Lock(fr->fr_Drawer, ACCESS_READ),
  8. OldLock = IDOS->SetCurrentDir(NewLock),
  9. File = IDOS->Open(ed->Name, MODE_OLDFILE);
  10.  
  11. if (File)
  12. {
  13. Acceptable = Verify_IFF_Format(File, 0, 0);
  14.  
  15. IDOS->Close(File);
  16. }
  17.  
  18. IDOS->SetCurrentDir(OldLock);
  19. IDOS->UnLock(NewLock);
  20. }
  21. else
  22. {
  23. Acceptable = TRUE;
  24. }
  25.  
  26. return Acceptable;
  27. }

And now I again I get files, however not only the files I had anticipated (IFF files), but also, say, XML-files and the like.

I'm at a loss.

OldFart

salass00
salass00's picture
Offline
Last seen: 6 months 1 week ago
Joined: 2011-02-03 11:27
Re: Filefilter hook question

The problem is that you are using the old style ASLFR_FilterFunc (GETFILE_FilterFunc) which has a pointer to a struct AnchorPathOld in the 3rd hook parameter instead of struct ExamineData. Replace GETFILE_FilterFunc with GETFILE_FilterHook and you should be okay.

A couple of other minor things to fix:

1) Although it won't matter in practice, the return value of the hook function should be ULONG and not BOOL.

2) You don't check the return value of Lock() function for failure. This means that if it fails your code will look for a file with the same name in "SYS:" (IIRC).

OldFart
OldFart's picture
Offline
Last seen: 3 months 1 week ago
Joined: 2010-11-30 14:09
Re: Filefilter hook question

It works! Thanks a lot!

As I was working on a project that had been sleeping for more then a decade, I overlooked the deprecation of GETFILE_FilterFunc.

About the return value:
The AutoDocs on the getfile gadget do not mention anything about it, but as there is a near one-to-one relationship with asl.library I peaked at the corresponding tag in the asl-autodocs and this is what it reads:

ASLFR_FilterHook (struct Hook *)
A function to call for each file and directory encountered.
If the function returns TRUE the file or directory is included
in the list. Otherwise it is rejected and not displayed.
(V52.27)

The function has the following signature:
BOOL Filter(struct Hook *hook,
const struct FileRequester *req,
const struct ExamineData *data);

If multiple filtering methods are employed simultaneously,
the hook specified by this tag will always take precedence.

So, to me it seems that a BOOL is in place there.

And finally: I implemented a check on the Lock() function. A grave omission.

OldFart

salass00
salass00's picture
Offline
Last seen: 6 months 1 week ago
Joined: 2011-02-03 11:27
Re: Filefilter hook question [solved]

I know that the autodoc says BOOL, but the hook function is called via CallHookPkt() which treats the return value as ULONG (or uint32 or in AmigaOS 4.x terms).

If you specify the return value as BOOL then the following code will give a warning with newer gcc:s

hook.h_Entry = (HOOKFUNC)FilterHook;

The fact that the autodoc specifies it as BOOL just means that the high 16 bits of the return value are ignored as it is assigned and truncated into a 16-bit BOOL variable.

Log in or register to post comments