safer shortcut migration

This commit is contained in:
Luke Pulverenti 2013-10-01 16:20:48 -04:00
parent 2da4ef2a01
commit 7c9c0c999d
4 changed files with 70 additions and 24 deletions

View File

@ -12,8 +12,8 @@ namespace MediaBrowser.Api.Library
/// </summary> /// </summary>
public static class LibraryHelpers public static class LibraryHelpers
{ {
private const string ShortcutFileExtension = ".lnk"; private const string ShortcutFileExtension = ".mblink";
private const string ShortcutFileSearch = "*.lnk"; private const string ShortcutFileSearch = "*" + ShortcutFileExtension;
/// <summary> /// <summary>
/// Adds the virtual folder. /// Adds the virtual folder.

View File

@ -1,4 +1,6 @@
using MediaBrowser.Model.Logging; using System.Collections.Generic;
using System.Linq;
using MediaBrowser.Model.Logging;
using System; using System;
using System.Collections.Specialized; using System.Collections.Specialized;
using System.IO; using System.IO;
@ -130,16 +132,21 @@ namespace MediaBrowser.Controller.IO
throw new ArgumentNullException("filename"); throw new ArgumentNullException("filename");
} }
return new WindowsShortcut(filename).ResolvedPath; if (string.Equals(Path.GetExtension(filename), ".mblink", StringComparison.OrdinalIgnoreCase))
{
return File.ReadAllText(filename);
}
//var link = new ShellLink(); //return new WindowsShortcut(filename).ResolvedPath;
//((IPersistFile)link).Load(filename, NativeMethods.STGM_READ);
//// TODO: if I can get hold of the hwnd call resolve first. This handles moved and renamed files. var link = new ShellLink();
//// ((IShellLinkW)link).Resolve(hwnd, 0) ((IPersistFile)link).Load(filename, NativeMethods.STGM_READ);
//var sb = new StringBuilder(NativeMethods.MAX_PATH); // TODO: if I can get hold of the hwnd call resolve first. This handles moved and renamed files.
//WIN32_FIND_DATA data; // ((IShellLinkW)link).Resolve(hwnd, 0)
//((IShellLinkW)link).GetPath(sb, sb.Capacity, out data, 0); var sb = new StringBuilder(NativeMethods.MAX_PATH);
//return sb.ToString(); WIN32_FIND_DATA data;
((IShellLinkW)link).GetPath(sb, sb.Capacity, out data, 0);
return sb.ToString();
} }
/// <summary> /// <summary>
@ -160,13 +167,18 @@ namespace MediaBrowser.Controller.IO
throw new ArgumentNullException("target"); throw new ArgumentNullException("target");
} }
var link = new ShellLink(); File.WriteAllText(shortcutPath, target);
((IShellLinkW)link).SetPath(target); //var link = new ShellLink();
((IPersistFile)link).Save(shortcutPath, true); //((IShellLinkW)link).SetPath(target);
//((IPersistFile)link).Save(shortcutPath, true);
} }
private static readonly Dictionary<string, string> ShortcutExtensionsDictionary = new[] { ".mblink", ".lnk" }
.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase);
/// <summary> /// <summary>
/// Determines whether the specified filename is shortcut. /// Determines whether the specified filename is shortcut.
/// </summary> /// </summary>
@ -180,7 +192,9 @@ namespace MediaBrowser.Controller.IO
throw new ArgumentNullException("filename"); throw new ArgumentNullException("filename");
} }
return string.Equals(Path.GetExtension(filename), ".lnk", StringComparison.OrdinalIgnoreCase); var extension = Path.GetExtension(filename);
return !string.IsNullOrEmpty(extension) && ShortcutExtensionsDictionary.ContainsKey(extension);
} }
/// <summary> /// <summary>
@ -258,7 +272,7 @@ namespace MediaBrowser.Controller.IO
public WindowsShortcut(string file) public WindowsShortcut(string file)
{ {
ParseLink(File.ReadAllBytes(file)); ParseLink(File.ReadAllBytes(file), Encoding.UTF8);
} }
private static bool isMagicPresent(byte[] link) private static bool isMagicPresent(byte[] link)
@ -274,7 +288,7 @@ namespace MediaBrowser.Controller.IO
* Gobbles up link data by parsing it and storing info in member fields * Gobbles up link data by parsing it and storing info in member fields
* @param link all the bytes from the .lnk file * @param link all the bytes from the .lnk file
*/ */
private void ParseLink(byte[] link) private void ParseLink(byte[] link, Encoding encoding)
{ {
if (!isMagicPresent(link)) if (!isMagicPresent(link))
throw new IOException("Invalid shortcut; magic is missing", 0); throw new IOException("Invalid shortcut; magic is missing", 0);
@ -317,11 +331,11 @@ namespace MediaBrowser.Controller.IO
const int networkVolumeTable_offset_offset = 0x14; const int networkVolumeTable_offset_offset = 0x14;
const int finalname_offset_offset = 0x18; const int finalname_offset_offset = 0x18;
int finalname_offset = link[file_start + finalname_offset_offset] + file_start; int finalname_offset = link[file_start + finalname_offset_offset] + file_start;
String finalname = getNullDelimitedString(link, finalname_offset); String finalname = getNullDelimitedString(link, finalname_offset, encoding);
if (IsLocal) if (IsLocal)
{ {
int basename_offset = link[file_start + basename_offset_offset] + file_start; int basename_offset = link[file_start + basename_offset_offset] + file_start;
String basename = getNullDelimitedString(link, basename_offset); String basename = getNullDelimitedString(link, basename_offset, encoding);
ResolvedPath = basename + finalname; ResolvedPath = basename + finalname;
} }
else else
@ -330,12 +344,12 @@ namespace MediaBrowser.Controller.IO
int shareName_offset_offset = 0x08; int shareName_offset_offset = 0x08;
int shareName_offset = link[networkVolumeTable_offset + shareName_offset_offset] int shareName_offset = link[networkVolumeTable_offset + shareName_offset_offset]
+ networkVolumeTable_offset; + networkVolumeTable_offset;
String shareName = getNullDelimitedString(link, shareName_offset); String shareName = getNullDelimitedString(link, shareName_offset, encoding);
ResolvedPath = shareName + "\\" + finalname; ResolvedPath = shareName + "\\" + finalname;
} }
} }
private static string getNullDelimitedString(byte[] bytes, int off) private static string getNullDelimitedString(byte[] bytes, int off, Encoding encoding)
{ {
int len = 0; int len = 0;
@ -349,7 +363,7 @@ namespace MediaBrowser.Controller.IO
len++; len++;
} }
return Encoding.UTF8.GetString(bytes, off, len); return encoding.GetString(bytes, off, len);
} }
/* /*

View File

@ -1084,7 +1084,7 @@ namespace MediaBrowser.Server.Implementations.Library
{ {
Name = Path.GetFileName(dir), Name = Path.GetFileName(dir),
Locations = Directory.EnumerateFiles(dir, "*.lnk", SearchOption.TopDirectoryOnly) Locations = Directory.EnumerateFiles(dir, "*.mblink", SearchOption.TopDirectoryOnly)
.Select(FileSystem.ResolveShortcut) .Select(FileSystem.ResolveShortcut)
.OrderBy(i => i) .OrderBy(i => i)
.ToList(), .ToList(),

View File

@ -2,6 +2,7 @@
using MediaBrowser.Common.Constants; using MediaBrowser.Common.Constants;
using MediaBrowser.Common.Implementations.Logging; using MediaBrowser.Common.Implementations.Logging;
using MediaBrowser.Common.Implementations.Updates; using MediaBrowser.Common.Implementations.Updates;
using MediaBrowser.Controller.IO;
using MediaBrowser.Model.Logging; using MediaBrowser.Model.Logging;
using MediaBrowser.Server.Implementations; using MediaBrowser.Server.Implementations;
using MediaBrowser.ServerApplication.Native; using MediaBrowser.ServerApplication.Native;
@ -187,6 +188,8 @@ namespace MediaBrowser.ServerApplication
SystemEvents.SessionEnding += SystemEvents_SessionEnding; SystemEvents.SessionEnding += SystemEvents_SessionEnding;
SystemEvents.SessionSwitch += SystemEvents_SessionSwitch; SystemEvents.SessionSwitch += SystemEvents_SessionSwitch;
MigrateShortcuts(appPaths.RootFolderPath);
_appHost = new ApplicationHost(appPaths, logManager); _appHost = new ApplicationHost(appPaths, logManager);
_app = new App(_appHost, _appHost.LogManager.GetLogger("App"), runService); _app = new App(_appHost, _appHost.LogManager.GetLogger("App"), runService);
@ -523,5 +526,34 @@ namespace MediaBrowser.ServerApplication
/// </summary> /// </summary>
SEM_NOOPENFILEERRORBOX = 0x8000 SEM_NOOPENFILEERRORBOX = 0x8000
} }
private static void MigrateShortcuts(string directory)
{
Directory.CreateDirectory(directory);
foreach (var file in Directory.EnumerateFiles(directory, "*.lnk", SearchOption.AllDirectories).ToList())
{
MigrateShortcut(file);
}
}
private static void MigrateShortcut(string file)
{
var newFile = Path.ChangeExtension(file, ".mblink");
try
{
var resolvedPath = FileSystem.ResolveShortcut(file);
if (!string.IsNullOrEmpty(resolvedPath))
{
FileSystem.CreateShortcut(newFile, resolvedPath);
}
}
finally
{
File.Delete(file);
}
}
} }
} }