From 218b26070a41a5d1b25911b027cc93ffcc1e7c34 Mon Sep 17 00:00:00 2001 From: theadib Date: Mon, 31 Dec 2007 18:27:52 +0000 Subject: [PATCH] win32 installer, do not remove user files --- packaging/win32/MessageBox.txt | 186 ++++++++++++++++++++++++++ packaging/win32/inkscape.nsi | 234 ++++++++++++++++++++++++--------- packaging/win32/md5dll.dll | Bin 0 -> 8192 bytes packaging/win32/messagebox.dll | Bin 0 -> 6144 bytes 4 files changed, 355 insertions(+), 65 deletions(-) create mode 100644 packaging/win32/MessageBox.txt create mode 100644 packaging/win32/md5dll.dll create mode 100644 packaging/win32/messagebox.dll diff --git a/packaging/win32/MessageBox.txt b/packaging/win32/MessageBox.txt new file mode 100644 index 000000000..dddab5553 --- /dev/null +++ b/packaging/win32/MessageBox.txt @@ -0,0 +1,186 @@ +Customisable MessageBox Plug-In (v0.98 beta 3) + +[ Archive Page: http://nsis.sourceforge.net/archive/??? ] + +-------------- + +The Customisable MessageBox plug-in allows you to use a MessageBox in your installer which can be altered to how you want it to be. You can control: + * the number of buttons shown + * the text each button shows + * a standard or customisable icon ( flexible so you can use the installer or other files ) + * a fully working 'forth' button! + +The plug-in uses a few tricks to allow for the messagebox functionality to be altered so that the button text can finally be altered making [ Yes | Yes to All | No | No to All ] ( and anything else you care for ) possible. + +Also with the changes made it is now possible to have a functional 'forth' button - yes you read correctly! When using the function just pass in four button texts and you will see the forth button - simple really :o) + +There is only the one function to show the messagebox so enjoy. + +[ As of v0.98 beta the parameters of calling the function have changed, check out usage for the revised options - thanks to n0On3 for the suggestions. ] + + +Usage +----- + +messagebox::show styles caption ( module_name, icon_id ) text but1 [ but2 but3 but4 ] + +styles - messagebox styles ( supports most of the windows messagebox styles ) + +caption - the text to be used for the dialog title ( or the installer title if not specified ) + +module_name - sets the name of the file ( usually a dll or exe file ) that contains the custom icon to be used - if 0 is passed then the installer will be used + +icon_id - the id of the icon group to be used for the custom icon + +text - the text to be shown by the messagebox + +but1 - specified text or name id to use ie IDYES, IDNO, etc ( there must always be at least one button ) + +but2, but3, but4 - optional buttons which follow the same way as for but1 + + +When passing in options, you should use a "" pair for options you pass in to ensure the strings are correctly read. It is not necessary to do so for the predefined button texts +e.g. "IDCANCEL" is the same as IDCANCEL. + +See Example.nsi for an example ;o) ( bit hacked at the moment due to testing but shows most things ) + + +Return Values +----- + +To get the return value use Pop $0 immediately after the function has been used incase other functions alter the value. + +If there were no problems then the function will return the number of the button pressed working from the left being 'button 1'. +i.e. + if you have [ yes | no | abort ] and 'no' is selected then the return value will be '2' + +If an error happens then the messagebox will return 0. + +If there are no buttons passed then the function will return '-1'. + + +Some More Info +---------------- + +If you pass an empty string for the caption ( "" ) then the installer title text will be used instead (stripping back the current section name as NSIS messageboxes do). +If the installer is run silently then the title will be blank if setting the caption option to "" ( as NSIS messageboxes do ). This is because when the installer is silent it does not have a visible window and so will not have a window title ( had not taken this into account initially, oops - fixed from v0.98 beta 3 ). + +When you want to use a custom icon, setting module to '0' will look for the icon in the installer otherwise it will search the file specified. +e.g. + "0,103" will load the installer icon ( well in testing it does :o) ) + "shell32.dll,24" will load the help file icon from the shell32.dll ( as long as the file exists! ) + +If the module passed is not valid then the usericon style will not be used ( you may receive a windows message informing of this ). + +If the icon is not valid then the messagebox will just show a blank area where the icon would be displayed assuming that the value of module is valid. + +If a usericon is specified then if there are any of the messagebox icon styles passed in, these will be ignored. This allows an icon to appear otherwise internal style conflicts will prevent any icon being shown. + +If you want to display the standard button texts then pass the following strings in for the necessary button: + + IDOK - Ok + IDCANCEL - Cancel + IDABORT - Abort + IDRETRY - Retry + IDIGNORE - Ignore + IDYES - Yes + IDNO - No + IDHELP - Help / 4th button + IDTRYAGAIN - Try Again + IDCONTINUE - Continue + +When the function is processing the passed button texts to use, if a duplicate of the predefined texts (above) happen then the only the first instance will be allowed +e.g. + IDYES "ah go on if you dare" IDYES -> [ YES | ah go on if you dare ] + +Each button will be resized if needed to allow the text to fit correctly in the button without being clipped. If the text is still too long for the messagebox width ( limited to 80% of the screen width ) then buttons will be resized and clipping of the button text may happen again ( this will be fixed in v1.0 ). + + +Final Notes +------- + +I have no idea how the code will work with international text (since i just use plain text in the code) so if you try it in a multilanguage setup then let me know how it reacts or if there are any issues with the function's display. + +The predefined button texts are hard coded and cannot be altered. To alter the default texts involves passing in the language button text as a custom button text. + +The button resizing code is not complete at the moment ( as can be clearly seen from the first messagebox ) when it detects that the width of the messagebox is at the 80% screen width. Issues are that the buttons are not correctly resized to ensure that they appear correctly ( as is the case with the second messagebox ). This is more down to fiddling with the button widths after the initial processing but will be fixed soon :o) + + +Credits +------- + +Coded by Darren Owen, aka DrO (Sept 2003) + +n0On3 - Idea request and helpful feedback ( the simplified function use over previous versions :o) ) + +A plugin from me to you :o) + + +Version History +------- + +v0.1 +* Initial release of the function +* Basic support to show that the button text can be altered on the messagebox +* Inital support for controlling the number of buttons shown + +v0.5 +* Setting of text of only the buttons wanted ( "/but? blah" ) +* Now if a string is not passed then the text will not be set (broken in the v0.1 release) +* Altered a lot of internal workings to allow for more customising of the MessageBox +* Better support for the number of buttons to show +* The functional '4th' button - making use of the 'Help' button to act as a real button +* Fixed a number of crash issues due to buffer sizes and a few other bugs, etc + +v0.8 +* A lot of changes made :o) +* Improved internal handling so that now button text is set correctly either when the number of buttons is set or user styles are set so now "/but2 blah" will always set the second buttons text and not just a few cases as beforehand +* Altered the order of the parameters from earlier versions to make some internals easier to do :o) +* The 4th / Help button will now close the MessageBox in ALL cases - would not close correctly if there was not a 'cancel' button in earlier versions +* Buffers are now allocated to the NSIS buffer sizes passed to the dll on use for better compatibility between dll and installer +* When the button numbers are set, the function will map the returned value now to the button selected instead of the normal wndows defined return value +* some other bits and bobs that i've forgotten on the way + +v0.9 +* Added in support for displaying custom icons on the messagebox ( along with standard icons which can be shown ) either in the installer or from other files +* Altered the example script to show off some more bits of what it can do + +v0.95 beta +* Added in support for resizing of buttons based on the text set into the button ( use the /trim before the text to be set ) +* Messagebox is now limited to approximately 80% of the screen size ( as the messagebox normally does ) +* The resizing of button texts will also update the width of the text width to ensure it keeps to the size of the messagebox +* Support is not complete for /trim ( still need to update the graduating of the width increment ) +* When the 80% width is reached, currently buttons will disappear off the messagebox ( handling for a double height button will come to cope with this soon ) +* Altered the example script to show off some more bits of what it can do + +v0.98 beta +* Removed the passing in of a hwnd parameter - is always owned by the installer +* Altered the custom icon option to be a single parameter now in the form 'module,id' where module can be 0 to use the installer +* All return values are now mapped to the button number pressed ie 1,2,etc +* Now the number of buttons to show is based on the button string texts passed in to the function :o) +* Altered the order of parameters to work in a top to bottom order with respect to the messagebox layout and to match closer to the NSIS setup +[ a good suggestion from n0On3 - nice ] +- now goes: style title usericon text but1 [ but2 but3 but4 ] +* Altered the button texts to be set in the order passed and will also convert the default ids too! eg IDYES -> "Yes", IDIGNORE -> "Ignore" +* Fixed the graduating of the button trim feature to appear 'natural' +[ adds approxiamately 3 character widths either side when the text won't fit fully in the button ] +* Fixed a few bugs in the code introduced in the changes made +* Support for MB_DEFBUTTON? is broken when a button has to be resized ( will fix this soon - already worked out how to but not why this happens ) + +v0.98 beta 2 +* Fixed the MB_DEFBUTTON? issue ( needed to prevent the wm_active message being handled ) +* Verified the installer will show icons correctly if the installer is run silently ( no code changes were made ) +* Added in checking of the defined buttons to ensure that duplicates are not allowed (only the first occurrance is allowed) +* Checked that all strings are verified for having data before being used +* A few code tidy-ups introduced to the code +* Typo fix in the example +* Added in stripping out of the icon definitions if a user icon is specified (otherwise no icon will appear!) +* Updated the readme file to reflect the changes made to the plug-in's functionality since v0.98 beta and to clarify things in better detail now ( i hope ) +* Added in a reference to the archive page for the plugin ( will upload majority of this file to the archive ) +* All internal buffers are now set to the buffer size passed into the plugin when it is called and altered how they are referenced +* Fixed how the module string is cleared, should fix a potential crash issue i hope +* Partially fixed the resizing of the text area when using long button strings to correctly limit out when the 80% limit is reached ( fine when now icon is used at the moment ) +* Added a silent installer option to the example script, just !define SILENT to get the silent version (should show that the function works fine either in a normal or silent installer) + +v0.98 beta 3 +* Fixed a crash when a silent installer is run ( pointed out by n0On3 ) - not checking the string length when getting the installer title if ""is the pased caption value, doh! \ No newline at end of file diff --git a/packaging/win32/inkscape.nsi b/packaging/win32/inkscape.nsi index 2b70ab239..db241cd13 100644 --- a/packaging/win32/inkscape.nsi +++ b/packaging/win32/inkscape.nsi @@ -12,6 +12,7 @@ !define PRODUCT_WEB_SITE "http://www.inkscape.org" !define PRODUCT_DIR_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\inkscape.exe" !define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" +;!define UNINST_EXE "uninstall.exe" @@ -48,6 +49,10 @@ SetCompressor /SOLID lzma ;!insertmacro UNATTENDED_UNINSTALL !insertmacro INTERACTIVE_UNINSTALL +!addplugindir . +!include "FileFunc.nsh" +!insertmacro un.GetParent + ; Welcome page !insertmacro MUI_PAGE_WELCOME @@ -482,7 +487,9 @@ FunctionEnd ReadRegStr $2 HKU "$1\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" AppData StrCmp $2 "" delprefs-Loop DetailPrint "$2\Inkscape will be removed" - RMDir /r "$2\Inkscape" + Delete "$2\Inkscape\preferences.xml" + Delete "$2\Inkscape\extension-errors.log" + RMDir "$2\Inkscape" Goto delprefs-Loop delprefs-End: !macroend @@ -490,54 +497,26 @@ FunctionEnd ;-------------------------------- ; Installer Sections -; @todo better idea is to call the original uninstaller first Section -removeInkscape ; check for an old installation and clean that dlls and stuff - ClearErrors - IfFileExists $INSTDIR\etc 0 doDeleteLib - DetailPrint "$INSTDIR\etc exists, will be removed" - RmDir /r $INSTDIR\etc - IfErrors 0 +4 - DetailPrint "fatal: failed to delete $INSTDIR\etc" - DetailPrint "aborting installation" - Abort - doDeleteLib: - - ClearErrors - IfFileExists $INSTDIR\lib 0 doDeleteLocale - DetailPrint "$INSTDIR\lib exists, will be removed" - RmDir /r $INSTDIR\lib - IfErrors 0 +4 - DetailPrint "fatal: failed to delete $INSTDIR\lib" - DetailPrint "aborting installation" - Abort - doDeleteLocale: - - ClearErrors - IfFileExists $INSTDIR\locale 0 doDeleteDll - DetailPrint "$INSTDIR\locale exists, will be removed" - RmDir /r $INSTDIR\locale - IfErrors 0 +4 - DetailPrint "fatal: failed to delete $INSTDIR\locale" - DetailPrint "aborting installation" - Abort - doDeleteDll: - ClearErrors - FindFirst $0 $1 $INSTDIR\*.dll - FindNextLoop: - StrCmp $1 "" FindNextDone - DetailPrint "$INSTDIR\$1 exists, will be removed" - Delete $INSTDIR\$1 - IfErrors 0 +4 - DetailPrint "fatal: failed to delete $INSTDIR\$1" - DetailPrint "aborting installation" - Abort +FindFirstINSTDIR: + FindFirst $0 $1 $INSTDIR\*.* +FindINSTDIR: + StrCmp $1 "" FindNextDoneINSTDIR + StrCmp $1 "." FindNextINSTDIR + StrCmp $1 ".." FindNextINSTDIR + Goto FoundSomethingINSTDIR +FindNextINSTDIR: FindNext $0 $1 - Goto FindNextLoop - FindNextDone: - - ;remove the old inkscape shortcuts from the startmenu + Goto FindINSTDIR +FoundSomethingINSTDIR: +; @TODO translate + MessageBox MB_RETRYCANCEL "${PRODUCT_NAME} must be installed in an empty directory. $INSTDIR ($1) is not empty. Please clear this directory first!$(lng_OK_CANCEL_DESC)" /SD IDCANCEL IDRETRY FindFirstINSTDIR + Quit +FindNextDoneINSTDIR: + + ;remove the old inkscape shortcuts from the startmenu ;just in case they are still there SetShellVarContext current Delete "$SMPROGRAMS\Inkscape\Uninstall Inkscape.lnk" @@ -980,6 +959,7 @@ SectionGroupEnd Section -FinalizeInstallation + DetailPrint "finalize installation" StrCmp $MultiUser "1" "" SingleUser DetailPrint "admin mode, registry root will be HKLM" SetShellVarContext all @@ -1011,7 +991,7 @@ Section -FinalizeInstallation ; uninstall settings ClearErrors ; WriteUninstaller "$INSTDIR\uninst.exe" - WriteRegExpandStr SHCTX "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\${UNINST_EXE}" + WriteRegExpandStr SHCTX "${PRODUCT_UNINST_KEY}" "UninstallString" "${UNINST_EXE}" WriteRegExpandStr SHCTX "${PRODUCT_UNINST_KEY}" "InstallDir" "$INSTDIR" WriteRegExpandStr SHCTX "${PRODUCT_UNINST_KEY}" "InstallLocation" "$INSTDIR" WriteRegStr SHCTX "${PRODUCT_UNINST_KEY}" "DisplayName" "${PRODUCT_NAME} ${PRODUCT_VERSION}" @@ -1021,6 +1001,36 @@ Section -FinalizeInstallation WriteRegDWORD SHCTX "${PRODUCT_UNINST_KEY}" "NoRepair" "1" IfErrors 0 +2 DetailPrint "fatal: failed to write to registry un-installation info" + + ;create/update log always within .onInstSuccess function + !insertmacro UNINSTALL.LOG_UPDATE_INSTALL + + DetailPrint "create MD5 sums" + md5dll::GetMD5File /NOUNLOAD "$INSTDIR\inkscape.exe" + Pop $1 ;md5 of file + DetailPrint $1 + ClearErrors + FileOpen $0 $INSTDIR\uninstall.dat r + FileOpen $9 $INSTDIR\uninstall.log w + IfErrors doneinstall +readnextlineinstall: + ClearErrors + FileRead $0 $1 + IfErrors doneinstall + StrCpy $1 $1 -2 + DetailPrint $1 + md5dll::GetMD5File /NOUNLOAD $1 + Pop $2 + DetailPrint $2 + StrCmp $2 "" +2 + FileWrite $9 "$2 $1$\r$\n" + Goto readnextlineinstall +doneinstall: + FileClose $0 + FileClose $9 + ; this file is not needed anymore + Delete $INSTDIR\uninstall.dat + SectionEnd ; Last the Descriptions @@ -1120,9 +1130,10 @@ Function .onInit ReadRegStr $R1 HKCU ${PRODUCT_UNINST_KEY} "DisplayName" StrCmp $R0 "" uninstall_before_done - MessageBox MB_YESNO|MB_ICONEXCLAMATION $(lng_WANT_UNINSTALL_BEFORE) /SD IDNO IDYES +1 IDNO uninstall_before_done + MessageBox MB_YESNO|MB_ICONEXCLAMATION $(lng_WANT_UNINSTALL_BEFORE) /SD IDNO IDNO uninstall_before_done ;Run the uninstaller ;uninst: + DetailPrint "execute $R0 in $INSTDIR" ClearErrors ExecWait '$R0 _?=$INSTDIR' ;Do not copy the uninstaller to a temp file uninstall_before_done: @@ -1230,8 +1241,7 @@ FunctionEnd Function .onInstSuccess - ;create/update log always within .onInstSuccess function - !insertmacro UNINSTALL.LOG_UPDATE_INSTALL + FunctionEnd ; -------------------------------------------------- @@ -1251,7 +1261,7 @@ FunctionEnd Function un.onInit ;begin uninstall, could be added on top of uninstall section instead - !insertmacro UNINSTALL.LOG_BEGIN_UNINSTALL + ;!insertmacro UNINSTALL.LOG_BEGIN_UNINSTALL ClearErrors StrCpy $User "" @@ -1292,6 +1302,61 @@ Function un.onInit FunctionEnd +# removes a file and if the directory is empty afterwards the directory also +# push md5, push filename, call unremovefilename +Function un.RemoveFile + Var /Global filename + Var /Global md5sum + Var /Global ismd5sum + Var /Global removenever ; never remove a touched file + Var /Global removealways ; always remove files touched by user + Pop $filename + Pop $md5sum + + IfFileExists $filename +2 0 + Return + StrCmp $removealways "always" unremovefile 0 + md5dll::GetMD5File /NOUNLOAD $filename + Pop $ismd5sum ;md5 of file + StrCmp $md5sum $ismd5sum unremovefile 0 + DetailPrint "uups MD5 does not match" + StrCmp $removenever "never" 0 +2 + Return + ; the md5 sums does not match so we ask + ; @TODO translate + messagebox::show MB_DEFBUTTON3|MB_TOPMOST "deleting changed file" "0,103" \ + "The file has been changed after installation.$\r$\nDo you still want to delete that file?" \ + "Yes" "always answer YES" "No" "always answer NO" + ;DetailPrint "messagebox finished" + Pop $md5sum + ;DetailPrint "messagebox call returned... $md5sum" + StrCmp $md5sum "1" unremovefile 0 ; Yes + StrCmp $md5sum "2" 0 unremoveno ; Yes always + StrCpy $removealways "always" + ;DetailPrint "removealways" + Goto unremovefile +unremoveno: + StrCmp $md5sum "3" 0 unremovenever ; No + ;DetailPrint "No remove" + Return +unremovenever: + StrCpy $removenever "never" + ;DetailPrint "removenever" + Return +unremovefile: + ;DetailPrint "removefile" + ClearErrors + Delete $filename + ;now recursivly remove the path +unrmdir: + ${un.GetParent} $filename $filename + IfErrors 0 +2 + Return + RMDir $filename + IfErrors +2 + Goto unrmdir +FunctionEnd + Section Uninstall ; remove personal settings @@ -1300,7 +1365,7 @@ Section Uninstall DetailPrint "purge personal settings in $APPDATA\Inkscape" ;RMDir /r "$APPDATA\Inkscape" !insertmacro delprefs - endPurge: + endPurge: ; Remove file associations for svg editor DetailPrint "removing file associations for svg editor" @@ -1426,24 +1491,63 @@ Section Uninstall DetailPrint "removing uninstall info" ;uninstall from path, must be repeated for every install logged path individual - !insertmacro UNINSTALL.LOG_UNINSTALL "$INSTDIR\lib\locale" - !insertmacro UNINSTALL.LOG_UNINSTALL "$INSTDIR\locale" - !insertmacro UNINSTALL.LOG_UNINSTALL "$INSTDIR\doc" - !insertmacro UNINSTALL.LOG_UNINSTALL "$INSTDIR\share\tutorials" - !insertmacro UNINSTALL.LOG_UNINSTALL "$INSTDIR\share\templates" - !insertmacro UNINSTALL.LOG_UNINSTALL "$INSTDIR\share\screens" - !insertmacro UNINSTALL.LOG_UNINSTALL "$INSTDIR\share\clipart" - !insertmacro UNINSTALL.LOG_UNINSTALL "$INSTDIR\share\extensions" - !insertmacro UNINSTALL.LOG_UNINSTALL "$INSTDIR\share\icons" - !insertmacro UNINSTALL.LOG_UNINSTALL "$INSTDIR\share" - !insertmacro UNINSTALL.LOG_UNINSTALL "$INSTDIR\modules" - !insertmacro UNINSTALL.LOG_UNINSTALL "$INSTDIR\python" - !insertmacro UNINSTALL.LOG_UNINSTALL "$INSTDIR" + ;!insertmacro UNINSTALL.LOG_UNINSTALL "$INSTDIR\lib\locale" + ;!insertmacro UNINSTALL.LOG_UNINSTALL "$INSTDIR\locale" + ;!insertmacro UNINSTALL.LOG_UNINSTALL "$INSTDIR\doc" + ;!insertmacro UNINSTALL.LOG_UNINSTALL "$INSTDIR\share\tutorials" + ;!insertmacro UNINSTALL.LOG_UNINSTALL "$INSTDIR\share\templates" + ;!insertmacro UNINSTALL.LOG_UNINSTALL "$INSTDIR\share\screens" + ;!insertmacro UNINSTALL.LOG_UNINSTALL "$INSTDIR\share\clipart" + ;!insertmacro UNINSTALL.LOG_UNINSTALL "$INSTDIR\share\extensions" + ;!insertmacro UNINSTALL.LOG_UNINSTALL "$INSTDIR\share\icons" + ;!insertmacro UNINSTALL.LOG_UNINSTALL "$INSTDIR\share" + ;!insertmacro UNINSTALL.LOG_UNINSTALL "$INSTDIR\modules" + ;!insertmacro UNINSTALL.LOG_UNINSTALL "$INSTDIR\python" + ;!insertmacro UNINSTALL.LOG_UNINSTALL "$INSTDIR" ;end uninstall, after uninstall from all logged paths has been performed - !insertmacro UNINSTALL.LOG_END_UNINSTALL + ;!insertmacro UNINSTALL.LOG_END_UNINSTALL ;RMDir /r "$INSTDIR" + + StrCpy $removenever "" + StrCpy $removealways "" + + InitPluginsDir + SetPluginUnload manual + + ClearErrors + FileOpen $0 $INSTDIR\uninstall.log r + IfErrors uninstallnotfound +readnextline: + ClearErrors + FileRead $0 $1 + IfErrors done + ; cat the line into md5 and filename + StrLen $2 $1 + IntCmp $2 35 readnextline readnextline + StrCpy $3 $1 32 + StrCpy $4 $1 $2-36 34 #remove trailing CR/LF + StrCpy $4 $4 -2 + Push $3 + Push $4 + Call un.RemoveFile + Goto readnextline +uninstallnotfound: +; @TODO translate + MessageBox MB_OK "Fatal! $INSTDIR\uninstall.log not found! Please clear directory $INSTDIR yourself!" /SD IDOK +done: + FileClose $0 + + Delete "$INSTDIR\uninstall.log" + Delete "$INSTDIR\uninstall.exe" + ; remove empty directories + RMDir "$INSTDIR\data" + RMDir "$INSTDIR\doc" + RMDir "$INSTDIR\modules" + RMDir "$INSTDIR\plugins" + + RMDir $INSTDIR SetAutoClose false diff --git a/packaging/win32/md5dll.dll b/packaging/win32/md5dll.dll new file mode 100644 index 0000000000000000000000000000000000000000..abefbb038a43eaca6e223dee72e9ae69328fb99c GIT binary patch literal 8192 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 literal 0 HcmV?d00001 diff --git a/packaging/win32/messagebox.dll b/packaging/win32/messagebox.dll new file mode 100644 index 0000000000000000000000000000000000000000..97407fa1af6005ea3b68b2c43cd58defb2e8e514 GIT binary patch literal 6144 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 a@3jxv_uA9;to_^eN&6}LEA~IPa{3=xZwkQx literal 0 HcmV?d00001 -- 2.30.2