For Macintosh: File formats are different. Hagan posted a note (Feb 26, 2021) on the user list (use-livecode@lists.runrev.com) that may be used for that platform. Additional comments for better and other solutions are welcome, of course. I hope it is ok to repost Hagan's comment here:
On macOS URL link files are stored as a plist-file like:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>URL</key>
<string>https://lessons.livecode.com/</string>
</dict>
</plist>
On Windows, these shortcut files do not display a file extension even if extensions are made to show up. The hidden extensions used are ".lnk" or ".url" .But they will show up using the context menu (right mouse button) and checking the menu item "Properties". Also they become visible when calling the LC function files().
Local shortcuts ".lnk" files point to either files or folders or application icons and can start a process/app or open the target folder.
URL files are mostly generated when the user drags-and-drops the Internet Browser's URL field to the desktop.
Since Shortcut files with the ".lnk" extension have a binary format on Windows, the correct way to read out the file path to the target file (the file or folder the shortcut is pointing to) would be to actually read the binary format using binaryencode/binarydecode functions and reading chunks of bytes to detect the size of the target path string and the byte offset. I did not have that time and need to do so and looked at the file content to find clues that allow to extract the target link as a complete file path. And I am not fluent with bit and byte operations.
Therefore, this here is a hack that works for me and I did not detect any problem yet. If you have a similar need, you will have to adjust the function hackLnkFile() using your computer name and your drive letter on Windows by redefining two local variables.
The code is commented in detail so that also beginners may understand how to write a little hack in LiveCode. The script uses LC functions such as files(), merge(), URL("binfile:"&<filepath>) and offset().
I suggest to put all code/script into one script only unless for certain other reasons. It is by far easier to have all handlers (=commands or functions) in one script for development and debugging. Here I used the card script exclusively. There are no scripts in buttons, fields or any other object. All is put into one script package (which could also be a script of a behavior). The names of buttons or fields trigger the switch statement to execute.
I am using explicit variable declarations always for valid reasons and I am using LC naming conventions.
Additionally:
"-->" is a comment mark pointing to a handler and it's location
"--x" is a comment mark for a statement used for debugging which later will be removed
" put ... into msg --x" The message box is only used in development. Again, it is explicitly named to not confuse it with other 'put' statements.
To differentiate internal LC command and message handlers -- for example 'on mouseUp' -- from user defined commands, I am always using the synonymous term 'command myCommandName' when creating a command/message handler, as is also recommended.
Code: Select all
## Script author: Golive
## Script location: Card script
## Stack name: rhFileParser-url-lnk.livecode
## Last update: 2021-02-25 22:35
on mouseUp
local tTarget
put the short name of the target into tTarget
switch tTarget
case "getFolder" -- Button with name "getFolder"
getFolder
break
case "getFiles" -- Button with name "getFiles"
getFiles
break
case "getLinkFiles" -- Button with name "getLinkFiles"
getLinkFiles
break
end switch
end mouseUp
command getLinkFiles
lock screen
put getLinkFiles(field "folderpath") into field "list" -- Local field "list"
unlock screen
end getLinkFiles
command getFiles pFolderPath
if pFolderPath is empty then put field "folderpath" into pFolderPath
if there is not a folder pFolderPath then exit to top
put files (pFolderPath) into field "list" --> LC function
end getFiles
command getFolder
local tFolderPath
answer folder "Please select the folder path"
if it is empty then exit to top
put it into tFolderPath
put tFolderPath into field "folderPath" -- Local field
end getFolder
function getLinkFiles pFolderPath
## On Windows: Reads the URL or Link of Windows shortcut files with the invisible extension ".lnk" or ".url"
# pFolderPath: Path to the folder that contains 'link' files
# Returns records of 'link' files for a given folder separated by a line containing three dashes/hyphens "---"
local tFileNames -- List of file names in a folder
local tFileName -- Single file name
local tFilePath --The path to a specific file
local tRecordList -- The file list containing records with target file paths
local tContent -- Content of a 'link' or shortcut file (binary for ".ink" files
// Validation
if pFolderPath is empty then
if there is a field "folderPath" then -- Local field
then put field "folderpath" into pFolderPath
end if
end if
if there is not a folder pFolderPath then return "Error: Source Folder does not exist."
put files (pFolderPath) into tFileNames --> LC function
if tFileNames is empty then return "Error: Source Folder contains no files."
// Go through each filename
repeat with i = 1 to the number of lines of tFileNames
set the cursor to busy
put line i of tFileNames into tFileName
put pFolderPath &"/"&tFileName into tFilePath
// Skip files that are not looked at here
// Could be omitted if using filter functions before to filter the requested file types
if ".url" is not in tFileName AND ".lnk" is not in tFileName then
next repeat
end if
// Get the content of the source link file
put URL("binfile:"&tFilePath) into tContent
// Build a record of information associated with the link file and target file/folder
// The format is the same as the standard format of ".url." files
if ".url" is in tFilename then
put word 1 to -1 of tFilename &CR& pFolderPath &CR& word 1 to -1 of tContent &CR&"---"&CR after tRecordList
else if ".lnk" is in tFileName then
put hackLnkFile(tContent) into tContent --> Same script function parsing the binary file format of ".lnk" files
put word 1 to -1 of tFilename &CR& pFolderPath &CR& "[LocalLink]" &CR& word 1 to -1 of tContent &CR&"---"&CR after tRecordList
end if
end repeat
delete last line of tRecordList
return "---"&CR& tRecordList
end getLinkFiles
function hackLnkFile pData
## On Windows: Hack the binary ".lnk" file format with quick 'dirty' solution.
# The Windows file mainly contains binary data and we want to extract the target filepath.
# It would be correct to actually read the relevant bytes from the binary format of ".lnk" files.
# We are not only extracing target file paths, but also target folder paths.
# Returns a filepath string starting from the local system the drive name indicating the target file or folder.
local tComputerName = "xAcer" -- Use your computer name with an "x" in front. This here is my computer name.
local tDriveLetter = "C:\" -- Use the current drive letter
local tNewContent -- Collecting data in the tNewContent string
local tExtList -- Item list of file extension you may look for
local tDelimiter -- A string that seems to delimit the file path extracted
local tChar -- Local char to process
local a,b -- start and ending integers to extract the filepath from the content
// Filtering out valid file name characters
// There are better way using chartonum() checks or filter with REGEX functions.
repeat for each char tChar in pData
// Add whatever characters are used in your language and used to name files
if tChar is in "abcedfghijklmnopqrstuvwsxyzüöäéèà*@|+1234567890 .:\/-[]()_" then put tChar after tNewContent
end repeat
// Use file extensions you are interested in:
put merge(".txt,.pdf,.livecode,.rev,.docx,.xlsx,.png,.pre,[[tComputerName]]") into tExtList
// Get the file extension as a delimiter for each file
repeat for each item tItem in tExtList
if tItem is in tNewContent then
put tItem into tDelimiter
exit repeat
end if
end repeat
// Get the first part of the target file path
put offset(tDriveLetter,tNewContent) into a
put char a to -1 of tNewContent into tNewContent
// Find the end of the target file path
// The logic is from trial and error analyzing the ".lnk" file of Windwos
if tDelimiter is in tNewContent and tDelimiter is not empty then
if tComputerName is tDelimiter then
put offset (tDelimiter,tNewContent) -1 into b
else
put offset (tDelimiter,tNewContent) + length(tDelimiter) -1 into b
end if
else if ".." is in tDelimiter then
put b - length(tDelimiter)-1 into b
else
put -1 into b -- If nothing else works, get the undelimited string
end if
// Return the filepath with "URL =" as the prefix to get the same format as in ".url" files
return "URL ="& char 1 to b of tNewContent
end hackLnkFile
Also, here is a detailed file description published by Microsoft: https://docs.microsoft.com/en-us/opensp ... 1d6cc0f943