【问题标题】:PHP: How do you determine if a file is a shortcut on Windows platforms?PHP:如何确定文件是否是 Windows 平台上的快捷方式?
【发布时间】:2011-08-02 16:57:39
【问题描述】:

不包括尚未与 PHP 捆绑的任何 3rd 方扩展,是否有任何方法可以确定 Windows 机器上的给定文件是否为快捷方式/链接?内置函数 is_link 仅适用于 *nix 平台,因此在 Windows 机器上运行的以下内容不会返回预期结果:

$filePath = 'C:\somefile.lnk'; // path to shortcut file
var_dump(is_file($filePath)); // returns true
var_dump(is_link($filePath)); // returns false

这会在尝试使用快捷方式的目标文件时导致问题,并最终对快捷方式文件本身进行操作。快捷方式的前四个字节似乎通常是4c 00 00 00。但这个开始字节序列总是仅限于快捷方式似乎并不可靠。

附带问题: 如何从快捷方式文件中提取目标路径? (注:readlink() 似乎返回了快捷方式文件本身的路径)。

编辑:只是为了省点麻烦,根据PHP使用finfomime_content_type的快捷方式文件的mime类型是“application/octet-stream”,实际上不会帮助。

【问题讨论】:

  • is_link 页面上,Windows workaround
  • 此外,windows .lnk 文件只是由 Windows shell 解释的桌面文件。 NTFS 有一些真正的符号链接和硬链接支持。 (不确定is_link 是否与他们打交道。)
  • @Tim Cooper:我看到了。我认为这是一次伟大的尝试,但对于该用户如何设计该解决方案缺乏任何形式的引用。我还找到了几个对快捷方式文件进行逆向工程的示例,但没有官方的。也许还有更具体的事情要做?

标签: php windows shortcuts


【解决方案1】:

就像填写答案一样。几年前写的,不确定它是否适用于当前的 Windows 版本。

要检查魔术字节,只需使用:

 $bin = file_get_contents("file.lnk", 2048);
 if (substr($bin, 0, 20) == "L\000\000\000\001\024\002\000\000\000\000\000\300\000\000\000\000\000\000F") {

如果你想提取路径:

  function decode_windows_visual_shortcut($bin) {

            # taken from "The Windows Shortcut File Format.pdf" V1.0 as
            # reverse-engineered by Jesse Hager <jessehager@iname.com> 

            if (!defined("WIN_LNK_F_ITEMLIST")) {

                    define("WIN_LNK_F_ITEMLIST", 1);
                    define("WIN_LNK_F_FILE", 2);
                    define("WIN_LNK_F_DESC", 4);
                    define("WIN_LNK_F_RELATIVE", 8);
                    define("WIN_LNK_F_WORKDIR", 16);
                    define("WIN_LNK_F_CMDARGS", 32);
                    define("WIN_LNK_F_ICON", 64);   
                    define("WIN_LNK_F2_DIR", 16);   

                    function bread(&$bin, &$p, $bytes=4) {
                            $h = bin2hex( strrev($s = substr($bin, $p, $bytes)) );
                            $v = base_convert($h, 16, 10);
                            $p += $bytes;
                            return($v);  
                    }
            }

            $res = array();
            $p = 0x14;
            $fl=$res["flags"] = bread($bin,$p);
            $res["t_attr"] = bread($bin,$p);   
            $p = 0x4C;

            if ($fl & WIN_LNK_F_ITEMLIST) {
                    #-- don't need this
                    $p += bread($bin,$p,2);
            }

            if ($fl & WIN_LNK_F_FILE) {
                    #-- File Location Info
                    $p0 = $p;
                    $p = $p0 + 0x10;
                    $p_path = $p0 + bread($bin,$p);
                    $p = $p0 + 0x18;
                    $p_file = $p0 + bread($bin,$p);
                    $path = substr($bin, $p_path, 704);
                    $path = substr($path, 0, strpos($path, "\000"));
                    $file = substr($bin, $p_file, 704);
                    $file = substr($file, 0, strpos($file, "\000"));
                    $res["path"] = $path;
                    $res["file"] = $file;
            }

            return($res);
    }

http://code.google.com/p/8bits/downloads/detail?name=The_Windows_Shortcut_File_Format.pdf

【讨论】:

  • 到目前为止,您的 substr($bin, 0, 20) == ... 位看起来不错。但是该死的。我可能需要一点时间来验证这一切。让我回复你。
猜你喜欢
  • 1970-01-01
  • 2011-04-18
  • 1970-01-01
  • 1970-01-01
  • 2013-09-22
  • 2018-05-07
  • 2020-11-18
  • 1970-01-01
相关资源
最近更新 更多