Function that makes absolute paths from relative ones
Author: romca (talk, contrib) |
Description
This function modifies configuration files. It finds relative paths and changes them to be absolute.
How To Use
Push "/" ;what makes a directory delimiter - i.e. backslash "\", or forward slash "/", or "::" Push "D:/MyApplication/onCD/Dir2" ;the base directory (where do I stand?) - must have the same delimiters as above Push "C:\MyApplication\configuration.conf" ;the file that will be modified Call MakeAbsolutePath
This will result in:
"./swish-e.exe" => "D:/MyApplication/onCD/Dir2/swish-e.exe" "../swish-e.exe" => "D:/MyApplication/onCD/swish-e.exe" './swish-e.exe' => './swish-e.exe' "../../../index.swish-e" => "D:/index.swish-e"
And in this nonsense:
"../../../../../../../index.swish-e" => "D:/../../../../index.swish-e"
It is up to you to check if the relative address is correct and you should not use this "./../../myfile.exe". The function is not so clever. You can use "." or ".." but not both in one string.
You can use forward as well as backward slashes, colons, semicolons - whatever you want to delimit directories, but it must to be found in your conf files and in the string that you are passing on to the function. If you do not want to replace something, enclose it in single quotation marks '../../swish-e.exe'
The function doesn't modify variables, but needs the three subfunctions that start with rca - do dot remove them.
Example
Push "/" Push "$EXEDIR\myplace" Push "C:\MyApplication\configuration.conf" Call MakeAbsolutePath
The Functions (MakeAbsolutePath + rca*)
Function MakeAbsolutePath Exch $0 ;the file to search in Exch Exch $1 ;the manipulated string Exch 2 Exch $2 ;the directory delimiter Exch Push $3 Push $4 Push $5 Push $6 Push $R1 Push $R2 Push $R3 Push $R4 Push $R5 StrCpy $3 "" StrCpy $4 "" StrCpy $5 "" StrCpy $6 "" StrCpy $R1 "" StrCpy $R2 "" StrCpy $R3 "" StrCpy $R4 "" StrCpy $R5 "" StrCpy $R3 $1 ;the base directory StrCpy $5 $2 ;delimiter ClearErrors #we start to search for ..$5 (../) - from the short to the longest (../../../.....) StrCpy $R1 "..$5" loop_dir: Push $0 Push "$\"$R1" Call rcaFileSearch ;get things out of the stack after the rcaFileSearch finished Pop $3 Pop $2 Pop $4 #DetailPrint " function rcaFileSearch found($\"$R1) ? :($3), ($2) occurrences in ($4) rows"; StrCmp $3 yes 0 this_check StrCpy $R2 $R1 ;if we found short, we will try to find a longer one StrCpy $R1 "$R1..$5" Goto loop_dir this_check: StrCmp $R2 "" single_dir 0 StrCpy $R1 $R2 ;the latest successful string eg. "../../../" Strlen $R2 $R1 ;its length Strlen $6 $5 IntOp $6 $6 + 2 IntOp $R4 $R2 / $6 ;the number of directories in string eg. 6/3=2 #DetailPrint "the number of directories in the string that will be cut off ($R4)" #here we have the longest string and the number of directories we may cut off from the base dir Strlen $3 $R3 Big_loop: StrCpy $1 0 StrCpy $2 0 ClearErrors Small_loop: IfErrors single_dir IntOp $1 $1 - 1 StrCmp "$1" "-255" bezpecnostni_pojistka ;emergency check, decrease the number of found directories and start again StrCpy $R5 $R3 1 $1 StrCmp $R5 "$5" 0 Small_loop IntOp $2 $2 + 1 StrCmp $2 $R4 0 Small_loop ;if the number of loops equals to the number of directories IntOp $6 $3 + $1 StrCpy $R5 $R3 $6 StrCpy $R5 "$R5$5" Push "$\"$R1" #text to be replaced , adding \" Push "$\"$R5" #replace with Push all #replace all occurrences Push all #replace all occurrences Push $0 #file to replace in Call rcaAdvReplaceInFile bezpecnostni_pojistka: IntOp $R4 $R4 - 1 StrCpy $R1 $R1 -3 StrCmp $R4 0 "" Big_loop single_dir: StrCpy $R3 "$R3$5" Push "$\".$5" #text to be replaced Push "$\"$R3" #replace with Push all #replace all occurrences Push all #replace all occurrences Push $0 #file to replace in Call rcaAdvReplaceInFile Pop $R5 Pop $R4 Pop $R3 Pop $R2 Pop $R1 Pop $6 Pop $5 Pop $4 Pop $3 Pop $0 Pop $2 Pop $1 FunctionEnd ;------------------- + ----------------------- Function rcaFileSearch #this function was written by -Stu (Afrow UK) #and is accessible from nsis web pages #thanks Exch $0 ;search for Exch Exch $1 ;input file Exch Push $2 Push $3 Push $4 Push $5 Push $6 Push $7 Push $8 Push $9 Push $R0 ClearErrors FileOpen $2 $1 r StrLen $4 $0 StrCpy $5 0 StrCpy $7 no StrCpy $8 0 StrCpy $9 0 loop_main: FileRead $2 $3 IfErrors done IntOp $R0 $R0 + $9 StrCpy $9 0 StrCpy $5 0 filter_top: IntOp $5 $5 - 1 StrCpy $6 $3 $4 $5 StrCmp $6 "" loop_main StrCmp $6 $0 0 filter_top StrCpy $3 $3 $5 StrCpy $5 0 StrCpy $7 yes StrCpy $9 1 IntOp $8 $8 + 1 Goto filter_top done: FileClose $2 StrCpy $0 $8 StrCpy $1 $7 StrCpy $2 $R0 Pop $R0 Pop $9 Pop $8 Pop $7 Pop $6 Pop $5 Pop $4 Pop $3 ;Exch 2 Exch $2 ;output number of lines Exch 2 Exch Exch $0 ;output yes/no Exch Exch $1 ;output count found FunctionEnd ;------------------- + ----------------------- Function rcaAdvReplaceInFile #again, written by Afrow UK 2003-05-18 #I think that there is problem when you do not want to replace all occurrences of text #but this is not my case Exch $0 ;file to replace in Exch Exch $1 ;number to replace after Exch Exch 2 Exch $2 ;replace and onwards Exch 2 Exch 3 Exch $3 ;replace with Exch 3 Exch 4 Exch $4 ;to replace Exch 4 Push $5 ;minus count Push $6 ;universal Push $7 ;end string Push $8 ;left string Push $9 ;right string Push $R0 ;file1 Push $R1 ;file2 Push $R2 ;read Push $R3 ;universal Push $R4 ;count (onwards) Push $R5 ;count (after) Push $R6 ;temp file name GetTempFileName $R6 FileOpen $R1 $0 r ;file to search in FileOpen $R0 $R6 w ;temp file StrLen $R3 $4 StrCpy $R4 -1 StrCpy $R5 -1 loop_read: ClearErrors FileRead $R1 $R2 ;read line IfErrors exit StrCpy $5 0 StrCpy $7 $R2 loop_filter: IntOp $5 $5 - 1 StrCpy $6 $7 $R3 $5 ;search StrCmp $6 "" file_write1 ;here was "file_write2" StrCmp $6 $4 0 loop_filter StrCpy $8 $7 $5 ;left part IntOp $6 $5 + $R3 StrCpy $9 $7 "" $6 ;right part StrLen $6 $7 StrCpy $7 $8$3$9 ;re-join ; DetailPrint "-$6 $5 $7" StrCmp -$6 $5 0 loop_filter IntOp $R4 $R4 + 1 StrCmp $2 all file_write1 StrCmp $R4 $2 0 file_write2 IntOp $R4 $R4 - 1 IntOp $R5 $R5 + 1 StrCmp $1 all file_write1 StrCmp $R5 $1 0 file_write1 IntOp $R5 $R5 - 1 Goto file_write2 file_write1: FileWrite $R0 $7 ;write modified line Goto loop_read file_write2: FileWrite $R0 $R2 ;write unmodified line Goto loop_read exit: FileClose $R0 FileClose $R1 SetDetailsPrint none Delete $0 Rename $R6 $0 Delete $R6 SetDetailsPrint both Pop $R6 Pop $R5 Pop $R4 Pop $R3 Pop $R2 Pop $R1 Pop $R0 Pop $9 Pop $8 Pop $7 Pop $6 Pop $5 Pop $0 Pop $1 Pop $2 Pop $3 Pop $4 FunctionEnd ;==================================================== Function rcaChangeBackslash Exch $R1 ;string to search in Push $R2 Push $R3 Push $1 StrCpy $R2 "" StrCpy $R3 "" ClearErrors StrCpy "$1" 0 #counter ; GetFullPathName /SHORT $R1 $9 Znovu: StrCpy "$R2" "$R1" 1 "$1" StrCmp "$R2" "" Konec "" StrCmp "$R2" "\" "" +2 StrCpy "$R2" "/" StrCpy "$R3" "$R3$R2" IntOp "$1" "$1" + 1 Goto Znovu Konec: StrCpy $R1 $R3 Pop $1 Pop $R3 Pop $R2 Exch $R1 FunctionEnd
(rca 2004-04)
Good luck.