Matmaus / LnkParse3

Windows Shortcut file (LNK) parser
MIT License
63 stars 13 forks source link

Shortopt #11

Closed ernix closed 3 years ago

ernix commented 3 years ago

I think it is problematic to create lnk_command just like relative_path + " " + arguments.

A relative path may contain white spaces (e.g. Program Files). Some characters are escaped with ^. https://stackoverflow.com/questions/6828751/batch-character-escaping

Matmaus commented 3 years ago

I think it is problematic to create lnk_command just like relative_path + " " + arguments.

A relative path may contain white spaces (e.g. Program Files). Some characters are escaped with ^. https://stackoverflow.com/questions/6828751/batch-character-escaping

What do you suggest?

ernix commented 3 years ago

Consider rename this parameter. short seems to print just a shorter version of output or something like that. I would suggest using target for example. What do you think?

Yes, I don't like the term short that much either. It implies there is another option long, but not. I think --resolve (without short version) is the appropriate term for this. Please see IShellLinkA document.

About concatenating, I would rather drop command_line_arguments from the default output. To create something from LNK file, we are gonna have to emulate how Windows parse/escape/construct/execute these params. That's tough. We can use subprocess.list2cmdline to quote relative_path with spaces. But I have no idea how to deal with arguments, some examples even contain DOS scripts like redirecting and short-circuit operators.

In [1]: import subprocess

In [2]: help(subprocess.list2cmdline)
Help on function list2cmdline in module subprocess:

list2cmdline(seq)
    Translate a sequence of arguments into a command line
    string, using the same rules as the MS C runtime:

    1) Arguments are delimited by white space, which is either a
       space or a tab.

    2) A string surrounded by double quotation marks is
       interpreted as a single argument, regardless of white space
       contained within.  A quoted string can be embedded in an
       argument.

    3) A double quotation mark preceded by a backslash is
       interpreted as a literal double quotation mark.

    4) Backslashes are interpreted literally, unless they
       immediately precede a double quotation mark.

    5) If backslashes immediately precede a double quotation mark,
       every pair of backslashes is interpreted as a literal
       backslash.  If the number of backslashes is odd, the last
       backslash escapes the next double quotation mark as
       described in rule 3.
Matmaus commented 3 years ago

I think --resolve (without short version) is the appropriate term for this. Please see IShellLinkA document.

Hmm, resolve seems to me like it would do something in the background like "Attempts to find the target of a Shell link, even if it has been moved or renamed". But what it really does is that it simply return target. See "-s", "--short", action="store_true", help="print target only". What do you think?

About concatenating, I would rather drop command_line_arguments from the default output.

I think it is an interesting attribute that should be kept in the default output if possible.

We can use subprocess.list2cmdline to quote relative_path with spaces.

It is a good idea I think.

But I have no idea how to deal with arguments, some examples even contain DOS scripts like redirecting and short-circuit operators.

What is wrong with that? Isn't quoting of path sufficient? Would it be runnable on Windows or not? I think it is not necessary to be able to run it, but I have no problem doing that if you need it.

ernix commented 3 years ago

Hmm, resolve seems to me like it would do something in the background like "Attempts to find the target of a Shell link, even if it has been moved or renamed". But what it really does is that it simply return target. See "-s", "--short", action="store_true", help="print target only". What do you think?

Ah, I think that's right.

What is wrong with that? Isn't quoting of path sufficient? Would it be runnable on Windows or not? I think it is not necessary to be able to run it, but I have no problem doing that if you need it.

OK, I'll quote only relative_path so that we can differentiate it from the rest of command_line_arguments.

ernix commented 3 years ago

Do you think the following results are reasonable?

$ for file in tests/samples/*.lnk; do printf "%s:\t%s\n" "$(basename "$file")" "$(lnkparse -t -f "$file")"; done
lnk_failing.lnk:    ..\AppData\Roaming\.minecraft
lnk_failing2.lnk:   ..\..
lnk_failing3.lnk:   
lnk_failing4.lnk:   ..\AppData\Roaming\.minecraft
lnk_failing5.lnk:   /b
lnk_failing6.lnk:   /vendor:youdao%20/P%20%22C:/Youdao/ShoppingAssistant/ie/4.4
lnk_failing7.lnk:   ..\..\..\..\..\..\..\ProgramData\VК_DJ\VК_DJ.exe
lnk_success.lnk:    .\AnonymusBrowser.exe no_ipcheck - username=05551112233 password=123456
lnk_success2.lnk:   .\AnonymusBrowser.exe no_ipcheck no_resize
lnk_success3.lnk:   "..\..\..\Program Files (x86)\HDZB_USBKEY_NEW1G\HDZB_USBKEY_NEW1G.exe"
lnk_success4.lnk:   .\AnonymusBrowser.exe no_ipcheck
lnk_success5.lnk:   .\AnonymusBrowser.exe no_resize
lnk_success6.lnk:   /c start _ & _\DeviceManager.exe & exit
lnk_success7.lnk:   .\AnonymusBrowser.exe no_ipcheck no_resize username=05551112233 password=123456
lnk_success8.lnk:   .\AnonymusBrowser.exe no_resize username=05551112233 password=123456
lnk_with_broken_link_info.lnk:  "..\..\..\..\..\..\Program Files\xt\xt.exe"
lnk_with_decoding_error.lnk:    ".\.CSV file"
lnk_with_decoding_error2.lnk:   /C .\WindowsServices\movemenoreg.vbs
lnk_with_decoding_error3.lnk:   ".\Mod for Pixelmon\Error Fix.bat"
lnk_with_invalid_date.lnk:  .\.git
lnk_with_invalid_date2.lnk: /c ren cfsdaacdfawd\*.vbss *.vbs &start \cfsdaacdfawd\aiasfacoiaksf.vbs&start explorer .android_secure&exit
lnk_with_invalid_date3.lnk: .\ 
microsoft_example.lnk:  .\a.txt
Matmaus commented 3 years ago

Yes, I think they look good. A good point to quote paths :+1: . I did not know about list2cmdline yet.