Beispiel #1
0
    /// <summary>
    /// Returns a command-line for executing the "0install run" command.
    /// Generates and returns a stub EXE if possible, falls back to directly pointing to the "0install" EXE otherwise.
    /// </summary>
    /// <param name="target">The application to be launched.</param>
    /// <param name="command">The command argument to be passed to the the "0install run" command; can be <c>null</c>.</param>
    /// <param name="machineWide"><c>true</c> place the generated stub in a machine-wide location; <c>false</c> to place it in the current user profile.</param>
    /// <exception cref="OperationCanceledException">The user canceled the task.</exception>
    /// <exception cref="InvalidOperationException">There was a compilation error while generating the stub EXE.</exception>
    /// <exception cref="IOException">A problem occurred while writing to the filesystem.</exception>
    /// <exception cref="WebException">A problem occurred while downloading additional data (such as icons).</exception>
    /// <exception cref="UnauthorizedAccessException">Write access to the filesystem is not permitted.</exception>
    public IReadOnlyList <string> GetRunCommandLine(FeedTarget target, string?command = null, bool machineWide = false)
    {
        string targetKey = target.Uri + "#" + command;

        var  entryPoint = target.Feed.GetEntryPoint(command);
        bool gui        = entryPoint is not {
            NeedsTerminal : true
        };

        string targetHash = targetKey.Hash(SHA256.Create());
        string exeName    = (entryPoint == null)
            ? FeedUri.Escape(target.Feed.Name)
            : entryPoint.BinaryName ?? entryPoint.Command;
        string path = Path.Combine(
            IntegrationManager.GetDir(machineWide, "stubs", targetHash),
            exeName + ".exe");

#if !DEBUG
        try
#endif
        {
            CreateOrUpdateRunStub(path, target, gui, command);
            return(new[] { path });
        }
#if !DEBUG
        catch (Exception ex)
        {
            var exe = GetExe(gui);
            Log.Error($"Failed to generate stub EXE for {targetKey}. Falling back to using '{exe}' directly.", ex);
            return(GetArguments(target.Uri, command, gui)
                   .Prepend(Path.Combine(Locations.InstallBase, exe))
                   .ToList());
        }
#endif
    }
Beispiel #2
0
        /// <inheritdoc/>
        public void Add(FeedUri feedUri, byte[] data)
        {
            #region Sanity checks
            if (feedUri == null)
            {
                throw new ArgumentNullException("feedUri");
            }
            if (data == null)
            {
                throw new ArgumentNullException("data");
            }
            #endregion

            // Add to underlying cache
            _backingCache.Add(feedUri, data);

            // Add to memory cache (replacing existing old versions)
            var feed = XmlStorage.LoadXml <Feed>(new MemoryStream(data));
            feed.Normalize(feedUri);

            string key = feedUri.Escape();
            lock (_feedDictionary)
            {
                _feedDictionary.Remove(key);
                _feedDictionary.Add(key, feed);
            }
        }
Beispiel #3
0
    /// <inheritdoc/>
    public void Add(FeedUri feedUri, byte[] data)
    {
        #region Sanity checks
        if (feedUri == null)
        {
            throw new ArgumentNullException(nameof(feedUri));
        }
        if (data == null)
        {
            throw new ArgumentNullException(nameof(data));
        }
        #endregion

        if (!Directory.Exists(Path))
        {
            Directory.CreateDirectory(Path);
        }

        try
        {
            string path = System.IO.Path.Combine(Path, feedUri.Escape());
            Log.Debug($"Adding feed {feedUri.ToStringRfc()} to disk cache: {path}");
            WriteToFile(data, path);
        }
        catch (PathTooLongException)
        {
            Log.Info("File path in feed cache too long. Using hash of feed URI to shorten path.");
            WriteToFile(data, System.IO.Path.Combine(Path, feedUri.AbsoluteUri.Hash(SHA256.Create())));
        }
    }
Beispiel #4
0
    /// <summary>
    /// Returns a command-line for executing the "0install run" command. Generates and returns a stub EXE if possible, falls back to directly pointing to the "0install" binary otherwise.
    /// </summary>
    /// <param name="target">The application to be launched.</param>
    /// <param name="command">The command argument to be passed to the the "0install run" command; can be <c>null</c>.</param>
    /// <param name="machineWide"><c>true</c> place the generated stub in a machine-wide location; <c>false</c> to place it in the current user profile.</param>
    /// <returns></returns>
    /// <exception cref="OperationCanceledException">The user canceled the task.</exception>
    /// <exception cref="InvalidOperationException">There was a compilation error while generating the stub EXE.</exception>
    /// <exception cref="IOException">A problem occurred while writing to the filesystem.</exception>
    /// <exception cref="WebException">A problem occurred while downloading additional data (such as icons).</exception>
    /// <exception cref="UnauthorizedAccessException">Write access to the filesystem is not permitted.</exception>
    public IReadOnlyList <string> GetRunCommandLine(FeedTarget target, string?command = null, bool machineWide = false)
    {
        var  entryPoint = target.Feed.GetEntryPoint(command);
        bool gui        = entryPoint is not {
            NeedsTerminal : true
        };

        try
        {
#if NETFRAMEWORK
            string hash    = (target.Uri + "#" + command).Hash(SHA256.Create());
            string exeName = (entryPoint == null)
                ? FeedUri.Escape(target.Feed.Name)
                : entryPoint.BinaryName ?? entryPoint.Command;
            string path = Path.Combine(
                IntegrationManager.GetDir(machineWide, "stubs", hash),
                exeName + ".exe");

            CreateOrUpdateRunStub(path, target, gui, command);
            return(new[] { path });
#else
            return(GetArguments(target.Uri, command, gui)
                   .Prepend(GetBinary(gui))
                   .ToList());
#endif
        }
        #region Error handling
        catch (InvalidOperationException ex)
        {
            // Wrap exception since only certain exception types are allowed
            throw new IOException(ex.Message, ex);
        }
        #endregion
    }
Beispiel #5
0
        /// <inheritdoc/>
        public string GetPath(FeedUri feedUri)
        {
            #region Sanity checks
            if (feedUri == null)
            {
                throw new ArgumentNullException(nameof(feedUri));
            }
            #endregion

            if (feedUri.IsFile)
            {
                throw new KeyNotFoundException("Feed cache does not handle local files: " + feedUri.ToStringRfc());
            }

            string fileName = feedUri.Escape();
            string path     = Path.Combine(DirectoryPath, fileName);
            if (FileUtils.ExistsCaseSensitive(path))
            {
                return(path);
            }
            else
            {
                throw new KeyNotFoundException(string.Format(Resources.FeedNotInCache, feedUri, path));
            }
        }
Beispiel #6
0
        /// <inheritdoc/>
        public bool Contains(FeedUri feedUri)
        {
            #region Sanity checks
            if (feedUri == null) throw new ArgumentNullException(nameof(feedUri));
            #endregion

            // Local files are passed through directly
            if (feedUri.IsFile) return File.Exists(feedUri.LocalPath);

            return FileUtils.ExistsCaseSensitive(Path.Combine(DirectoryPath, feedUri.Escape()));
        }
Beispiel #7
0
    /// <inheritdoc/>
    public bool Contains(FeedUri feedUri)
    {
        #region Sanity checks
        if (feedUri == null)
        {
            throw new ArgumentNullException(nameof(feedUri));
        }
        #endregion

        return(feedUri.IsFile
            ? File.Exists(feedUri.LocalPath)
            : FileUtils.ExistsCaseSensitive(System.IO.Path.Combine(Path, feedUri.Escape())));
    }
Beispiel #8
0
        //--------------------//

        #region Contains
        /// <inheritdoc/>
        public bool Contains(FeedUri feedUri)
        {
            #region Sanity checks
            if (feedUri == null)
            {
                throw new ArgumentNullException("feedUri");
            }
            #endregion

            // Local files are passed through directly
            if (feedUri.IsFile)
            {
                return(File.Exists(feedUri.LocalPath));
            }

            return(FileUtils.ExistsCaseSensitive(Path.Combine(DirectoryPath, feedUri.Escape())));
        }
Beispiel #9
0
    /// <inheritdoc/>
    public string?GetPath(FeedUri feedUri)
    {
        #region Sanity checks
        if (feedUri == null)
        {
            throw new ArgumentNullException(nameof(feedUri));
        }
        #endregion

        if (feedUri.IsFile)
        {
            return(feedUri.LocalPath);
        }

        string path = System.IO.Path.Combine(Path, feedUri.Escape());
        return(FileUtils.ExistsCaseSensitive(path) ? path : null);
    }
Beispiel #10
0
        /// <inheritdoc/>
        public void Remove(FeedUri feedUri)
        {
            #region Sanity checks
            if (feedUri == null)
            {
                throw new ArgumentNullException("feedUri");
            }
            #endregion

            // Remove from memory cache
            string key = feedUri.Escape();
            lock (_feedDictionary)
                _feedDictionary.Remove(key);

            // Remove from underlying cache
            _backingCache.Remove(feedUri);
        }
Beispiel #11
0
 /// <summary>
 /// Determines the file path used to store a feed with a particular ID.
 /// </summary>
 /// <exception cref="KeyNotFoundException">The requested <paramref name="feedUri"/> was not found in the cache.</exception>
 private string GetPath(FeedUri feedUri)
 {
     if (feedUri.IsFile)
     {
         return(feedUri.LocalPath);
     }
     {
         string fileName = feedUri.Escape();
         string path     = Path.Combine(DirectoryPath, fileName);
         if (FileUtils.ExistsCaseSensitive(path))
         {
             return(path);
         }
         else
         {
             throw new KeyNotFoundException(string.Format(Resources.FeedNotInCache, feedUri, path));
         }
     }
 }
Beispiel #12
0
        /// <summary>
        /// Builds a stub EXE in a well-known location. Future calls with the same arguments will return the same EXE.
        /// </summary>
        /// <param name="target">The application to be launched via the stub.</param>
        /// <param name="command">The command argument to be passed to the the "0install run" command; can be <c>null</c>.</param>
        /// <param name="handler">A callback object used when the the user is to be informed about the progress of long-running operations such as downloads.</param>
        /// <param name="machineWide">Store the stub in a machine-wide directory instead of just for the current user.</param>
        /// <returns>The path to the generated stub EXE.</returns>
        /// <exception cref="OperationCanceledException">The user canceled the task.</exception>
        /// <exception cref="InvalidOperationException">There was a compilation error while generating the stub EXE.</exception>
        /// <exception cref="IOException">A problem occurs while writing to the filesystem.</exception>
        /// <exception cref="WebException">A problem occured while downloading additional data (such as icons).</exception>
        /// <exception cref="InvalidOperationException">Write access to the filesystem is not permitted.</exception>
        public static string GetRunStub(FeedTarget target, [CanBeNull] string command, [NotNull] ITaskHandler handler, bool machineWide = false)
        {
            #region Sanity checks
            if (handler == null)
            {
                throw new ArgumentNullException(nameof(handler));
            }
            #endregion

            var    entryPoint = target.Feed.GetEntryPoint(command);
            string exeName    = (entryPoint != null)
                ? entryPoint.BinaryName ?? entryPoint.Command
                : FeedUri.Escape(target.Feed.Name);
            bool needsTerminal = (entryPoint != null && entryPoint.NeedsTerminal);

            string hash = (target.Uri + "#" + command).Hash(SHA256.Create());
            string path = Path.Combine(Locations.GetIntegrationDirPath("0install.net", machineWide, "desktop-integration", "stubs", hash), exeName + ".exe");

            CreateOrUpdateRunStub(target, path, command, needsTerminal, handler);
            return(path);
        }
        /// <inheritdoc/>
        public void Add(FeedUri feedUri, byte[] data)
        {
            #region Sanity checks
            if (feedUri == null) throw new ArgumentNullException("feedUri");
            if (data == null) throw new ArgumentNullException("data");
            #endregion

            // Add to underlying cache
            _backingCache.Add(feedUri, data);

            // Add to memory cache (replacing existing old versions)
            var feed = XmlStorage.LoadXml<Feed>(new MemoryStream(data));
            feed.Normalize(feedUri);

            string key = feedUri.Escape();
            lock (_feedDictionary)
            {
                _feedDictionary.Remove(key);
                _feedDictionary.Add(key, feed);
            }
        }
Beispiel #14
0
        /// <inheritdoc/>
        public Feed GetFeed(FeedUri feedUri)
        {
            #region Sanity checks
            if (feedUri == null)
            {
                throw new ArgumentNullException("feedUri");
            }
            #endregion

            string key = feedUri.Escape();
            lock (_feedDictionary)
            {
                if (!_feedDictionary.ContainsKey(key))
                { // Add to memory cache if missing
                    Feed feed = _backingCache.GetFeed(feedUri);
                    _feedDictionary.Add(key, feed);
                    return(feed);
                }

                // Get from memory cache
                return(_feedDictionary[key]);
            }
        }
        /// <summary>
        /// Builds a stub EXE in a well-known location. Future calls with the same arguments will return the same EXE.
        /// </summary>
        /// <param name="target">The application to be launched via the stub.</param>
        /// <param name="command">The command argument to be passed to the the "0install run" command; can be <c>null</c>.</param>
        /// <param name="machineWide">Store the stub in a machine-wide directory instead of just for the current user.</param>
        /// <param name="iconStore">Stores icon files downloaded from the web as local files.</param>
        /// <returns>The path to the generated stub EXE.</returns>
        /// <exception cref="OperationCanceledException">The user canceled the task.</exception>
        /// <exception cref="InvalidOperationException">There was a compilation error while generating the stub EXE.</exception>
        /// <exception cref="IOException">A problem occurred while writing to the filesystem.</exception>
        /// <exception cref="WebException">A problem occurred while downloading additional data (such as icons).</exception>
        /// <exception cref="InvalidOperationException">Write access to the filesystem is not permitted.</exception>
        public static string GetRunStub(FeedTarget target, string?command, IIconStore iconStore, bool machineWide = false)
        {
            #region Sanity checks
            if (iconStore == null)
            {
                throw new ArgumentNullException(nameof(iconStore));
            }
            #endregion

            var    entryPoint = target.Feed.GetEntryPoint(command);
            string exeName    = (entryPoint != null)
                ? entryPoint.BinaryName ?? entryPoint.Command
                : FeedUri.Escape(target.Feed.Name);
            bool needsTerminal = (entryPoint != null && entryPoint.NeedsTerminal);

            string hash = (target.Uri + "#" + command).Hash(SHA256.Create());
            string path = Path.Combine(
                IntegrationManager.GetDir(machineWide, "stubs", hash),
                exeName + ".exe");

            CreateOrUpdateRunStub(target, path, command, needsTerminal, iconStore);
            return(path);
        }
Beispiel #16
0
        /// <inheritdoc/>
        public string GetPath(FeedUri feedUri)
        {
            #region Sanity checks
            if (feedUri == null) throw new ArgumentNullException(nameof(feedUri));
            #endregion

            if (feedUri.IsFile) throw new KeyNotFoundException("Feed cache does not handle local files: " + feedUri.ToStringRfc());

            string fileName = feedUri.Escape();
            string path = Path.Combine(DirectoryPath, fileName);
            if (FileUtils.ExistsCaseSensitive(path)) return path;
            else throw new KeyNotFoundException(string.Format(Resources.FeedNotInCache, feedUri, path));
        }
 /// <summary>
 /// Determines the file path used to store a feed with a particular ID.
 /// </summary>
 /// <exception cref="KeyNotFoundException">The requested <paramref name="feedUri"/> was not found in the cache.</exception>
 private string GetPath(FeedUri feedUri)
 {
     if (feedUri.IsFile) return feedUri.LocalPath;
     {
         string fileName = feedUri.Escape();
         string path = Path.Combine(DirectoryPath, fileName);
         if (FileUtils.ExistsCaseSensitive(path)) return path;
         else throw new KeyNotFoundException(string.Format(Resources.FeedNotInCache, feedUri, path));
     }
 }
        /// <inheritdoc/>
        public void Add(FeedUri feedUri, byte[] data)
        {
            #region Sanity checks
            if (feedUri == null) throw new ArgumentNullException("feedUri");
            if (data == null) throw new ArgumentNullException("data");
            #endregion

            if (!Directory.Exists(DirectoryPath)) Directory.CreateDirectory(DirectoryPath);

            try
            {
                string path = Path.Combine(DirectoryPath, feedUri.Escape());
                Log.Debug("Adding feed " + feedUri.ToStringRfc() + " to disk cache: " + path);
                WriteToFile(data, path);
            }
            catch (PathTooLongException)
            {
                Log.Info("File path in feed cache too long. Using hash of feed URI to shorten path.");
                WriteToFile(data, Path.Combine(DirectoryPath, feedUri.AbsoluteUri.Hash(SHA256.Create())));
            }
        }
        /// <inheritdoc/>
        public Feed GetFeed(FeedUri feedUri)
        {
            #region Sanity checks
            if (feedUri == null) throw new ArgumentNullException("feedUri");
            #endregion

            string key = feedUri.Escape();
            lock (_feedDictionary)
            {
                if (!_feedDictionary.ContainsKey(key))
                { // Add to memory cache if missing
                    Feed feed = _backingCache.GetFeed(feedUri);
                    _feedDictionary.Add(key, feed);
                    return feed;
                }

                // Get from memory cache
                return _feedDictionary[key];
            }
        }
        /// <inheritdoc/>
        public void Remove(FeedUri feedUri)
        {
            #region Sanity checks
            if (feedUri == null) throw new ArgumentNullException("feedUri");
            #endregion

            // Remove from memory cache
            string key = feedUri.Escape();
            lock (_feedDictionary)
                _feedDictionary.Remove(key);

            // Remove from underlying cache
            _backingCache.Remove(feedUri);
        }