internal PackageItem(PackageSource source, string id, string version)
        {
            Id = id;
            Version = version;
            PackageSource = source;

            FastPath = source.MakeFastPath(id, version);
        }
 public WebSearch(PackageSource source)
 {
     _source = source;
 }
        /// <summary>
        /// Searches package sources given name and version information 
        /// 
        /// Package information must be returned using <c>request.YieldPackage(...)</c> function.
        /// </summary>
        /// <param name="name">a name or partial name of the package(s) requested</param>
        /// <param name="requiredVersion">A specific version of the package. Null or empty if the user did not specify</param>
        /// <param name="minimumVersion">A minimum version of the package. Null or empty if the user did not specify</param>
        /// <param name="maximumVersion">A maximum version of the package. Null or empty if the user did not specify</param>
        /// <param name="id">if this is greater than zero (and the number should have been generated using <c>StartFind(...)</c>, the core is calling this multiple times to do a batch search request. The operation can be delayed until <c>CompleteFind(...)</c> is called</param>
        /// <param name="request">An object passed in from the CORE that contains functions that can be used to interact with the CORE and HOST</param>
        public void FindPackage(string name, string requiredVersion, string minimumVersion, string maximumVersion, int id, IRequest request)
        {
            request.Debug("Calling '{0}::FindPackage' '{1}','{2}','{3}','{4}'", PackageProviderName, requiredVersion, minimumVersion, maximumVersion, id);

            List<PackageSource> sources;
            var providerPackageSources = ProviderStorage.GetPackageSources(request);

            if (request.Sources != null && request.Sources.Any())
            {
                sources = new List<PackageSource>();

                foreach (var userRequestedSource in request.Sources)
                {
                    if (providerPackageSources.ContainsKey(userRequestedSource))
                    {
                        sources.Add(providerPackageSources[userRequestedSource]);
                    }
                }
            }
            else
            {
                sources = providerPackageSources.Select(i => i.Value).ToList();
            }

            if (request.IsCanceled)
            {
                return;
            }

            foreach (var source in sources)
            {
                var downloadLinks = new HashSet<Uri>();
                var webSearch = new WebSearch(source);
                var downloadWebsites = webSearch.Search(name, 3);

                foreach (var downloadWebsite in downloadWebsites)
                {
                    try
                    {
                        var downloadLink = DownloadLinkFinder.GetDownloadLink(downloadWebsite).Result;

                        // TODO: for now we're returning all potential downloads for the user to choose from
                        // TODO: we could provide our own ranking, e.g. check if downloadLink is the same domain as url
                        if (downloadLink != null && downloadLinks.Add(downloadLink))
                        {
                            var domainName = downloadLink.GetLeftPart(UriPartial.Authority).Replace("/www.", "/").Replace("http://", "").Replace("https://", "");
                            var packageSource = new PackageSource(domainName, domainName);
                            var packageItem = new PackageItem(packageSource, downloadLink.ToString(), "");

                            // YieldPackage returns false when operation was cancelled
                            if (!request.YieldPackage(packageItem, name))
                            {
                                return;
                            }
                        }
                    }
                    catch (Exception)
                    {
                        continue;
                    }
                }
            }
        }