RTollison 0 Posted November 6, 2023 is there a way with the TFileOpenDialog to limit the directory to a specified folder or downstream but not allow going upstream. c:\myfolder\ and any subfolder from there but not allow user to go above that to say c:\ or c:\yourfolder... Share this post Link to post
David Heffernan 2345 Posted November 6, 2023 I don't think this is possible because there's no good use for such a feature Share this post Link to post
Der schöne Günther 316 Posted November 6, 2023 You will have to roll your own file picker or simply display something like "Sorry, this file is not allowed" if it's not in the correct directory. Windows regular file picker does not stop the user from entering an absolute path, following shortcuts, drag & dropping files, copying & pasting, ... the list goes on. 1 Share this post Link to post
RTollison 0 Posted November 6, 2023 reason for this is cloud server and multiple clients. we give them a specific folder that is theirs but if we allow them to navigate to other clients folders it presents a security problem. we have permissions in place but not fullproof just yet. Share this post Link to post
Pat Foley 51 Posted November 6, 2023 Use ShellAPI and ListBox or ListView perhaps. Try typing over the path in the FileOpenDialog location bar and see what happens with "cmd" or "explorer" text.😈 Share this post Link to post
Remy Lebeau 1398 Posted November 6, 2023 (edited) 1 hour ago, RTollison said: is there a way with the TFileOpenDialog to limit the directory to a specified folder or downstream but not allow going upstream. c:\myfolder\ and any subfolder from there but not allow user to go above that to say c:\ or c:\yourfolder... TFileOpenDialog has OnFolderChanging and OnFileOkClick events that can be used to verify/reject the user's input so they can't use what you don't want them to use. Edited November 6, 2023 by Remy Lebeau Share this post Link to post
David Heffernan 2345 Posted November 6, 2023 2 hours ago, RTollison said: reason for this is cloud server and multiple clients. we give them a specific folder that is theirs but if we allow them to navigate to other clients folders it presents a security problem. we have permissions in place but not fullproof just yet. The fix the actual problem. Otherwise your security is broken. Share this post Link to post
Remy Lebeau 1398 Posted November 6, 2023 2 hours ago, RTollison said: reason for this is cloud server and multiple clients. we give them a specific folder that is theirs but if we allow them to navigate to other clients folders it presents a security problem. Letting a user even see that another user's folder exists, even if it's not selectable, is just bad UI design and broken security waiting to be exploited. Share this post Link to post
Hans J. Ellingsgaard 21 Posted November 6, 2023 I think this shold be dealt with at the OS level with user rights. What happens if the user open the file explorer, and start browsing folders from there? Share this post Link to post
RTollison 0 Posted November 7, 2023 no explorer option allowed except thru this yet to be finished dll. Share this post Link to post
RTollison 0 Posted November 7, 2023 parallels with a published app that has limited UI for folder/file selection. we have restricted permissions set and stuff but some locations the user HAVE to have permissions, c:\... for some windows api stuff. well now all users can go nuts on some of those files if they are so inclined. we map a drive for each client but the base drive d is available to allow some navigation and stuff like that. so yes we have restricted access but a fileopendialog will let you go just about anywhere. Share this post Link to post
RTollison 0 Posted November 10, 2023 (edited) i found this old post, Remy's, and i am wanting to figure out how to allow user to navigate downfolder and back up to initialidir folder. so if initialdir = v:\myfolder then they can go anywhere downfolder from there but can not go to v:\ stop at v:\myfolder. procedure TForm1.FileOpenDialog1FolderChanging(Sender: TObject; var CanChange: Boolean); var Dlg: TFileOpenDialog; DefFolder: IShellItem; iOrder: Integer; begin CanChange := False; Dlg := Sender as TFileOpenDialog; if Succeeded(SHCreateItemFromParsingName(PWideChar(WideString(Dlg.DefaultFolder)), nil, IShellItem, DefFolder)) then try CanChange := Dlg.ShellItem.Compare(DefFolder, SICHINT_ALLFIELDS, iOrder) = S_OK; finally DefFolder := nil; end; end; Edited November 10, 2023 by RTollison Share this post Link to post
Remy Lebeau 1398 Posted November 10, 2023 (edited) 4 hours ago, RTollison said: i found this old post, Remy's Which post are you referring to? The code you have shown does not look like code I would have written. 4 hours ago, RTollison said: i am wanting to figure out how to allow user to navigate downfolder and back up to initialidir folder Note that the TFileOpenDialog.DefaultFolder applies only if there was no folder previously selected with the same dialog. You might want to prepare your initial IShellItem to your desired root folder before you open the dialog. That being said, you are setting the CanChange parameter to true only if the selected folder and the default folder are the same, which is not what you want. You need to check if the desired initial folder is a parent/ancestor of the selected folder. So, for that, you need to take the Dlg.ShellItem and walk its parent list comparing each one individually until you find a match or exhaust the list. Or, you could query each IShellItem for its ITEMIDLIST and use ILIsParent() or equivalent. For example (untested): var MyFolderShellItem: IShellItem; ... if Succeeded(SHCreateItemFromParsingName(PChar('C:\MyFolder'), nil, IShellItem, MyFolderShellItem)) then try FileOpenDialog1.Execute; finally MyFolderShellItem := nil; end; ... function IsParentOf(ARoot, AItem: IShellItem): Boolean; var iOrder: Integer; iParent: IShellItem; begin Result := (AItem.GetParent(iParent) = S_OK) and ((iParent.Compare(ARoot, SICHINT_ALLFIELDS or SICHINT_TEST_FILESYSPATH_IF_NOT_EQUAL, iOrder) = S_OK) or IsParentOf(ARoot, iParent)); end; { alternatively: function IsParentOf(ARoot, AItem: IShellItem): Boolean; var RootIdList, ItemIdList: PIDLIST_ABSOLUTE; begin Result := False; if SHGetIDListFromObject(ARoot, @RootIdList) = S_OK then try if SHGetIDListFromObject(AItem, @ItemIdList) = S_OK then try Result := ILIsParent(RootIdList, ItemIdList, FALSE); finally CoTaskMemFree(ItemIdList); end; finally CoTaskMemFree(RootIdList); end; end; } procedure TForm1.FileOpenDialog1FolderChanging(Sender: TObject; var CanChange: Boolean); begin CanChange := IsParentOf(MyFolderShellItem, (Sender as TFileOpenDialog).ShellItem); end; Edited November 10, 2023 by Remy Lebeau Share this post Link to post
RTollison 0 Posted November 10, 2023 my apologies it was a post you edited windows - How to retrieve creation date of an IShellItem? - Stack Overflow and thank you for this update. really appreciate it. Share this post Link to post
Pat Foley 51 Posted November 10, 2023 On 11/6/2023 at 1:55 PM, Remy Lebeau said: On 11/6/2023 at 11:19 AM, RTollison said: reason for this is cloud server and multiple clients. we give them a specific folder that is theirs but if we allow them to navigate to other clients folders it presents a security problem. Letting a user even see that another user's folder exists, even if it's not selectable, is just bad UI design and broken security waiting to be exploited. I would change this to mean each client 'sees' only one 'cloud' or 'channel'. Meaning the Admin for one client's machines would never see another client's channel machines and data. Have each client users use email and password to start windows and access their file share and shared drives as allowed by the logon of that user's account. Share this post Link to post
RTollison 0 Posted November 10, 2023 IT has already went down this road with locking up everything except clients own mapped drive. we had to create dlls already for accessing ftp, http, mapi, smtp and other functions. when clients were locked out of the servers c drive it broke some of our dll functionality. they had to open up locations randomly as clients were getting an error about some missing feature or whatever. so as it stands now they are locked out of most places that they shouldn't be allowed, but our cobol program runtime has a file explorer library that we use in some programs. like say a file extract for payroll ACH. now we open up the explorer window and in theory they would selelct the file from the folder we prompted to them. but a few have navigated to other folders and could use the preview to see what was in the other folders/files. So this new dll is to put an end to the wandering user. not about security but prevent the wandering user. Share this post Link to post
Pat Foley 51 Posted November 10, 2023 Some Entities track employee's computer use and issue "warnings". What are your peers doing in like setups? Share this post Link to post
David Heffernan 2345 Posted November 11, 2023 14 hours ago, RTollison said: but a few have navigated to other folders and could use the preview to see what was in the other folders/files. So this new dll is to put an end to the wandering user. not about security but prevent the wandering user. If this isn't about security then there's no need for the feature you are trying to implement. Share this post Link to post
RTollison 0 Posted November 15, 2023 all good and valid reasons for not creating the dll, but lets just say that i want the challenge because i have nothing better to do. so now i am committed to creating this dll for the sake of creating such a dll with this very dialog feature. NOTE: This very question has been asked by others in the past so maybe there is some kind of reward at the end of the rainbow. Share this post Link to post
RTollison 0 Posted November 15, 2023 this is what i found to keep the folder from changing at all but just staying in the defaultfolder. I am trying to figure out how to update the compare command and do a isparent. i see there is a getparent option just not able to implement it on my own. procedure TForm3.FileOpenDialog1FolderChanging(Sender: TObject; var CanChange: Boolean); var Dlg: TFileOpenDialog; DefFolder: IShellItem; iOrder: Integer; begin CanChange := False; Dlg := Sender as TFileOpenDialog; if Succeeded(SHCreateItemFromParsingName(PWideChar(WideString(Dlg.DefaultFolder)), nil, IShellItem, DefFolder)) then try CanChange := Dlg.ShellItem.Compare(DefFolder, SICHINT_ALLFIELDS, iOrder) = S_OK; finally DefFolder := nil; end; end; Share this post Link to post
Remy Lebeau 1398 Posted November 16, 2023 (edited) On 11/15/2023 at 10:17 AM, RTollison said: this is what i found to keep the folder from changing at all but just staying in the defaultfolder. I am trying to figure out how to update the compare command and do a isparent. i see there is a getparent option just not able to implement it on my own. I literally gave you such code a week ago. Did you not see/try it? Edited November 16, 2023 by Remy Lebeau Share this post Link to post
RTollison 0 Posted November 16, 2023 Yes sir, I got error messages about mismatch field types(compilig) and on one of the isparent functions it would compile but then i got an error message about access denied with 0000434 or something like that. I tried to resolve them but honestly, i could not figure out what needed to be done.(IShellItem is beyond my programming experience and i really hate bothering others when they have given me something to work with) so while doing the digging around i noticed that the ishellitem has a getdisplayname option (hoping for a string value) so i can then run containstext to check it that way. Share this post Link to post
Remy Lebeau 1398 Posted November 16, 2023 42 minutes ago, RTollison said: Yes sir, I got error messages about mismatch field types(compilig) Then you should have said something earlier. I whipped up those examples off the top of my head, I didn't test them (and stated as much). What is the exact error message, and on which line(s) of code? 42 minutes ago, RTollison said: and on one of the isparent functions it would compile but then i got an error message about access denied with 0000434 or something like that. Can you be more specific? What is your root folder? What is your selected folder? While walking the parent tree, which folder are you getting the error on (ie, what is the display data for the failing IShellItem)? 42 minutes ago, RTollison said: I tried to resolve them but honestly, i could not figure out what needed to be done. You should have said something earlier. 42 minutes ago, RTollison said: IShellItem is beyond my programming experience and i really hate bothering others when they have given me something to work with How else are you going to learn? 42 minutes ago, RTollison said: while doing the digging around i noticed that the ishellitem has a getdisplayname option (hoping for a string value) so i can then run containstext to check it that way. That won't solve your main goal, since you will only be getting individual folder names from it, not full paths. Share this post Link to post
RTollison 0 Posted November 16, 2023 i appreciated the help enough to try and figure it out. knew the code was off the top but figured it was something to work with. i googled the heck out of those options but still not able to figure it out. and i like figuring it out if possible on my own. but my limited knowledge just didn't get past the mismatch stuff. as for the x0000000... error i googled it and it said i was denied access. again apologies for not going back directly but i wanted to figure it out and failed miserably. however i did (on the surface) get this to work. probably not the best solution but it seems to be working. procedure TForm3.FileOpenDialog1FolderChanging(Sender: TObject; var CanChange: Boolean); var Dlg: TFileOpenDialog; DefFolder: IShellItem; iOrder: Integer; Path: PWideChar; begin CanChange := False; Dlg := Sender as TFileOpenDialog; if Succeeded(SHCreateItemFromParsingName(PWideChar(WideString(Dlg.DefaultFolder)), nil, IShellItem, DefFolder)) then try begin Dlg.ShellItem.GetDisplayName(SIGDN_FILESYSPATH, Path); CanChange := ContainsText(Path, Dlg.DefaultFolder); end; finally begin DefFolder := nil; end; end; Path := ''; end; Share this post Link to post
Remy Lebeau 1398 Posted November 17, 2023 (edited) 19 hours ago, RTollison said: Dlg.ShellItem.GetDisplayName(SIGDN_FILESYSPATH, Path); CanChange := ContainsText(Path, Dlg.DefaultFolder); Just note that comparing filesystem paths as plain strings is not 100% reliable. Better to use system APIs that are better suited for that task, so you don't run into issues related to differences in casing, localization, 8.3 shortening, etc... Edited November 17, 2023 by Remy Lebeau 1 Share this post Link to post