Remove unused NugetCore code

This commit is contained in:
Caelan Sayler
2021-08-12 13:51:24 +01:00
parent 213aef318a
commit 8a8a0e8dad
51 changed files with 0 additions and 6371 deletions

View File

@@ -1,101 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Linq;
namespace NuGet
{
public class ConfigurationDefaults
{
private ISettings _settingsManager = NullSettings.Instance;
private const string ConfigurationDefaultsFile = "NuGetDefaults.config";
private static readonly ConfigurationDefaults _instance = InitializeInstance();
private bool _defaultPackageSourceInitialized;
private List<PackageSource> _defaultPackageSources;
private string _defaultPushSource;
private static ConfigurationDefaults InitializeInstance()
{
var baseDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "NuGet");
PhysicalFileSystem fileSystem = new PhysicalFileSystem(baseDirectory);
return new ConfigurationDefaults(fileSystem, ConfigurationDefaultsFile);
}
/// <summary>
/// An internal constructor MAINLY INTENDED FOR TESTING THE CLASS. But, the product code is only expected to use the static Instance property
/// Only catches FileNotFoundException. Will throw all exceptions including other IOExceptions and XmlExceptions for invalid xml and so on
/// </summary>
/// <param name="fileSystem"></param>
/// <param name="path"></param>
internal ConfigurationDefaults(IFileSystem fileSystem, string path)
{
try
{
if (fileSystem.FileExists(path))
{
_settingsManager = new Settings(fileSystem, path);
}
}
catch (FileNotFoundException)
{
}
// Intentionally, we don't catch all IOExceptions, XmlException or other file related exceptions like UnAuthorizedAccessException
// This way, administrator will become aware of the failures when the ConfigurationDefaults file is not valid or permissions are not set properly
}
public static ConfigurationDefaults Instance
{
get
{
return _instance;
}
}
public IEnumerable<PackageSource> DefaultPackageSources
{
get
{
if (_defaultPackageSources == null)
{
_defaultPackageSources = new List<PackageSource>();
IList<SettingValue> disabledPackageSources = _settingsManager.GetSettingValues("disabledPackageSources", isPath: false);
IList<SettingValue> packageSources = _settingsManager.GetSettingValues("packageSources", isPath: false);
foreach (var settingValue in packageSources)
{
// In a SettingValue representing a package source, the Key represents the name of the package source and the Value its source
_defaultPackageSources.Add(new PackageSource(settingValue.Value,
settingValue.Key,
isEnabled: !disabledPackageSources.Any<SettingValue>(p => p.Key.Equals(settingValue.Key, StringComparison.CurrentCultureIgnoreCase)),
isOfficial: true));
}
}
return _defaultPackageSources;
}
}
public string DefaultPushSource
{
get
{
if (_defaultPushSource == null && !_defaultPackageSourceInitialized)
{
_defaultPackageSourceInitialized = true;
_defaultPushSource = _settingsManager.GetConfigValue("DefaultPushSource");
}
return _defaultPushSource;
}
}
public string DefaultPackageRestoreConsent
{
get
{
return _settingsManager.GetValue("packageRestore", "enabled");
}
}
}
}

View File

@@ -1,27 +0,0 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
namespace NuGet
{
public interface ISettings
{
string GetValue(string section, string key);
string GetValue(string section, string key, bool isPath);
[SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is the best fit for this internal class")]
IList<KeyValuePair<string, string>> GetValues(string section);
IList<SettingValue> GetSettingValues(string section, bool isPath);
[SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is the best fit for this internal class")]
IList<KeyValuePair<string, string>> GetNestedValues(string section, string key);
void SetValue(string section, string key, string value);
[SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is the best fit for this internal class")]
void SetValues(string section, IList<KeyValuePair<string, string>> values);
[SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is the best fit for this internal class")]
void SetNestedValues(string section, string key, IList<KeyValuePair<string, string>> values);
bool DeleteValue(string section, string key);
bool DeleteSection(string section);
}
}

View File

@@ -1,67 +0,0 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using NuGet.Resources;
namespace NuGet
{
public class NullSettings : ISettings
{
private static readonly NullSettings _settings = new NullSettings();
public static NullSettings Instance
{
get { return _settings; }
}
public string GetValue(string section, string key)
{
return String.Empty;
}
public string GetValue(string section, string key, bool isPath)
{
return String.Empty;
}
public IList<KeyValuePair<string, string>> GetValues(string section)
{
return new List<KeyValuePair<string, string>>().AsReadOnly();
}
public IList<SettingValue> GetSettingValues(string section, bool isPath)
{
return new List<SettingValue>().AsReadOnly();
}
public IList<KeyValuePair<string, string>> GetNestedValues(string section, string key)
{
return new List<KeyValuePair<string, string>>().AsReadOnly();
}
public void SetValue(string section, string key, string value)
{
throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, NuGetResources.InvalidNullSettingsOperation, "SetValue"));
}
public void SetValues(string section, IList<KeyValuePair<string, string>> values)
{
throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, NuGetResources.InvalidNullSettingsOperation, "SetValues"));
}
public void SetNestedValues(string section, string key, IList<KeyValuePair<string, string>> values)
{
throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, NuGetResources.InvalidNullSettingsOperation, "SetNestedValues"));
}
public bool DeleteValue(string section, string key)
{
throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, NuGetResources.InvalidNullSettingsOperation, "DeleteValue"));
}
public bool DeleteSection(string section)
{
throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, NuGetResources.InvalidNullSettingsOperation, "DeleteSection"));
}
}
}

View File

@@ -1,46 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NuGet
{
public class SettingValue
{
public SettingValue(string key, string value, bool isMachineWide, int priority = 0)
{
Key = key;
Value = value;
IsMachineWide = isMachineWide;
Priority = priority;
}
public string Key { get; private set; }
public string Value { get; private set; }
public bool IsMachineWide { get; private set; }
// The priority of this setting in the nuget.config hierarchy. Bigger number means higher priority.
public int Priority { get; private set; }
public override bool Equals(object obj)
{
var rhs = obj as SettingValue;
if (rhs == null)
{
return false;
}
return rhs.Key == Key &&
rhs.Value == Value &&
rhs.IsMachineWide == rhs.IsMachineWide;
}
public override int GetHashCode()
{
return Tuple.Create(Key, Value, IsMachineWide).GetHashCode();
}
}
}

View File

@@ -1,746 +0,0 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Threading;
using System.Xml;
using System.Xml.Linq;
using NuGet.Resources;
namespace NuGet
{
public class Settings : ISettings
{
private readonly XDocument _config;
private readonly IFileSystem _fileSystem;
private readonly string _fileName;
// next config file to read if any
private Settings _next;
private readonly bool _isMachineWideSettings;
// The priority of this setting file
private int _priority;
public Settings(IFileSystem fileSystem)
: this(fileSystem, Constants.SettingsFileName, false)
{
}
public Settings(IFileSystem fileSystem, string fileName)
: this(fileSystem, fileName, false)
{
}
public Settings(IFileSystem fileSystem, string fileName, bool isMachineWideSettings)
{
if (fileSystem == null)
{
throw new ArgumentNullException("fileSystem");
}
if (String.IsNullOrEmpty(fileName))
{
throw new ArgumentException(CommonResources.Argument_Cannot_Be_Null_Or_Empty, "fileName");
}
_fileSystem = fileSystem;
_fileName = fileName;
XDocument conf = null;
ExecuteSynchronized(() => conf = XmlUtility.GetOrCreateDocument("configuration", _fileSystem, _fileName));
_config = conf;
_isMachineWideSettings = isMachineWideSettings;
}
/// <summary>
/// Flag indicating whether this file is a machine wide settings file. A machine wide settings
/// file will not be modified.
/// </summary>
public bool IsMachineWideSettings
{
get { return _isMachineWideSettings; }
}
public string ConfigFilePath
{
get
{
return Path.IsPathRooted(_fileName) ?
_fileName :
Path.GetFullPath(Path.Combine(_fileSystem.Root, _fileName));
}
}
/// <summary>
/// Loads user settings from the NuGet configuration files. The method walks the directory
/// tree in <paramref name="fileSystem"/> up to its root, and reads each NuGet.config file
/// it finds in the directories. It then reads the user specific settings,
/// which is file <paramref name="configFileName"/>
/// in <paramref name="fileSystem"/> if <paramref name="configFileName"/> is not null,
/// If <paramref name="configFileName"/> is null, the user specific settings file is
/// %AppData%\NuGet\NuGet.config.
/// After that, the machine wide settings files are added.
/// </summary>
/// <remarks>
/// For example, if <paramref name="fileSystem"/> is c:\dir1\dir2, <paramref name="configFileName"/>
/// is "userConfig.file", the files loaded are (in the order that they are loaded):
/// c:\dir1\dir2\nuget.config
/// c:\dir1\nuget.config
/// c:\nuget.config
/// c:\dir1\dir2\userConfig.file
/// machine wide settings (e.g. c:\programdata\NuGet\Config\*.config)
/// </remarks>
/// <param name="fileSystem">The file system to walk to find configuration files.
/// Can be null.</param>
/// <param name="configFileName">The user specified configuration file.</param>
/// <param name="machineWideSettings">The machine wide settings. If it's not null, the
/// settings files in the machine wide settings are added after the user sepcific
/// config file.</param>
/// <returns>The settings object loaded.</returns>
public static ISettings LoadDefaultSettings(
IFileSystem fileSystem,
string configFileName,
IMachineWideSettings machineWideSettings)
{
// Walk up the tree to find a config file; also look in .nuget subdirectories
var validSettingFiles = new List<Settings>();
if (fileSystem != null)
{
validSettingFiles.AddRange(
GetSettingsFileNames(fileSystem)
.Select(f => ReadSettings(fileSystem, f))
.Where(f => f != null));
}
LoadUserSpecificSettings(validSettingFiles, fileSystem, configFileName);
if (machineWideSettings != null)
{
validSettingFiles.AddRange(
machineWideSettings.Settings.Select(
s => new Settings(s._fileSystem, s._fileName, s._isMachineWideSettings)));
}
if (validSettingFiles.IsEmpty())
{
// This means we've failed to load all config files and also failed to load or create the one in %AppData%
// Work Item 1531: If the config file is malformed and the constructor throws, NuGet fails to load in VS.
// Returning a null instance prevents us from silently failing and also from picking up the wrong config
return NullSettings.Instance;
}
validSettingFiles[0]._priority = validSettingFiles.Count;
// if multiple setting files were loaded, chain them in a linked list
for (int i = 1; i < validSettingFiles.Count; ++i)
{
validSettingFiles[i]._next = validSettingFiles[i - 1];
validSettingFiles[i]._priority = validSettingFiles[i - 1]._priority - 1;
}
// return the linked list head. Typicall, it's either the config file in %ProgramData%\NuGet\Config,
// or the user specific config (%APPDATA%\NuGet\nuget.config) if there are no machine
// wide config files. The head file is the one we want to read first, while the user specific config
// is the one that we want to write to.
// TODO: add UI to allow specifying which one to write to
return validSettingFiles.Last();
}
private static void LoadUserSpecificSettings(
List<Settings> validSettingFiles,
IFileSystem fileSystem,
string configFileName)
{
// for the default location, allow case where file does not exist, in which case it'll end
// up being created if needed
Settings appDataSettings = null;
if (configFileName == null)
{
// load %AppData%\NuGet\NuGet.config
string appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
if (!String.IsNullOrEmpty(appDataPath))
{
var defaultSettingsFilePath = Path.Combine(
appDataPath, "NuGet", Constants.SettingsFileName);
// Since defaultSettingsFilePath is a full path, so it doesn't matter what value is
// used as root for the PhysicalFileSystem.
appDataSettings = ReadSettings(
fileSystem ?? new PhysicalFileSystem(@"c:\"),
defaultSettingsFilePath);
}
}
else
{
if (!fileSystem.FileExists(configFileName))
{
string message = String.Format(CultureInfo.CurrentCulture,
NuGetResources.FileDoesNotExit,
fileSystem.GetFullPath(configFileName));
throw new InvalidOperationException(message);
}
appDataSettings = ReadSettings(fileSystem, configFileName);
}
if (appDataSettings != null)
{
validSettingFiles.Add(appDataSettings);
}
}
/// <summary>
/// Loads the machine wide settings.
/// </summary>
/// <remarks>
/// For example, if <paramref name="paths"/> is {"IDE", "Version", "SKU" }, then
/// the files loaded are (in the order that they are loaded):
/// %programdata%\NuGet\Config\IDE\Version\SKU\*.config
/// %programdata%\NuGet\Config\IDE\Version\*.config
/// %programdata%\NuGet\Config\IDE\*.config
/// %programdata%\NuGet\Config\*.config
/// </remarks>
/// <param name="fileSystem">The file system in which the settings files are read.</param>
/// <param name="paths">The additional paths under which to look for settings files.</param>
/// <returns>The list of settings read.</returns>
public static IEnumerable<Settings> LoadMachineWideSettings(
IFileSystem fileSystem,
params string[] paths)
{
List<Settings> settingFiles = new List<Settings>();
string basePath = @"NuGet\Config";
string combinedPath = Path.Combine(paths);
while (true)
{
string directory = Path.Combine(basePath, combinedPath);
// load setting files in directory
foreach (var file in fileSystem.GetFiles(directory, "*.config"))
{
var settings = ReadSettings(fileSystem, file, true);
if (settings != null)
{
settingFiles.Add(settings);
}
}
if (combinedPath.Length == 0)
{
break;
}
int index = combinedPath.LastIndexOf(Path.DirectorySeparatorChar);
if (index < 0)
{
index = 0;
}
combinedPath = combinedPath.Substring(0, index);
}
return settingFiles;
}
public string GetValue(string section, string key)
{
return GetValue(section, key, isPath: false);
}
public string GetValue(string section, string key, bool isPath)
{
if (String.IsNullOrEmpty(section))
{
throw new ArgumentException(CommonResources.Argument_Cannot_Be_Null_Or_Empty, "section");
}
if (String.IsNullOrEmpty(key))
{
throw new ArgumentException(CommonResources.Argument_Cannot_Be_Null_Or_Empty, "key");
}
XElement element = null;
string ret = null;
var curr = this;
while (curr != null)
{
XElement newElement = curr.GetValueInternal(section, key, element);
if (!object.ReferenceEquals(element, newElement))
{
element = newElement;
// we need to evaluate using current Settings in case value needs path transformation
ret = curr.ElementToValue(element, isPath);
}
curr = curr._next;
}
return ret;
}
private static string ResolvePath(string configDirectory, string value)
{
// Three cases for when Path.IsRooted(value) is true:
// 1- C:\folder\file
// 2- \\share\folder\file
// 3- \folder\file
// In the first two cases, we want to honor the fully qualified path
// In the last case, we want to return X:\folder\file with X: drive where config file is located.
// However, Path.Combine(path1, path2) always returns path2 when Path.IsRooted(path2) == true (which is current case)
var root = Path.GetPathRoot(value);
// this corresponds to 3rd case
if (root != null && root.Length == 1 && (root[0] == Path.DirectorySeparatorChar || value[0] == Path.AltDirectorySeparatorChar))
{
return Path.Combine(Path.GetPathRoot(configDirectory), value.Substring(1));
}
return Path.Combine(configDirectory, value);
}
private string ElementToValue(XElement element, bool isPath)
{
if (element == null)
{
return null;
}
// Return the optional value which if not there will be null;
string value = element.GetOptionalAttributeValue("value");
if (!isPath || String.IsNullOrEmpty(value))
{
return value;
}
return _fileSystem.GetFullPath(ResolvePath(Path.GetDirectoryName(ConfigFilePath), value));
}
private XElement GetValueInternal(string section, string key, XElement curr)
{
// Get the section and return curr if it doesn't exist
var sectionElement = GetSection(_config.Root, section);
if (sectionElement == null)
{
return curr;
}
// Get the add element that matches the key and return curr if it doesn't exist
return FindElementByKey(sectionElement, key, curr);
}
public IList<KeyValuePair<string, string>> GetValues(string section)
{
return GetValues(section, isPath: false);
}
private IList<KeyValuePair<string, string>> GetValues(string section, bool isPath)
{
var values = GetSettingValues(section, isPath);
return values.Select(v => new KeyValuePair<string, string>(v.Key, v.Value)).ToList().AsReadOnly();
}
public IList<SettingValue> GetSettingValues(string section, bool isPath)
{
if (String.IsNullOrEmpty(section))
{
throw new ArgumentException(CommonResources.Argument_Cannot_Be_Null_Or_Empty, "section");
}
var settingValues = new List<SettingValue>();
var curr = this;
while (curr != null)
{
curr.PopulateValues(section, settingValues, isPath);
curr = curr._next;
}
return settingValues.AsReadOnly();
}
private void PopulateValues(string section, List<SettingValue> current, bool isPath)
{
var sectionElement = GetSection(_config.Root, section);
if (sectionElement != null)
{
ReadSection(sectionElement, current, isPath);
}
}
public IList<KeyValuePair<string, string>> GetNestedValues(string section, string key)
{
if (String.IsNullOrEmpty(section))
{
throw new ArgumentException(CommonResources.Argument_Cannot_Be_Null_Or_Empty, "section");
}
if (String.IsNullOrEmpty(key))
{
throw new ArgumentException(CommonResources.Argument_Cannot_Be_Null_Or_Empty, "key");
}
var values = new List<SettingValue>();
var curr = this;
while (curr != null)
{
curr.PopulateNestedValues(section, key, values);
curr = curr._next;
}
return values.Select(v => new KeyValuePair<string, string>(v.Key, v.Value)).ToList().AsReadOnly();
}
private void PopulateNestedValues(string section, string key, List<SettingValue> current)
{
var sectionElement = GetSection(_config.Root, section);
if (sectionElement == null)
{
return;
}
var subSection = GetSection(sectionElement, key);
if (subSection == null)
{
return;
}
ReadSection(subSection, current, isPath: false);
}
public void SetValue(string section, string key, string value)
{
// machine wide settings cannot be changed.
if (IsMachineWideSettings)
{
if (_next == null)
{
throw new InvalidOperationException(NuGetResources.Error_NoWritableConfig);
}
_next.SetValue(section, key, value);
return;
}
if (String.IsNullOrEmpty(section))
{
throw new ArgumentException(CommonResources.Argument_Cannot_Be_Null_Or_Empty, "section");
}
var sectionElement = GetOrCreateSection(_config.Root, section);
SetValueInternal(sectionElement, key, value);
Save();
}
public void SetValues(string section, IList<KeyValuePair<string, string>> values)
{
// machine wide settings cannot be changed.
if (IsMachineWideSettings)
{
if (_next == null)
{
throw new InvalidOperationException(NuGetResources.Error_NoWritableConfig);
}
_next.SetValues(section, values);
return;
}
if (String.IsNullOrEmpty(section))
{
throw new ArgumentException(CommonResources.Argument_Cannot_Be_Null_Or_Empty, "section");
}
if (values == null)
{
throw new ArgumentNullException("values");
}
var sectionElement = GetOrCreateSection(_config.Root, section);
foreach (var kvp in values)
{
SetValueInternal(sectionElement, kvp.Key, kvp.Value);
}
Save();
}
public void SetNestedValues(string section, string key, IList<KeyValuePair<string, string>> values)
{
// machine wide settings cannot be changed.
if (IsMachineWideSettings)
{
if (_next == null)
{
throw new InvalidOperationException(NuGetResources.Error_NoWritableConfig);
}
_next.SetNestedValues(section, key, values);
return;
}
if (String.IsNullOrEmpty(section))
{
throw new ArgumentException(CommonResources.Argument_Cannot_Be_Null_Or_Empty, "section");
}
if (values == null)
{
throw new ArgumentNullException("values");
}
var sectionElement = GetOrCreateSection(_config.Root, section);
var element = GetOrCreateSection(sectionElement, key);
foreach (var kvp in values)
{
SetValueInternal(element, kvp.Key, kvp.Value);
}
Save();
}
private void SetValueInternal(XElement sectionElement, string key, string value)
{
if (String.IsNullOrEmpty(key))
{
throw new ArgumentException(CommonResources.Argument_Cannot_Be_Null_Or_Empty, "key");
}
if (value == null)
{
throw new ArgumentNullException("value");
}
var element = FindElementByKey(sectionElement, key, null);
if (element != null)
{
element.SetAttributeValue("value", value);
Save();
}
else
{
sectionElement.AddIndented(new XElement("add",
new XAttribute("key", key),
new XAttribute("value", value)));
}
}
public bool DeleteValue(string section, string key)
{
// machine wide settings cannot be changed.
if (IsMachineWideSettings)
{
if (_next == null)
{
throw new InvalidOperationException(NuGetResources.Error_NoWritableConfig);
}
return _next.DeleteValue(section, key);
}
if (String.IsNullOrEmpty(section))
{
throw new ArgumentException(CommonResources.Argument_Cannot_Be_Null_Or_Empty, "section");
}
if (String.IsNullOrEmpty(key))
{
throw new ArgumentException(CommonResources.Argument_Cannot_Be_Null_Or_Empty, "key");
}
var sectionElement = GetSection(_config.Root, section);
if (sectionElement == null)
{
return false;
}
var elementToDelete = FindElementByKey(sectionElement, key, null);
if (elementToDelete == null)
{
return false;
}
elementToDelete.RemoveIndented();
Save();
return true;
}
public bool DeleteSection(string section)
{
// machine wide settings cannot be changed.
if (IsMachineWideSettings)
{
if (_next == null)
{
throw new InvalidOperationException(NuGetResources.Error_NoWritableConfig);
}
return _next.DeleteSection(section);
}
if (String.IsNullOrEmpty(section))
{
throw new ArgumentException(CommonResources.Argument_Cannot_Be_Null_Or_Empty, "section");
}
var sectionElement = GetSection(_config.Root, section);
if (sectionElement == null)
{
return false;
}
sectionElement.RemoveIndented();
Save();
return true;
}
private void ReadSection(XContainer sectionElement, ICollection<SettingValue> values, bool isPath)
{
var elements = sectionElement.Elements();
foreach (var element in elements)
{
string elementName = element.Name.LocalName;
if (elementName.Equals("add", StringComparison.OrdinalIgnoreCase))
{
var v = ReadValue(element, isPath);
values.Add(new SettingValue(v.Key, v.Value, _isMachineWideSettings, _priority));
}
else if (elementName.Equals("clear", StringComparison.OrdinalIgnoreCase))
{
values.Clear();
}
}
}
private void Save()
{
ExecuteSynchronized(() => _fileSystem.AddFile(_fileName, _config.Save));
}
// When isPath is true, then the setting value is checked to see if it can be interpreted
// as relative path. If it can, the returned value will be the full path of the relative path.
// If it cannot be interpreted as relative path, the value is returned as-is.
private KeyValuePair<string, string> ReadValue(XElement element, bool isPath)
{
var keyAttribute = element.Attribute("key");
var valueAttribute = element.Attribute("value");
if (keyAttribute == null || String.IsNullOrEmpty(keyAttribute.Value) || valueAttribute == null)
{
throw new InvalidDataException(String.Format(CultureInfo.CurrentCulture, NuGetResources.UserSettings_UnableToParseConfigFile, ConfigFilePath));
}
var value = valueAttribute.Value;
Uri uri;
if (isPath && Uri.TryCreate(value, UriKind.Relative, out uri))
{
string configDirectory = Path.GetDirectoryName(ConfigFilePath);
value = _fileSystem.GetFullPath(Path.Combine(configDirectory, value));
}
return new KeyValuePair<string, string>(keyAttribute.Value, value);
}
private static XElement GetSection(XElement parentElement, string section)
{
section = XmlConvert.EncodeLocalName(section);
return parentElement.Element(section);
}
private static XElement GetOrCreateSection(XElement parentElement, string sectionName)
{
sectionName = XmlConvert.EncodeLocalName(sectionName);
var section = parentElement.Element(sectionName);
if (section == null)
{
section = new XElement(sectionName);
parentElement.AddIndented(section);
}
return section;
}
private static XElement FindElementByKey(XElement sectionElement, string key, XElement curr)
{
XElement result = curr;
foreach (var element in sectionElement.Elements())
{
string elementName = element.Name.LocalName;
if (elementName.Equals("clear", StringComparison.OrdinalIgnoreCase))
{
result = null;
}
else if (elementName.Equals("add", StringComparison.OrdinalIgnoreCase) &&
element.GetOptionalAttributeValue("key").Equals(key, StringComparison.OrdinalIgnoreCase))
{
result = element;
}
}
return result;
}
/// <remarks>
/// Order is most significant (e.g. applied last) to least significant (applied first)
/// ex:
/// c:\foo\nuget.config
/// c:\nuget.config
/// </remarks>
private static IEnumerable<string> GetSettingsFileNames(IFileSystem fileSystem)
{
// for dirs obtained by walking up the tree, only consider setting files that already exist.
// otherwise we'd end up creating them.
foreach (var dir in GetSettingsFilePaths(fileSystem))
{
string fileName = Path.Combine(dir, Constants.SettingsFileName);
if (fileSystem.FileExists(fileName))
{
yield return fileName;
}
}
}
private static IEnumerable<string> GetSettingsFilePaths(IFileSystem fileSystem)
{
string root = fileSystem.Root;
while (root != null)
{
yield return root;
root = Path.GetDirectoryName(root);
}
}
private static Settings ReadSettings(IFileSystem fileSystem, string settingsPath)
{
return ReadSettings(fileSystem, settingsPath, false);
}
private static Settings ReadSettings(IFileSystem fileSystem, string settingsPath, bool isMachineWideSettings)
{
try
{
return new Settings(fileSystem, settingsPath, isMachineWideSettings);
}
catch (XmlException)
{
return null;
}
}
/// <summary>
/// Wrap all IO operations on setting files with this function to avoid file-in-use errors
/// </summary>
private void ExecuteSynchronized(Action ioOperation)
{
var fileName = _fileSystem.GetFullPath(_fileName);
// Global: ensure mutex is honored across TS sessions
using (var mutex = new Mutex(false, "Global\\" + EncryptionUtility.GenerateUniqueToken(fileName)))
{
var owner = false;
try
{
// operations on NuGet.config should be very short lived
owner = mutex.WaitOne(TimeSpan.FromMinutes(1));
// decision here is to proceed even if we were not able to get mutex ownership
// and let the potential IO errors bubble up. Reasoning is that failure to get
// ownership probably means faulty hardware and in this case it's better to report
// back than hang
ioOperation();
}
finally
{
if (owner)
{
mutex.ReleaseMutex();
}
}
}
}
}
}

View File

@@ -1,68 +0,0 @@
using System;
using System.Linq;
using System.Net;
using NuGet.Resources;
namespace NuGet
{
public class SettingsCredentialProvider : ICredentialProvider
{
private readonly ICredentialProvider _credentialProvider;
private readonly IPackageSourceProvider _packageSourceProvider;
private readonly ILogger _logger;
public SettingsCredentialProvider(ICredentialProvider credentialProvider, IPackageSourceProvider packageSourceProvider)
: this(credentialProvider, packageSourceProvider, NullLogger.Instance)
{
}
public SettingsCredentialProvider(ICredentialProvider credentialProvider, IPackageSourceProvider packageSourceProvider, ILogger logger)
{
if (credentialProvider == null)
{
throw new ArgumentNullException("credentialProvider");
}
if (packageSourceProvider == null)
{
throw new ArgumentNullException("packageSourceProvider");
}
_credentialProvider = credentialProvider;
_packageSourceProvider = packageSourceProvider;
_logger = logger;
}
public ICredentials GetCredentials(Uri uri, IWebProxy proxy, CredentialType credentialType, bool retrying)
{
NetworkCredential credentials;
// If we are retrying, the stored credentials must be invalid.
if (!retrying && (credentialType == CredentialType.RequestCredentials) && TryGetCredentials(uri, out credentials))
{
_logger.Log(MessageLevel.Info, NuGetResources.SettingsCredentials_UsingSavedCredentials, credentials.UserName);
return credentials;
}
return _credentialProvider.GetCredentials(uri, proxy, credentialType, retrying);
}
private bool TryGetCredentials(Uri uri, out NetworkCredential configurationCredentials)
{
var source = _packageSourceProvider.LoadPackageSources().FirstOrDefault(p =>
{
Uri sourceUri;
return !String.IsNullOrEmpty(p.UserName)
&& !String.IsNullOrEmpty(p.Password)
&& Uri.TryCreate(p.Source, UriKind.Absolute, out sourceUri)
&& UriUtility.UriStartsWith(sourceUri, uri);
});
if (source == null)
{
// The source is not in the config file
configurationCredentials = null;
return false;
}
configurationCredentials = new NetworkCredential(source.UserName, source.Password);
return true;
}
}
}

View File

@@ -1,48 +0,0 @@
using System;
using System.Net;
namespace NuGet
{
internal static class CredentialProviderExtensions
{
private static readonly string[] _authenticationSchemes = new[] { "Basic", "NTLM", "Negotiate" };
internal static ICredentials GetCredentials(this ICredentialProvider provider, WebRequest request, CredentialType credentialType, bool retrying = false)
{
return provider.GetCredentials(request.RequestUri, request.Proxy, credentialType, retrying);
}
internal static ICredentials AsCredentialCache(this ICredentials credentials, Uri uri)
{
// No credentials then bail
if (credentials == null)
{
return null;
}
// Do nothing with default credentials
if (credentials == CredentialCache.DefaultCredentials ||
credentials == CredentialCache.DefaultNetworkCredentials)
{
return credentials;
}
// If this isn't a NetworkCredential then leave it alone
var networkCredentials = credentials as NetworkCredential;
if (networkCredentials == null)
{
return credentials;
}
// Set this up for each authentication scheme we support
// The reason we're using a credential cache is so that the HttpWebRequest will forward our
// credentials if there happened to be any redirects in the chain of requests.
var cache = new CredentialCache();
foreach (var scheme in _authenticationSchemes)
{
cache.Add(uri, scheme, networkCredentials);
}
return cache;
}
}
}

View File

@@ -1,114 +0,0 @@
using System;
namespace NuGet
{
public static class SettingsExtensions
{
private const string ConfigSection = "config";
public static string GetRepositoryPath(this ISettings settings)
{
string path = settings.GetValue(ConfigSection, "repositoryPath", isPath: true);
if (!String.IsNullOrEmpty(path))
{
path = path.Replace('/', System.IO.Path.DirectorySeparatorChar);
}
return path;
}
public static string GetDecryptedValue(this ISettings settings, string section, string key, bool isPath = false)
{
if (String.IsNullOrEmpty(section))
{
throw new ArgumentException(CommonResources.Argument_Cannot_Be_Null_Or_Empty, "section");
}
if (String.IsNullOrEmpty(key))
{
throw new ArgumentException(CommonResources.Argument_Cannot_Be_Null_Or_Empty, "key");
}
var encryptedString = settings.GetValue(section, key, isPath);
if (encryptedString == null)
{
return null;
}
if (String.IsNullOrEmpty(encryptedString))
{
return String.Empty;
}
return EncryptionUtility.DecryptString(encryptedString);
}
public static void SetEncryptedValue(this ISettings settings, string section, string key, string value)
{
if (String.IsNullOrEmpty(section))
{
throw new ArgumentException(CommonResources.Argument_Cannot_Be_Null_Or_Empty, "section");
}
if (String.IsNullOrEmpty(key))
{
throw new ArgumentException(CommonResources.Argument_Cannot_Be_Null_Or_Empty, "key");
}
if (value == null)
{
throw new ArgumentNullException("value");
}
if (String.IsNullOrEmpty(value))
{
settings.SetValue(section, key, String.Empty);
}
else
{
var encryptedString = EncryptionUtility.EncryptString(value);
settings.SetValue(section, key, encryptedString);
}
}
/// <summary>
/// Retrieves a config value for the specified key
/// </summary>
/// <param name="settings">The settings instance to retrieve </param>
/// <param name="key">The key to look up</param>
/// <param name="decrypt">Determines if the retrieved value needs to be decrypted.</param>
/// <param name="isPath">Determines if the retrieved value is returned as a path.</param>
/// <returns>Null if the key was not found, value from config otherwise.</returns>
public static string GetConfigValue(this ISettings settings, string key, bool decrypt = false, bool isPath = false)
{
return decrypt ?
settings.GetDecryptedValue(ConfigSection, key, isPath) :
settings.GetValue(ConfigSection, key, isPath);
}
/// <summary>
/// Sets a config value in the setting.
/// </summary>
/// <param name="settings">The settings instance to store the key-value in.</param>
/// <param name="key">The key to store.</param>
/// <param name="value">The value to store.</param>
/// <param name="encrypt">Determines if the value needs to be encrypted prior to storing.</param>
public static void SetConfigValue(this ISettings settings, string key, string value, bool encrypt = false)
{
if (encrypt == true)
{
settings.SetEncryptedValue(ConfigSection, key, value);
}
else
{
settings.SetValue(ConfigSection, key, value);
}
}
/// <summary>
/// Deletes a config value from settings
/// </summary>
/// <param name="settings">The settings instance to delete the key from.</param>
/// <param name="key">The key to delete.</param>
/// <returns>True if the value was deleted, false otherwise.</returns>
public static bool DeleteConfigValue(this ISettings settings, string key)
{
return settings.DeleteValue(ConfigSection, key);
}
}
}

View File

@@ -1,47 +0,0 @@
using System;
using System.Collections.Concurrent;
using System.Net;
namespace NuGet
{
internal class CredentialStore : ICredentialCache
{
private readonly ConcurrentDictionary<Uri, ICredentials> _credentialCache = new ConcurrentDictionary<Uri, ICredentials>();
private static readonly CredentialStore _instance = new CredentialStore();
public static CredentialStore Instance
{
get
{
return _instance;
}
}
public ICredentials GetCredentials(Uri uri)
{
Uri rootUri = GetRootUri(uri);
ICredentials credentials;
if (_credentialCache.TryGetValue(uri, out credentials) ||
_credentialCache.TryGetValue(rootUri, out credentials))
{
return credentials;
}
return null;
}
public void Add(Uri uri, ICredentials credentials)
{
Uri rootUri = GetRootUri(uri);
_credentialCache.TryAdd(uri, credentials);
_credentialCache.AddOrUpdate(rootUri, credentials, (u, c) => credentials);
}
internal static Uri GetRootUri(Uri uri)
{
return new Uri(uri.GetComponents(UriComponents.SchemeAndServer, UriFormat.SafeUnescaped));
}
}
}

View File

@@ -1,8 +0,0 @@
namespace NuGet
{
public enum CredentialType
{
ProxyCredentials,
RequestCredentials
}
}

View File

@@ -1,205 +0,0 @@
using System;
using System.IO;
using System.Net;
namespace NuGet
{
public class HttpClient : IHttpClient
{
public event EventHandler<ProgressEventArgs> ProgressAvailable = delegate { };
public event EventHandler<WebRequestEventArgs> SendingRequest = delegate { };
private static ICredentialProvider _credentialProvider;
private Uri _uri;
public HttpClient(Uri uri)
{
if (uri == null)
{
throw new ArgumentNullException("uri");
}
_uri = uri;
}
public string UserAgent
{
get;
set;
}
public virtual Uri Uri
{
get
{
return _uri;
}
set
{
_uri = value;
}
}
public virtual Uri OriginalUri
{
get { return _uri; }
}
public string Method
{
get;
set;
}
public string ContentType
{
get;
set;
}
public bool AcceptCompression
{
get;
set;
}
public bool DisableBuffering
{
get;
set;
}
// TODO: Get rid of this. Horrid to have static properties like this especially in a code path that does not look thread safe.
public static ICredentialProvider DefaultCredentialProvider
{
get
{
return _credentialProvider ?? NullCredentialProvider.Instance;
}
set
{
_credentialProvider = value;
}
}
public virtual WebResponse GetResponse()
{
Func<WebRequest> webRequestFactory = () =>
{
WebRequest request = WebRequest.Create(Uri);
InitializeRequestProperties(request);
return request;
};
var requestHelper = new RequestHelper(
webRequestFactory,
RaiseSendingRequest,
ProxyCache.Instance,
CredentialStore.Instance,
DefaultCredentialProvider,
DisableBuffering);
return requestHelper.GetResponse();
}
public void InitializeRequest(WebRequest request)
{
// TODO: Clean this up. This is no longer used with the move to WCF 5.6.1, changes to the request are not applied to the actual request.
// Setup the request properties like content type and compression
InitializeRequestProperties(request);
// Use credentials from the cache if any for this uri
TrySetCredentialsAndProxy(request);
// Give clients a chance to examine/modify the request object before the request actually goes out.
RaiseSendingRequest(request);
}
private void TrySetCredentialsAndProxy(WebRequest request)
{
// Used the cached credentials and proxy we have
request.Credentials = CredentialStore.Instance.GetCredentials(Uri);
request.Proxy = ProxyCache.Instance.GetProxy(Uri);
STSAuthHelper.PrepareSTSRequest(request);
}
private void InitializeRequestProperties(WebRequest request)
{
var httpRequest = request as HttpWebRequest;
if (httpRequest != null)
{
httpRequest.UserAgent = UserAgent ?? HttpUtility.CreateUserAgentString("NuGet");
httpRequest.CookieContainer = new CookieContainer();
if (AcceptCompression)
{
httpRequest.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip;
}
}
if (!String.IsNullOrEmpty(ContentType))
{
request.ContentType = ContentType;
}
if (!String.IsNullOrEmpty(Method))
{
request.Method = Method;
}
}
public void DownloadData(Stream targetStream)
{
const int ChunkSize = 1024 * 4; // 4KB
using (var response = GetResponse())
{
// Total response length
int length = (int)response.ContentLength;
using (Stream stream = response.GetResponseStream())
{
// in some circumstances, the Content-Length response header is missing, resulting in
// the ContentLength = -1. In which case, we copy the whole stream and do not report progress.
if (length < 0)
{
stream.CopyTo(targetStream);
// reporting fake progress as 100%
OnProgressAvailable(100);
}
else
{
// We read the response stream chunk by chunk (each chunk is 4KB).
// After reading each chunk, we report the progress based on the total number bytes read so far.
int totalReadSoFar = 0;
byte[] buffer = new byte[ChunkSize];
while (totalReadSoFar < length)
{
int bytesRead = stream.Read(buffer, 0, Math.Min(length - totalReadSoFar, ChunkSize));
if (bytesRead == 0)
{
break;
}
else
{
targetStream.Write(buffer, 0, bytesRead);
totalReadSoFar += bytesRead;
OnProgressAvailable((totalReadSoFar * 100) / length);
}
}
}
}
}
}
private void OnProgressAvailable(int percentage)
{
ProgressAvailable(this, new ProgressEventArgs(percentage));
}
private void RaiseSendingRequest(WebRequest webRequest)
{
SendingRequest(this, new WebRequestEventArgs(webRequest));
}
}
}

View File

@@ -1,80 +0,0 @@
using System;
using System.Globalization;
using System.Net;
namespace NuGet
{
public static class HttpUtility
{
private const string UserAgentTemplate = "{0}/{1} ({2})";
private const string UserAgentWithHostTemplate = "{0}/{1} ({2}, {3})";
private const string ProjectGuidsHeader = "NuGet-ProjectGuids";
public static string CreateUserAgentString(string client)
{
if (client == null)
{
throw new ArgumentNullException("client");
}
var version = typeof(HttpUtility).Assembly.GetName().Version;
return String.Format(CultureInfo.InvariantCulture, UserAgentTemplate, client, version, Environment.OSVersion);
}
public static string CreateUserAgentString(string client, string host)
{
if (client == null)
{
throw new ArgumentNullException("client");
}
if (host == null)
{
throw new ArgumentNullException("host");
}
var version = typeof(HttpUtility).Assembly.GetName().Version;
return String.Format(
CultureInfo.InvariantCulture,
UserAgentWithHostTemplate,
client,
version /* NuGetnuget version */,
Environment.OSVersion /* OS version */,
host /* VS SKU + version */);
}
public static void SetUserAgent(WebRequest request, string userAgent, string projectGuids = null)
{
if (request == null)
{
throw new ArgumentNullException("request");
}
if (userAgent == null)
{
throw new ArgumentNullException("userAgent");
}
var httpRequest = request as HttpWebRequest;
if (httpRequest != null)
{
httpRequest.UserAgent = userAgent;
}
else
{
request.Headers[HttpRequestHeader.UserAgent] = userAgent;
}
if (!String.IsNullOrEmpty(projectGuids))
{
request.Headers[ProjectGuidsHeader] = projectGuids;
}
else
{
// this Request instance may be reused from the previous request.
// thus we clear the header to avoid sending project types of the previous request, if any
request.Headers.Remove(ProjectGuidsHeader);
}
}
}
}

View File

@@ -1,11 +0,0 @@
using System;
using System.Net;
namespace NuGet
{
public interface ICredentialCache
{
void Add(Uri uri, ICredentials credentials);
ICredentials GetCredentials(Uri uri);
}
}

View File

@@ -1,21 +0,0 @@
using System;
using System.Net;
namespace NuGet
{
/// <summary>
/// This interface represents the basic interface that one needs to implement in order to
/// support repository authentication.
/// </summary>
public interface ICredentialProvider
{
/// <summary>
/// Returns CredentialState state that let's the consumer know if ICredentials
/// were discovered by the ICredentialProvider. The credentials argument is then
/// populated with the discovered valid credentials that can be used for the given Uri.
/// The proxy instance if passed will be used to ensure that the request goes through the proxy
/// to ensure successful connection to the destination Uri.
/// </summary>
ICredentials GetCredentials(Uri uri, IWebProxy proxy, CredentialType credentialType, bool retrying);
}
}

View File

@@ -1,37 +0,0 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Net;
namespace NuGet
{
public interface IHttpClient : IHttpClientEvents
{
string UserAgent
{
get;
set;
}
Uri Uri
{
get;
}
Uri OriginalUri
{
get;
}
bool AcceptCompression
{
get;
set;
}
[SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification = "This is expensive")]
WebResponse GetResponse();
void InitializeRequest(WebRequest request);
void DownloadData(Stream targetStream);
}
}

View File

@@ -1,9 +0,0 @@
using System;
namespace NuGet
{
public interface IHttpClientEvents : IProgressProvider
{
event EventHandler<WebRequestEventArgs> SendingRequest;
}
}

View File

@@ -1,15 +0,0 @@
using System;
using System.Collections.Specialized;
using System.Net;
namespace NuGet
{
// For unit testing
public interface IHttpWebResponse : IDisposable
{
HttpStatusCode StatusCode { get; }
Uri ResponseUri { get; }
string AuthType { get; }
NameValueCollection Headers { get; }
}
}

View File

@@ -1,11 +0,0 @@
using System;
using System.Net;
namespace NuGet
{
public interface IProxyCache
{
void Add(IWebProxy proxy);
IWebProxy GetProxy(Uri uri);
}
}

View File

@@ -1,124 +0,0 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Net;
using System.Text;
namespace NuGet
{
/// <remarks>
/// Based on the blog post by Travis Illig at http://www.paraesthesia.com/archive/2009/12/16/posting-multipartform-data-using-.net-webrequest.aspx
/// </remarks>
public class MultipartWebRequest
{
private const string FormDataTemplate = "--{0}\r\nContent-Disposition: form-data; name=\"{1}\"\r\n\r\n{2}\r\n";
private const string FileTemplate = "--{0}\r\nContent-Disposition: form-data; name=\"{1}\"; filename=\"{2}\"\r\nContent-Type: {3}\r\n\r\n";
private readonly Dictionary<string, string> _formData;
private readonly List<PostFileData> _files;
public MultipartWebRequest()
: this(new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase))
{
}
public MultipartWebRequest(Dictionary<string, string> formData)
{
_formData = formData;
_files = new List<PostFileData>();
}
public void AddFormData(string key, string value)
{
_formData.Add(key, value);
}
public void AddFile(Func<Stream> fileFactory, string fieldName, long length, string contentType = "application/octet-stream")
{
_files.Add(new PostFileData
{
FileFactory = fileFactory,
FieldName = fieldName,
ContentType = contentType,
ContentLength = length
});
}
public void CreateMultipartRequest(WebRequest request)
{
string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x", CultureInfo.InvariantCulture);
request.ContentType = "multipart/form-data; boundary=" + boundary;
request.ContentLength = CalculateContentLength(boundary);
using (Stream stream = request.GetRequestStream())
{
foreach (var item in _formData)
{
string header = String.Format(CultureInfo.InvariantCulture, FormDataTemplate, boundary, item.Key, item.Value);
byte[] headerBytes = Encoding.UTF8.GetBytes(header);
stream.Write(headerBytes, 0, headerBytes.Length);
}
byte[] newlineBytes = Encoding.UTF8.GetBytes(Environment.NewLine);
foreach (var file in _files)
{
string header = String.Format(CultureInfo.InvariantCulture, FileTemplate, boundary, file.FieldName, file.FieldName, file.ContentType);
byte[] headerBytes = Encoding.UTF8.GetBytes(header);
stream.Write(headerBytes, 0, headerBytes.Length);
Stream fileStream = file.FileFactory();
fileStream.CopyTo(stream, bufferSize: 4 * 1024);
fileStream.Close();
stream.Write(newlineBytes, 0, newlineBytes.Length);
}
string trailer = String.Format(CultureInfo.InvariantCulture, "--{0}--", boundary);
byte[] trailerBytes = Encoding.UTF8.GetBytes(trailer);
stream.Write(trailerBytes, 0, trailerBytes.Length);
}
}
private long CalculateContentLength(string boundary)
{
long totalContentLength = 0;
foreach (var item in _formData)
{
string header = String.Format(CultureInfo.InvariantCulture, FormDataTemplate, boundary, item.Key, item.Value);
byte[] headerBytes = Encoding.UTF8.GetBytes(header);
totalContentLength += headerBytes.Length;
}
byte[] newlineBytes = Encoding.UTF8.GetBytes(Environment.NewLine);
foreach (var file in _files)
{
string header = String.Format(CultureInfo.InvariantCulture, FileTemplate, boundary, file.FieldName, file.FieldName, file.ContentType);
byte[] headerBytes = Encoding.UTF8.GetBytes(header);
totalContentLength += headerBytes.Length;
totalContentLength += file.ContentLength;
totalContentLength += newlineBytes.Length;
}
string trailer = String.Format(CultureInfo.InvariantCulture, "--{0}--", boundary);
byte[] trailerBytes = Encoding.UTF8.GetBytes(trailer);
totalContentLength += trailerBytes.Length;
return totalContentLength;
}
private sealed class PostFileData
{
public Func<Stream> FileFactory { get; set; }
public string ContentType { get; set; }
public string FieldName { get; set; }
public long ContentLength { get; set; }
}
}
}

View File

@@ -1,28 +0,0 @@
using System;
using System.Net;
namespace NuGet
{
public class NullCredentialProvider : ICredentialProvider
{
private static readonly NullCredentialProvider _instance = new NullCredentialProvider();
public static ICredentialProvider Instance
{
get
{
return _instance;
}
}
private NullCredentialProvider()
{
}
public ICredentials GetCredentials(Uri uri, IWebProxy proxy, CredentialType credentialType, bool retrying)
{
return null;
}
}
}

View File

@@ -1,183 +0,0 @@
using System;
using System.Collections.Concurrent;
using System.Net;
namespace NuGet
{
internal class ProxyCache : IProxyCache
{
private const string HostKey = "http_proxy";
private const string UserKey = "http_proxy.user";
private const string PasswordKey = "http_proxy.password";
/// <summary>
/// Capture the default System Proxy so that it can be re-used by the IProxyFinder
/// because we can't rely on WebRequest.DefaultWebProxy since someone can modify the DefaultWebProxy
/// property and we can't tell if it was modified and if we are still using System Proxy Settings or not.
/// One limitation of this method is that it does not look at the config file to get the defined proxy
/// settings.
/// </summary>
private static readonly IWebProxy _originalSystemProxy = WebRequest.GetSystemWebProxy();
private readonly ConcurrentDictionary<Uri, WebProxy> _cache = new ConcurrentDictionary<Uri, WebProxy>();
#if BOOTSTRAPPER
// Temporarily commenting these out until we can figure out a nicer way of doing this in the bootstrapper.
private static readonly Lazy<ProxyCache> _instance = new Lazy<ProxyCache>(() => new ProxyCache());
public ProxyCache()
{
}
#else
// It's not likely that http proxy settings are set in machine wide settings,
// so not passing machine wide settings to Settings.LoadDefaultSettings() should be fine.
private static readonly Lazy<ProxyCache> _instance = new Lazy<ProxyCache>(() => new ProxyCache(Settings.LoadDefaultSettings(fileSystem: null, configFileName: null, machineWideSettings: null ), new EnvironmentVariableWrapper()));
private readonly ISettings _settings;
private readonly IEnvironmentVariableReader _environment;
public ProxyCache(ISettings settings, IEnvironmentVariableReader environment)
{
_settings = settings;
_environment = environment;
}
#endif
internal static ProxyCache Instance
{
get
{
return _instance.Value;
}
}
public IWebProxy GetProxy(Uri uri)
{
#if !BOOTSTRAPPER
// Check if the user has configured proxy details in settings or in the environment.
WebProxy configuredProxy = GetUserConfiguredProxy();
if (configuredProxy != null)
{
// If a proxy was cached, it means the stored credentials are incorrect. Use the cached one in this case.
WebProxy actualProxy;
if (_cache.TryGetValue(configuredProxy.Address, out actualProxy))
{
return actualProxy;
}
return configuredProxy;
}
#endif
if (!IsSystemProxySet(uri))
{
return null;
}
WebProxy systemProxy = GetSystemProxy(uri);
WebProxy effectiveProxy;
// See if we have a proxy instance cached for this proxy address
if (_cache.TryGetValue(systemProxy.Address, out effectiveProxy))
{
return effectiveProxy;
}
return systemProxy;
}
#if !BOOTSTRAPPER
internal WebProxy GetUserConfiguredProxy()
{
// Try reading from the settings. The values are stored as 3 config values http_proxy, http_proxy_user, http_proxy_password
var host = _settings.GetConfigValue(HostKey);
if (!String.IsNullOrEmpty(host))
{
// The host is the minimal value we need to assume a user configured proxy.
var webProxy = new WebProxy(host);
string userName = _settings.GetConfigValue(UserKey);
string password = _settings.GetConfigValue(PasswordKey, decrypt: true);
if (!String.IsNullOrEmpty(userName) && !String.IsNullOrEmpty(password))
{
webProxy.Credentials = new NetworkCredential(userName, password);
}
return webProxy;
}
// Next try reading from the environment variable http_proxy. This would be specified as http://<username>:<password>@proxy.com
host = _environment.GetEnvironmentVariable(HostKey);
Uri uri;
if (!String.IsNullOrEmpty(host) && Uri.TryCreate(host, UriKind.Absolute, out uri))
{
var webProxy = new WebProxy(uri.GetComponents(UriComponents.HttpRequestUrl, UriFormat.SafeUnescaped));
if (!String.IsNullOrEmpty(uri.UserInfo))
{
var credentials = uri.UserInfo.Split(':');
if (credentials.Length > 1)
{
webProxy.Credentials = new NetworkCredential(userName: credentials[0], password: credentials[1]);
}
}
return webProxy;
}
return null;
}
#endif
public void Add(IWebProxy proxy)
{
var webProxy = proxy as WebProxy;
if (webProxy != null)
{
_cache.TryAdd(webProxy.Address, webProxy);
}
}
private static WebProxy GetSystemProxy(Uri uri)
{
// WebRequest.DefaultWebProxy seems to be more capable in terms of getting the default
// proxy settings instead of the WebRequest.GetSystemProxy()
var proxyUri = _originalSystemProxy.GetProxy(uri);
return new WebProxy(proxyUri);
}
/// <summary>
/// Return true or false if connecting through a proxy server
/// </summary>
/// <param name="uri"></param>
/// <returns></returns>
private static bool IsSystemProxySet(Uri uri)
{
// The reason for not calling the GetSystemProxy is because the object
// that will be returned is no longer going to be the proxy that is set by the settings
// on the users machine only the Address is going to be the same.
// Not sure why the .NET team did not want to expose all of the useful settings like
// ByPass list and other settings that we can't get because of it.
// Anyway the reason why we need the DefaultWebProxy is to see if the uri that we are
// getting the proxy for to should be bypassed or not. If it should be bypassed then
// return that we don't need a proxy and we should try to connect directly.
IWebProxy proxy = WebRequest.DefaultWebProxy;
if (proxy != null)
{
Uri proxyUri = proxy.GetProxy(uri);
if (proxyUri != null)
{
Uri proxyAddress = new Uri(proxyUri.AbsoluteUri);
if (String.Equals(proxyAddress.AbsoluteUri, uri.AbsoluteUri))
{
return false;
}
bool bypassUri = proxy.IsBypassed(uri);
if (bypassUri)
{
return false;
}
proxy = new WebProxy(proxyAddress);
}
}
return proxy != null;
}
}
}

View File

@@ -1,104 +0,0 @@
using System;
using System.Globalization;
using System.Net;
using NuGet.Resources;
namespace NuGet
{
/// <summary>
/// This class should be used when ever you are using a link that is actually
/// redirecting to the destination link that you want to use as the data source.
/// A good example of that is a link that forwards like the current nuget link
/// that is configured as a default location for nuget packages.
/// </summary>
public class RedirectedHttpClient : HttpClient
{
private const string RedirectedClientCacheKey = "RedirectedHttpClient|";
private readonly Uri _originalUri;
private readonly MemoryCache _memoryCache;
public RedirectedHttpClient(Uri uri)
: this(uri, MemoryCache.Instance)
{
}
public RedirectedHttpClient(Uri uri, MemoryCache memoryCache)
: base(uri)
{
_originalUri = uri;
_memoryCache = memoryCache;
}
public override WebResponse GetResponse()
{
return CachedClient.GetResponse();
}
public override Uri Uri
{
get
{
return CachedClient.Uri;
}
}
public override Uri OriginalUri
{
get
{
return _originalUri;
}
}
internal IHttpClient CachedClient
{
get
{
string cacheKey = GetCacheKey();
// Reset the IHttpClient instance if we catch an Exception so that
// subsequent requests are able to try and create it again in case there
// was some issue with authentication or some other request related configuration
// If we don't do it here then the exception is always thrown as soon as we
// try to access the cached value property since it's backed up by Lazy<T>.
try
{
return _memoryCache.GetOrAdd(cacheKey, EnsureClient, TimeSpan.FromHours(1));
}
catch (Exception)
{
// Re-initialize the cache and throw the exception so that we can
// see what happened.
_memoryCache.Remove(cacheKey);
throw;
}
}
}
private string GetCacheKey()
{
return RedirectedClientCacheKey + _originalUri.OriginalString;
}
protected internal virtual IHttpClient EnsureClient()
{
var originalClient = new HttpClient(_originalUri);
return new HttpClient(GetResponseUri(originalClient));
}
private Uri GetResponseUri(HttpClient client)
{
using (WebResponse response = client.GetResponse())
{
if (response == null)
{
throw new InvalidOperationException(
String.Format(CultureInfo.CurrentCulture,
NuGetResources.UnableToResolveUri,
Uri));
}
return response.ResponseUri;
}
}
}
}

View File

@@ -1,20 +0,0 @@
namespace NuGet
{
/// <summary>
/// Set of known context values to be used in calls to HttpUtility.CreateUserAgentString
/// </summary>
public static class RepositoryOperationNames
{
public static readonly string OperationHeaderName = "NuGet-Operation";
public static readonly string DependentPackageHeaderName = "NuGet-DependentPackage";
public static readonly string DependentPackageVersionHeaderName = "NuGet-DependentPackageVersion";
public static readonly string PackageId = "NuGet-PackageId";
public static readonly string PackageVersion = "NuGet-PackageVersion";
public static readonly string Update = "Update";
public static readonly string Install = "Install";
public static readonly string Restore = "Restore";
public static readonly string Mirror = "Mirror";
public static readonly string Reinstall = "Reinstall";
}
}

View File

@@ -1,351 +0,0 @@
using System;
using System.Collections.Specialized;
using System.Net;
namespace NuGet
{
/// <summary>
/// This class is used to keep sending requests until a response code that doesn't require
/// authentication happens or if the request requires authentication and
/// the user has stopped trying to enter them (i.e. they hit cancel when they are prompted).
/// </summary>
internal class RequestHelper
{
private Func<WebRequest> _createRequest;
private Action<WebRequest> _prepareRequest;
private IProxyCache _proxyCache;
private ICredentialCache _credentialCache;
private ICredentialProvider _credentialProvider;
HttpWebRequest _previousRequest;
IHttpWebResponse _previousResponse;
HttpStatusCode? _previousStatusCode;
int _credentialsRetryCount;
bool _usingSTSAuth;
bool _continueIfFailed;
int _proxyCredentialsRetryCount;
bool _basicAuthIsUsedInPreviousRequest;
bool _disableBuffering;
public RequestHelper(Func<WebRequest> createRequest,
Action<WebRequest> prepareRequest,
IProxyCache proxyCache,
ICredentialCache credentialCache,
ICredentialProvider credentialProvider,
bool disableBuffering)
{
_createRequest = createRequest;
_prepareRequest = prepareRequest;
_proxyCache = proxyCache;
_credentialCache = credentialCache;
_credentialProvider = credentialProvider;
_disableBuffering = disableBuffering;
}
public WebResponse GetResponse()
{
_previousRequest = null;
_previousResponse = null;
_previousStatusCode = null;
_usingSTSAuth = false;
_continueIfFailed = true;
_proxyCredentialsRetryCount = 0;
_credentialsRetryCount = 0;
int failureCount = 0;
const int MaxFailureCount = 10;
while (true)
{
// Create the request
var request = (HttpWebRequest)_createRequest();
ConfigureRequest(request);
try
{
if (_disableBuffering)
{
request.AllowWriteStreamBuffering = false;
// When buffering is disabled, we need to add the Authorization header
// for basic authentication by ourselves.
bool basicAuth = _previousResponse != null &&
_previousResponse.AuthType != null &&
_previousResponse.AuthType.IndexOf("Basic", StringComparison.OrdinalIgnoreCase) != -1;
var networkCredentials = request.Credentials.GetCredential(request.RequestUri, "Basic");
if (networkCredentials != null && basicAuth)
{
string authInfo = networkCredentials.UserName + ":" + networkCredentials.Password;
authInfo = Convert.ToBase64String(System.Text.Encoding.Default.GetBytes(authInfo));
request.Headers["Authorization"] = "Basic " + authInfo;
_basicAuthIsUsedInPreviousRequest = true;
}
}
// Prepare the request, we do something like write to the request stream
// which needs to happen last before the request goes out
_prepareRequest(request);
// Shim and replace this request if needed for v3
WebResponse response = HttpShim.Instance.ShimWebRequest(request);
// Cache the proxy and credentials
_proxyCache.Add(request.Proxy);
ICredentials credentials = request.Credentials;
_credentialCache.Add(request.RequestUri, credentials);
_credentialCache.Add(response.ResponseUri, credentials);
return response;
}
catch (WebException ex)
{
++failureCount;
if (failureCount >= MaxFailureCount)
{
throw;
}
using (IHttpWebResponse response = GetResponse(ex.Response))
{
if (response == null &&
ex.Status != WebExceptionStatus.SecureChannelFailure)
{
// No response, something went wrong so just rethrow
throw;
}
// Special case https connections that might require authentication
if (ex.Status == WebExceptionStatus.SecureChannelFailure)
{
if (_continueIfFailed)
{
// Act like we got a 401 so that we prompt for credentials on the next request
_previousStatusCode = HttpStatusCode.Unauthorized;
continue;
}
throw;
}
// If we were trying to authenticate the proxy or the request and succeeded, cache the result.
if (_previousStatusCode == HttpStatusCode.ProxyAuthenticationRequired &&
response.StatusCode != HttpStatusCode.ProxyAuthenticationRequired)
{
_proxyCache.Add(request.Proxy);
}
else if (_previousStatusCode == HttpStatusCode.Unauthorized &&
response.StatusCode != HttpStatusCode.Unauthorized)
{
_credentialCache.Add(request.RequestUri, request.Credentials);
_credentialCache.Add(response.ResponseUri, request.Credentials);
}
_usingSTSAuth = STSAuthHelper.TryRetrieveSTSToken(request.RequestUri, response);
if (!IsAuthenticationResponse(response) || !_continueIfFailed)
{
throw;
}
if (!EnvironmentUtility.IsNet45Installed &&
request.AllowWriteStreamBuffering == false &&
response.AuthType != null &&
IsNtlmOrKerberos(response.AuthType))
{
// integrated windows authentication does not work when buffering is
// disabled on .net 4.0.
throw;
}
_previousRequest = request;
_previousResponse = response;
_previousStatusCode = _previousResponse.StatusCode;
}
}
}
}
private void ConfigureRequest(HttpWebRequest request)
{
request.Proxy = _proxyCache.GetProxy(request.RequestUri);
if (request.Proxy != null && request.Proxy.Credentials == null)
{
request.Proxy.Credentials = CredentialCache.DefaultCredentials;
}
if (_previousResponse == null || ShouldKeepAliveBeUsedInRequest(_previousRequest, _previousResponse))
{
// Try to use the cached credentials (if any, for the first request)
request.Credentials = _credentialCache.GetCredentials(request.RequestUri);
// If there are no cached credentials, use the default ones
if (request.Credentials == null)
{
request.UseDefaultCredentials = true;
}
}
else if (_previousStatusCode == HttpStatusCode.ProxyAuthenticationRequired)
{
request.Proxy.Credentials = _credentialProvider.GetCredentials(
request, CredentialType.ProxyCredentials, retrying: _proxyCredentialsRetryCount > 0);
_continueIfFailed = request.Proxy.Credentials != null;
_proxyCredentialsRetryCount++;
}
else if (_previousStatusCode == HttpStatusCode.Unauthorized)
{
SetCredentialsOnAuthorizationError(request);
}
SetKeepAliveHeaders(request, _previousResponse);
if (_usingSTSAuth)
{
// Add request headers if the server requires STS based auth.
STSAuthHelper.PrepareSTSRequest(request);
}
// Wrap the credentials in a CredentialCache in case there is a redirect
// and credentials need to be kept around.
request.Credentials = request.Credentials.AsCredentialCache(request.RequestUri);
}
private void SetCredentialsOnAuthorizationError(HttpWebRequest request)
{
if (_usingSTSAuth)
{
// If we are using STS, the auth's being performed by a request header.
// We do not need to ask the user for credentials at this point.
return;
}
// When buffering is disabled, we need to handle basic auth ourselves.
bool basicAuth = _previousResponse.AuthType != null &&
_previousResponse.AuthType.IndexOf("Basic", StringComparison.OrdinalIgnoreCase) != -1;
if (_disableBuffering && basicAuth && !_basicAuthIsUsedInPreviousRequest)
{
// The basic auth credentials were not sent in the last request.
// We need to try with cached credentials in this request.
request.Credentials = _credentialCache.GetCredentials(request.RequestUri);
}
if (request.Credentials == null)
{
request.Credentials = _credentialProvider.GetCredentials(
request, CredentialType.RequestCredentials, retrying: _credentialsRetryCount > 0);
}
_continueIfFailed = request.Credentials != null;
_credentialsRetryCount++;
}
private static IHttpWebResponse GetResponse(WebResponse response)
{
var httpWebResponse = response as IHttpWebResponse;
if (httpWebResponse == null)
{
var webResponse = response as HttpWebResponse;
if (webResponse == null)
{
return null;
}
return new HttpWebResponseWrapper(webResponse);
}
return httpWebResponse;
}
private static bool IsAuthenticationResponse(IHttpWebResponse response)
{
return response.StatusCode == HttpStatusCode.Unauthorized ||
response.StatusCode == HttpStatusCode.ProxyAuthenticationRequired;
}
private static void SetKeepAliveHeaders(HttpWebRequest request, IHttpWebResponse previousResponse)
{
// KeepAlive is required for NTLM and Kerberos authentication. If we've never been authenticated or are using a different auth, we
// should not require KeepAlive.
// REVIEW: The WWW-Authenticate header is tricky to parse so a Equals might not be correct.
if (previousResponse == null ||
!IsNtlmOrKerberos(previousResponse.AuthType))
{
// This is to work around the "The underlying connection was closed: An unexpected error occurred on a receive."
// exception.
request.KeepAlive = false;
request.ProtocolVersion = HttpVersion.Version10;
}
}
private static bool ShouldKeepAliveBeUsedInRequest(HttpWebRequest request, IHttpWebResponse response)
{
if (request == null)
{
throw new ArgumentNullException("request");
}
if (response == null)
{
throw new ArgumentNullException("response");
}
return !request.KeepAlive && IsNtlmOrKerberos(response.AuthType);
}
private static bool IsNtlmOrKerberos(string authType)
{
if (String.IsNullOrEmpty(authType))
{
return false;
}
return authType.IndexOf("NTLM", StringComparison.OrdinalIgnoreCase) != -1
|| authType.IndexOf("Kerberos", StringComparison.OrdinalIgnoreCase) != -1;
}
private class HttpWebResponseWrapper : IHttpWebResponse
{
private readonly HttpWebResponse _response;
public HttpWebResponseWrapper(HttpWebResponse response)
{
_response = response;
}
public string AuthType
{
get
{
return _response.Headers[HttpResponseHeader.WwwAuthenticate];
}
}
public HttpStatusCode StatusCode
{
get
{
return _response.StatusCode;
}
}
public Uri ResponseUri
{
get
{
return _response.ResponseUri;
}
}
public NameValueCollection Headers
{
get
{
return _response.Headers;
}
}
public void Dispose()
{
if (_response != null)
{
_response.Close();
}
}
}
}
}

View File

@@ -1,131 +0,0 @@
using System;
using System.Globalization;
using System.Net;
using System.ServiceModel;
using System.ServiceModel.Security;
using System.Text;
using NuGet.Resources;
namespace NuGet
{
public static class STSAuthHelper
{
/// <summary>
/// Response header that specifies the WSTrust13 Windows Transport endpoint.
/// </summary>
/// <remarks>
/// TODO: Is there a way to discover this \ negotiate this endpoint?
/// </remarks>
private const string STSEndPointHeader = "X-NuGet-STS-EndPoint";
/// <summary>
/// Response header that specifies the realm to authenticate for. In most cases this would be the gallery we are going up against.
/// </summary>
private const string STSRealmHeader = "X-NuGet-STS-Realm";
/// <summary>
/// Request header that contains the SAML token.
/// </summary>
private const string STSTokenHeader = "X-NuGet-STS-Token";
/// <summary>
/// Adds the SAML token as a header to the request if it is already cached for this host.
/// </summary>
public static void PrepareSTSRequest(WebRequest request)
{
string cacheKey = GetCacheKey(request.RequestUri);
string token;
if (MemoryCache.Instance.TryGetValue(cacheKey, out token))
{
request.Headers[STSTokenHeader] = EncodeHeader(token);
}
}
/// <summary>
/// Attempts to retrieve a SAML token if the response indicates that server requires STS-based auth.
/// </summary>
/// <param name="requestUri">The feed URI we were connecting to.</param>
/// <param name="response">The 401 response we receieved from the server.</param>
/// <returns>True if we were able to successfully retrieve a SAML token from the STS specified in the response headers.</returns>
public static bool TryRetrieveSTSToken(Uri requestUri, IHttpWebResponse response)
{
if (response.StatusCode != HttpStatusCode.Unauthorized)
{
// We only care to do STS auth if the server returned a 401
return false;
}
string endPoint = GetSTSEndPoint(response);
string realm = response.Headers[STSRealmHeader];
if (String.IsNullOrEmpty(endPoint) || String.IsNullOrEmpty(realm))
{
// The server does not conform to our STS-auth requirements.
return false;
}
string cacheKey = GetCacheKey(requestUri);
// TODO: We need to figure out a way to cache the token for the duration of the token's validity (which is available as part of it's result).
MemoryCache.Instance.GetOrAdd(cacheKey,
() => GetSTSToken(requestUri, endPoint, realm),
TimeSpan.FromMinutes(30),
absoluteExpiration: true);
return true;
}
private static string GetSTSToken(Uri requestUri, string endPoint, string appliesTo)
{
var typeProvider = WIFTypeProvider.GetWIFTypes();
if (typeProvider == null)
{
throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, NuGetResources.UnableToLocateWIF, requestUri));
}
var binding = new WS2007HttpBinding(SecurityMode.Transport);
dynamic factory = Activator.CreateInstance(typeProvider.ChannelFactory, binding, endPoint);
factory.TrustVersion = TrustVersion.WSTrust13;
// Check if we can create 4.5 types.
dynamic rst = Activator.CreateInstance(typeProvider.RequestSecurityToken);
rst.RequestType = GetFieldValue<string>(typeProvider.RequestTypes, "Issue");
rst.KeyType = GetFieldValue<string>(typeProvider.KeyTypes, "Bearer");
// Dynamic verifies the type of the instance so we cannot use it to assign a value for this property.
var endPointAddress = Activator.CreateInstance(typeProvider.EndPoint, appliesTo);
SetProperty(rst, "AppliesTo", endPointAddress);
dynamic channel = factory.CreateChannel();
dynamic securityToken = channel.Issue(rst);
return securityToken.TokenXml.OuterXml;
}
private static void SetProperty(object instance, string propertyName, object value)
{
var type = instance.GetType();
var property = type.GetProperty(propertyName);
var propertySetter = property.GetSetMethod();
propertySetter.Invoke(instance, new[] { value });
}
private static TVal GetFieldValue<TVal>(Type type, string fieldName)
{
return (TVal)type.GetField(fieldName).GetValue(obj: null);
}
private static string GetSTSEndPoint(IHttpWebResponse response)
{
return response.Headers[STSEndPointHeader].SafeTrim();
}
private static string GetCacheKey(Uri requestUri)
{
return STSTokenHeader + "|" + requestUri.GetComponents(UriComponents.SchemeAndServer, UriFormat.SafeUnescaped);
}
private static string EncodeHeader(string token)
{
return Convert.ToBase64String(Encoding.UTF8.GetBytes(token));
}
}
}

View File

@@ -1,152 +0,0 @@
using System;
using System.Collections.Generic;
using System.Data.Services.Client;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
namespace NuGet
{
/// <summary>
/// HttpShim is a singleton that provides an event OnWebRequest for modifying WebRequests before they
/// are executed.
/// </summary>
public sealed class HttpShim
{
private static HttpShim _instance;
private Func<DataServiceClientRequestMessageArgs, DataServiceClientRequestMessage> _dataServiceHandler;
private Func<WebRequest, WebResponse> _webHandler;
internal HttpShim()
{
}
/// <summary>
/// Static instance of the shim.
/// </summary>
public static HttpShim Instance
{
get
{
if (_instance == null)
{
_instance = new HttpShim();
}
return _instance;
}
}
internal WebResponse ShimWebRequest(WebRequest request)
{
WebResponse response = null;
InitializeRequest(request);
if (_webHandler != null)
{
response = _webHandler(request);
}
else
{
response = request.GetResponse();
}
return response;
}
internal DataServiceClientRequestMessage ShimDataServiceRequest(DataServiceClientRequestMessageArgs args)
{
DataServiceClientRequestMessage message = null;
if (_dataServiceHandler != null)
{
message = _dataServiceHandler(args);
}
else
{
message = new HttpWebRequestMessage(args);
}
// apply proxy and credential settings on the core web request
InitializeMessage(message);
return message;
}
public void SetWebRequestHandler(Func<WebRequest, WebResponse> handler)
{
_webHandler = handler;
}
public void SetDataServiceRequestHandler(Func<DataServiceClientRequestMessageArgs, DataServiceClientRequestMessage> handler)
{
_dataServiceHandler = handler;
}
public void ClearHandlers()
{
_dataServiceHandler = null;
_webHandler = null;
}
// apply proxy settings and credentials here since they can no longer be applied from the context event
private static void InitializeMessage(DataServiceClientRequestMessage message)
{
IShimWebRequest webRequestMessage = message as IShimWebRequest;
HttpWebRequestMessage httpMessage = message as HttpWebRequestMessage;
if (httpMessage != null)
{
InitializeRequest(httpMessage.HttpWebRequest);
}
else if (webRequestMessage != null)
{
InitializeRequest(webRequestMessage.Request);
}
}
private static void InitializeRequest(WebRequest request)
{
try
{
SetCredentialsAndProxy(request);
InitializeRequestProperties(request);
}
catch (InvalidOperationException)
{
// ignore failures here, that can be caused by GetResponse having already been called
}
}
private static void SetCredentialsAndProxy(WebRequest request)
{
// Used the cached credentials and proxy we have
if (request.Credentials == null)
{
request.Credentials = CredentialStore.Instance.GetCredentials(request.RequestUri);
}
if (request.Proxy == null)
{
request.Proxy = ProxyCache.Instance.GetProxy(request.RequestUri);
}
STSAuthHelper.PrepareSTSRequest(request);
}
private static void InitializeRequestProperties(WebRequest request)
{
var httpRequest = request as HttpWebRequest;
if (httpRequest != null)
{
httpRequest.UserAgent = HttpUtility.CreateUserAgentString("NuGet Shim");
httpRequest.CookieContainer = new CookieContainer();
httpRequest.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip;
}
}
}
}

View File

@@ -1,14 +0,0 @@

using System;
namespace NuGet
{
public interface IShimController : IDisposable
{
void Enable(IPackageSourceProvider sourceProvider);
void UpdateSources();
void Disable();
}
}

View File

@@ -1,13 +0,0 @@

using System;
namespace NuGet
{
/// <summary>
/// Provides the IShimController instance for the v3 client.
/// </summary>
public interface IShimControllerProvider : IDisposable
{
IShimController Controller { get; }
}
}

View File

@@ -1,14 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
namespace NuGet
{
public interface IShimWebRequest
{
HttpWebRequest Request { get; }
}
}

View File

@@ -1,99 +0,0 @@
using Microsoft.Data.OData;
using System;
using System.Collections.Generic;
using System.Data.Services.Client;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
namespace NuGet
{
public class ShimDataRequestMessage : IODataRequestMessage
{
public HttpWebRequest WebRequest { get; private set; }
private SendingRequest2EventArgs _args;
public ShimDataRequestMessage(SendingRequest2EventArgs args)
{
_args = args;
WebRequest = ShimWebHelpers.AddHeaders(HttpWebRequest.CreateHttp(_args.RequestMessage.Url), _args.RequestMessage.Headers);
WebRequest.Method = _args.RequestMessage.Method;
}
public ShimDataRequestMessage(DataServiceClientRequestMessageArgs args)
{
WebRequest = ShimWebHelpers.AddHeaders(HttpWebRequest.CreateHttp(args.RequestUri), args.Headers);
WebRequest.Method = args.Method;
}
public string GetHeader(string headerName)
{
return WebRequest.Headers.Get(headerName);
}
public Stream GetStream()
{
return WebRequest.GetRequestStream();
}
public IEnumerable<KeyValuePair<string, string>> Headers
{
get
{
List<KeyValuePair<string, string>> headers = new List<KeyValuePair<string, string>>();
foreach(var header in WebRequest.Headers.AllKeys)
{
headers.Add(new KeyValuePair<string, string>(header, WebRequest.Headers.Get(header)));
}
return headers;
}
}
public void SetHeader(string headerName, string headerValue)
{
if (StringComparer.OrdinalIgnoreCase.Equals(headerName, "Content-Length"))
{
WebRequest.ContentLength = long.Parse(headerValue, CultureInfo.InvariantCulture.NumberFormat);
}
else
{
WebRequest.Headers.Set(headerName, headerValue);
}
}
public Uri Url
{
get
{
return WebRequest.RequestUri;
}
set
{
throw new NotImplementedException();
}
}
public string Method
{
get
{
return WebRequest.Method;
}
set
{
WebRequest.Method = value;
}
}
}
}

View File

@@ -1,44 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
namespace NuGet
{
public static class ShimWebHelpers
{
public static HttpWebRequest AddHeaders(HttpWebRequest response, IEnumerable<KeyValuePair<string, string>> headers)
{
foreach (var header in headers)
{
if (StringComparer.OrdinalIgnoreCase.Equals(header.Key, "accept"))
{
response.Accept = header.Value;
}
else if (StringComparer.OrdinalIgnoreCase.Equals(header.Key, "user-agent"))
{
response.UserAgent = header.Value;
}
else if (StringComparer.OrdinalIgnoreCase.Equals(header.Key, "content-type"))
{
response.ContentType = header.Value;
}
else
{
response.Headers.Set(header.Key, header.Value);
}
}
return response;
}
public static HttpWebRequest AddHeaders(HttpWebRequest response, IDictionary<string, string> headers)
{
return AddHeaders(response, headers.AsEnumerable());
}
}
}

View File

@@ -1,146 +0,0 @@
using System;
namespace NuGet
{
internal abstract class WIFTypeProvider
{
public abstract Type ChannelFactory { get; }
public abstract Type RequestSecurityToken { get; }
public abstract Type EndPoint { get; }
public abstract Type RequestTypes { get; }
public abstract Type KeyTypes { get; }
protected abstract string AssemblyName { get; }
public static WIFTypeProvider GetWIFTypes()
{
// First attempt to look up the 4.5 types
WIFTypeProvider wifProvider = new WIFTypes45();
if (wifProvider.ChannelFactory != null)
{
return wifProvider;
}
// We could be on 4.0 with the SDK \ WIF Runtime installed.
wifProvider = new WIFTypes40();
if (wifProvider.ChannelFactory != null)
{
return wifProvider;
}
return null;
}
protected string QualifyTypeName(string typeName)
{
return typeName + ',' + AssemblyName;
}
private sealed class WIFTypes40 : WIFTypeProvider
{
public override Type ChannelFactory
{
get
{
string typeName = QualifyTypeName("Microsoft.IdentityModel.Protocols.WSTrust.WSTrustChannelFactory");
return Type.GetType(typeName);
}
}
public override Type RequestSecurityToken
{
get
{
string typeName = QualifyTypeName("Microsoft.IdentityModel.Protocols.WSTrust.RequestSecurityToken");
return Type.GetType(typeName);
}
}
public override Type EndPoint
{
get
{
return typeof(System.ServiceModel.EndpointAddress);
}
}
public override Type RequestTypes
{
get
{
string typeName = QualifyTypeName("Microsoft.IdentityModel.SecurityTokenService.RequestTypes");
return Type.GetType(typeName);
}
}
public override Type KeyTypes
{
get
{
string typeName = QualifyTypeName("Microsoft.IdentityModel.SecurityTokenService.KeyTypes");
return Type.GetType(typeName);
}
}
protected override string AssemblyName
{
get { return "Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"; }
}
}
private sealed class WIFTypes45 : WIFTypeProvider
{
public override Type ChannelFactory
{
get
{
return Type.GetType("System.ServiceModel.Security.WSTrustChannelFactory, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");
}
}
public override Type RequestSecurityToken
{
get
{
string typeName = QualifyTypeName("System.IdentityModel.Protocols.WSTrust.RequestSecurityToken");
return Type.GetType(typeName);
}
}
public override Type EndPoint
{
get
{
string typeName = QualifyTypeName("System.IdentityModel.Protocols.WSTrust.EndpointReference");
return Type.GetType(typeName);
}
}
public override Type RequestTypes
{
get
{
string typeName = QualifyTypeName("System.IdentityModel.Protocols.WSTrust.RequestTypes");
return Type.GetType(typeName);
}
}
public override Type KeyTypes
{
get
{
string typeName = QualifyTypeName("System.IdentityModel.Protocols.WSTrust.KeyTypes");
return Type.GetType(typeName);
}
}
protected override string AssemblyName
{
get { return "System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"; }
}
}
}
}

View File

@@ -1,9 +0,0 @@
using System.Collections.Generic;
namespace NuGet
{
public interface IMachineWideSettings
{
IEnumerable<Settings> Settings { get; }
}
}

View File

@@ -20,7 +20,6 @@
<PackageReference Include="System.ServiceModel.Federation" Version="4.8.1" />
<PackageReference Include="System.IO.Packaging" Version="5.0.0" />
<PackageReference Include="System.Diagnostics.Tracing" Version="4.3.0" />
<PackageReference Include="System.Security.Cryptography.ProtectedData" Version="5.0.0" />
<PackageReference Include="SimpleWeakEventListener" Version="1.1.0" />
<PackageReference Include="Microsoft.Data.Services.Client" Version="5.8.4" />
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" />

View File

@@ -1,501 +0,0 @@
using NuGet.Resources;
using System;
using System.Collections.Generic;
using System.Data.Services.Common;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Runtime.Versioning;
namespace NuGet
{
[DataServiceKey("Id", "Version")]
[EntityPropertyMapping("LastUpdated", SyndicationItemProperty.Updated, SyndicationTextContentKind.Plaintext, keepInContent: false)]
[EntityPropertyMapping("Id", SyndicationItemProperty.Title, SyndicationTextContentKind.Plaintext, keepInContent: false)]
[EntityPropertyMapping("Authors", SyndicationItemProperty.AuthorName, SyndicationTextContentKind.Plaintext, keepInContent: false)]
[EntityPropertyMapping("Summary", SyndicationItemProperty.Summary, SyndicationTextContentKind.Plaintext, keepInContent: false)]
[CLSCompliant(false)]
public class DataServicePackage : IPackage
{
private IHashProvider _hashProvider;
private bool _usingMachineCache;
private string _licenseNames;
internal IPackage _package;
public string Id
{
get;
set;
}
public string Version
{
get;
set;
}
public string Title
{
get;
set;
}
public string Authors
{
get;
set;
}
public string Owners
{
get;
set;
}
public Uri IconUrl
{
get;
set;
}
public Uri LicenseUrl
{
get;
set;
}
public Uri ProjectUrl
{
get;
set;
}
public Uri ReportAbuseUrl
{
get;
set;
}
public Uri GalleryDetailsUrl
{
get;
set;
}
public string LicenseNames
{
get { return _licenseNames; }
set
{
_licenseNames = value;
LicenseNameCollection =
String.IsNullOrEmpty(value) ? new string[0] : value.Split(';').ToArray();
}
}
public ICollection<string> LicenseNameCollection { get; private set; }
public Uri LicenseReportUrl { get; set; }
public Uri DownloadUrl
{
get;
set;
}
public bool Listed
{
get;
set;
}
public DateTimeOffset? Published
{
get;
set;
}
public DateTimeOffset LastUpdated
{
get;
set;
}
public int DownloadCount
{
get;
set;
}
public bool RequireLicenseAcceptance
{
get;
set;
}
public bool DevelopmentDependency
{
get;
set;
}
public string Description
{
get;
set;
}
public string Summary
{
get;
set;
}
public string ReleaseNotes
{
get;
set;
}
public string Language
{
get;
set;
}
public string Tags
{
get;
set;
}
public string Dependencies
{
get;
set;
}
public string PackageHash
{
get;
set;
}
public string PackageHashAlgorithm
{
get;
set;
}
public bool IsLatestVersion
{
get;
set;
}
public bool IsAbsoluteLatestVersion
{
get;
set;
}
public string Copyright
{
get;
set;
}
public string MinClientVersion
{
get;
set;
}
private string OldHash { get; set; }
private IPackage Package
{
get
{
EnsurePackage(MachineCache.Default);
return _package;
}
}
internal PackageDownloader Downloader { get; set; }
internal IHashProvider HashProvider
{
get { return _hashProvider ?? new CryptoHashProvider(PackageHashAlgorithm); }
set { _hashProvider = value; }
}
bool IPackage.Listed
{
get
{
return Listed;
}
}
IEnumerable<string> IPackageMetadata.Authors
{
get
{
if (String.IsNullOrEmpty(Authors))
{
return Enumerable.Empty<string>();
}
return Authors.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
}
}
IEnumerable<string> IPackageMetadata.Owners
{
get
{
if (String.IsNullOrEmpty(Owners))
{
return Enumerable.Empty<string>();
}
return Owners.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
}
}
public IEnumerable<PackageDependencySet> DependencySets
{
get
{
if (String.IsNullOrEmpty(Dependencies))
{
return Enumerable.Empty<PackageDependencySet>();
}
return ParseDependencySet(Dependencies);
}
}
public ICollection<PackageReferenceSet> PackageAssemblyReferences
{
get
{
return Package.PackageAssemblyReferences;
}
}
SemanticVersion IPackageName.Version
{
get
{
if (Version != null)
{
return new SemanticVersion(Version);
}
return null;
}
}
Version IPackageMetadata.MinClientVersion
{
get
{
if (!String.IsNullOrEmpty(MinClientVersion))
{
return new Version(MinClientVersion);
}
return null;
}
}
public IEnumerable<IPackageAssemblyReference> AssemblyReferences
{
get
{
return Package.AssemblyReferences;
}
}
public IEnumerable<FrameworkAssemblyReference> FrameworkAssemblies
{
get
{
return Package.FrameworkAssemblies;
}
}
public virtual IEnumerable<FrameworkName> GetSupportedFrameworks()
{
return Package.GetSupportedFrameworks();
}
public IEnumerable<IPackageFile> GetFiles()
{
return Package.GetFiles();
}
public Stream GetStream()
{
return Package.GetStream();
}
public override string ToString()
{
return this.GetFullName();
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope")]
internal void EnsurePackage(IPackageCacheRepository cacheRepository)
{
// OData caches instances of DataServicePackage while updating their property values. As a result,
// the ZipPackage that we downloaded may no longer be valid (as indicated by a newer hash).
// When using MachineCache, once we've verified that the hashes match (which happens the first time around),
// we'll simply verify the file exists between successive calls.
IPackageMetadata packageMetadata = this;
if (_package == null ||
(_package is OptimizedZipPackage && !((OptimizedZipPackage)_package).IsValid) ||
!String.Equals(OldHash, PackageHash, StringComparison.OrdinalIgnoreCase) ||
(_usingMachineCache && !cacheRepository.Exists(Id, packageMetadata.Version)))
{
IPackage newPackage = null;
bool inMemOnly = false;
bool isValid = false;
// If the package exists in the cache and has the correct hash then use it. Otherwise download it.
if (TryGetPackage(cacheRepository, packageMetadata, out newPackage) && MatchPackageHash(newPackage))
{
isValid = true;
}
else
{
// We either do not have a package available locally or they are invalid. Download the package from the server.
if (cacheRepository.InvokeOnPackage(packageMetadata.Id, packageMetadata.Version,
(stream) => Downloader.DownloadPackage(DownloadUrl, this, stream)))
{
newPackage = cacheRepository.FindPackage(packageMetadata.Id, packageMetadata.Version);
Debug.Assert(newPackage != null);
}
else
{
// this can happen when access to the %LocalAppData% directory is blocked, e.g. on Windows Azure Web Site build
using (var targetStream = new MemoryStream())
{
Downloader.DownloadPackage(DownloadUrl, this, targetStream);
targetStream.Seek(0, SeekOrigin.Begin);
newPackage = new ZipPackage(targetStream);
}
inMemOnly = true;
}
// Because of CDN caching, the hash returned in odata feed
// can be out of sync with the hash of the file itself.
// So for now, we cannot call MatchPackageHash(newPackage) to
// validate that the file downloaded has the right hash.
isValid = true;
}
// apply the changes if the package hash was valid
if (isValid)
{
_package = newPackage;
// Use the id and version from the nuspec incase they were different in format or casing
Id = _package.Id;
Version = _package.Version.ToString();
// Make a note that the backing store for the ZipPackage is the machine cache.
_usingMachineCache = !inMemOnly;
OldHash = PackageHash;
}
else
{
// ensure package must end with a valid package, since we cannot load one we must throw.
throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture,
NuGetResources.Error_InvalidPackage, Version, Id));
}
}
}
/// <summary>
/// True if the given package matches PackageHash
/// </summary>
private bool MatchPackageHash(IPackage package)
{
return package != null && package.GetHash(HashProvider).Equals(PackageHash, StringComparison.OrdinalIgnoreCase);
}
private static List<PackageDependencySet> ParseDependencySet(string value)
{
var dependencySets = new List<PackageDependencySet>();
var dependencies = value.Split('|').Select(ParseDependency).ToList();
// group the dependencies by target framework
var groups = dependencies.GroupBy(d => d.Item3);
dependencySets.AddRange(
groups.Select(g => new PackageDependencySet(
g.Key, // target framework
g.Where(pair => !String.IsNullOrEmpty(pair.Item1)) // the Id is empty when a group is empty.
.Select(pair => new PackageDependency(pair.Item1, pair.Item2))))); // dependencies by that target framework
return dependencySets;
}
/// <summary>
/// Parses a dependency from the feed in the format:
/// id or id:versionSpec, or id:versionSpec:targetFramework
/// </summary>
private static Tuple<string, IVersionSpec, FrameworkName> ParseDependency(string value)
{
if (String.IsNullOrWhiteSpace(value))
{
return null;
}
// IMPORTANT: Do not pass StringSplitOptions.RemoveEmptyEntries to this method, because it will break
// if the version spec is null, for in that case, the Dependencies string sent down is "<id>::<target framework>".
// We do want to preserve the second empty element after the split.
string[] tokens = value.Trim().Split(new[] { ':' });
if (tokens.Length == 0)
{
return null;
}
// Trim the id
string id = tokens[0].Trim();
IVersionSpec versionSpec = null;
if (tokens.Length > 1)
{
// Attempt to parse the version
VersionUtility.TryParseVersionSpec(tokens[1], out versionSpec);
}
var targetFramework = (tokens.Length > 2 && !String.IsNullOrEmpty(tokens[2]))
? VersionUtility.ParseFrameworkName(tokens[2])
: null;
return Tuple.Create(id, versionSpec, targetFramework);
}
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "We want to return null if any error occurred while trying to find the package.")]
private static bool TryGetPackage(IPackageRepository repository, IPackageMetadata packageMetadata, out IPackage package)
{
try
{
package = repository.FindPackage(packageMetadata.Id, packageMetadata.Version);
}
catch
{
// If the package in the repository is corrupted then return null
package = null;
}
return package != null;
}
}
}

View File

@@ -1,111 +0,0 @@
using System;
using System.Globalization;
namespace NuGet
{
public class PackageRestoreConsent
{
private const string EnvironmentVariableName = "EnableNuGetPackageRestore";
private const string PackageRestoreSection = "packageRestore";
private const string PackageRestoreConsentKey = "enabled";
// the key to enable/disable automatic package restore during build.
private const string PackageRestoreAutomaticKey = "automatic";
private readonly ISettings _settings;
private readonly IEnvironmentVariableReader _environmentReader;
private readonly ConfigurationDefaults _configurationDefaults;
public PackageRestoreConsent(ISettings settings)
: this(settings, new EnvironmentVariableWrapper())
{
}
public PackageRestoreConsent(ISettings settings, IEnvironmentVariableReader environmentReader)
: this(settings, environmentReader, ConfigurationDefaults.Instance)
{
}
public PackageRestoreConsent(ISettings settings, IEnvironmentVariableReader environmentReader, ConfigurationDefaults configurationDefaults)
{
if (settings == null)
{
throw new ArgumentNullException("settings");
}
if (environmentReader == null)
{
throw new ArgumentNullException("environmentReader");
}
if (configurationDefaults == null)
{
throw new ArgumentNullException("configurationDefaults");
}
_settings = settings;
_environmentReader = environmentReader;
_configurationDefaults = configurationDefaults;
}
public bool IsGranted
{
get
{
string envValue = _environmentReader.GetEnvironmentVariable(EnvironmentVariableName).SafeTrim();
return IsGrantedInSettings || IsSet(envValue);
}
}
public bool IsGrantedInSettings
{
get
{
string settingsValue = _settings.GetValue(PackageRestoreSection, PackageRestoreConsentKey);
if (String.IsNullOrWhiteSpace(settingsValue))
{
settingsValue = _configurationDefaults.DefaultPackageRestoreConsent;
}
settingsValue = settingsValue.SafeTrim();
if (String.IsNullOrEmpty(settingsValue))
{
// default value of user consent is true.
return true;
}
return IsSet(settingsValue);
}
set
{
_settings.SetValue(PackageRestoreSection, PackageRestoreConsentKey, value.ToString());
}
}
public bool IsAutomatic
{
get
{
string settingsValue = _settings.GetValue(PackageRestoreSection, PackageRestoreAutomaticKey);
if (String.IsNullOrWhiteSpace(settingsValue))
{
return IsGrantedInSettings;
}
settingsValue = settingsValue.SafeTrim();
return IsSet(settingsValue);
}
set
{
_settings.SetValue(PackageRestoreSection, PackageRestoreAutomaticKey, value.ToString());
}
}
private static bool IsSet(string value)
{
bool boolResult;
int intResult;
return ((Boolean.TryParse(value, out boolResult) && boolResult) ||
(Int32.TryParse(value, NumberStyles.Number, CultureInfo.InvariantCulture, out intResult) && (intResult == 1)));
}
}
}

View File

@@ -1,15 +0,0 @@
using System;
using System.Collections.Generic;
namespace NuGet
{
public interface IPackageSourceProvider
{
IEnumerable<PackageSource> LoadPackageSources();
event EventHandler PackageSourcesSaved;
void SavePackageSources(IEnumerable<PackageSource> sources);
void DisablePackageSource(PackageSource source);
bool IsPackageSourceEnabled(PackageSource source);
}
}

View File

@@ -1,115 +0,0 @@
using System;
using System.Runtime.Serialization;
namespace NuGet
{
[DataContract]
public class PackageSource : IEquatable<PackageSource>
{
private readonly int _hashCode;
[DataMember]
public string Name { get; private set; }
[DataMember]
public string Source { get; private set; }
/// <summary>
/// This does not represent just the NuGet Official Feed alone
/// It may also represent a Default Package Source set by Configuration Defaults
/// </summary>
public bool IsOfficial { get; set; }
public bool IsMachineWide { get; set; }
public bool IsEnabled { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public bool IsPasswordClearText { get; set; }
public bool IsPersistable
{
get;
private set;
}
public PackageSource(string source) :
this(source, source, isEnabled: true)
{
}
public PackageSource(string source, string name) :
this(source, name, isEnabled: true)
{
}
public PackageSource(string source, string name, bool isEnabled)
: this(source, name, isEnabled, isOfficial: false)
{
}
public PackageSource(
string source,
string name,
bool isEnabled,
bool isOfficial,
bool isPersistable = true)
{
if (source == null)
{
throw new ArgumentNullException("source");
}
if (name == null)
{
throw new ArgumentNullException("name");
}
Name = name;
Source = source;
IsEnabled = isEnabled;
IsOfficial = isOfficial;
IsPersistable = isPersistable;
_hashCode = Name.ToUpperInvariant().GetHashCode() * 3137 + Source.ToUpperInvariant().GetHashCode();
}
public bool Equals(PackageSource other)
{
if (other == null)
{
return false;
}
return Name.Equals(other.Name, StringComparison.CurrentCultureIgnoreCase) &&
Source.Equals(other.Source, StringComparison.OrdinalIgnoreCase);
}
public override bool Equals(object obj)
{
var source = obj as PackageSource;
if (source != null)
{
return Equals(source);
}
return base.Equals(obj);
}
public override string ToString()
{
return Name + " [" + Source + "]";
}
public override int GetHashCode()
{
return _hashCode;
}
public PackageSource Clone()
{
return new PackageSource(Source, Name, IsEnabled, IsOfficial, IsPersistable) { UserName = UserName, Password = Password, IsPasswordClearText = IsPasswordClearText, IsMachineWide = IsMachineWide };
}
}
}

View File

@@ -1,384 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
namespace NuGet
{
public class PackageSourceProvider : IPackageSourceProvider
{
private const string PackageSourcesSectionName = "packageSources";
private const string DisabledPackageSourcesSectionName = "disabledPackageSources";
private const string CredentialsSectionName = "packageSourceCredentials";
private const string UsernameToken = "Username";
private const string PasswordToken = "Password";
private const string ClearTextPasswordToken = "ClearTextPassword";
private readonly ISettings _settingsManager;
private readonly IEnumerable<PackageSource> _providerDefaultSources;
private readonly IDictionary<PackageSource, PackageSource> _migratePackageSources;
private readonly IEnumerable<PackageSource> _configurationDefaultSources;
private IEnvironmentVariableReader _environment;
public PackageSourceProvider(ISettings settingsManager)
: this(settingsManager, providerDefaultSources: null)
{
}
/// <summary>
/// Creates a new PackageSourceProvider instance.
/// </summary>
/// <param name="settingsManager">Specifies the settings file to use to read package sources.</param>
/// <param name="providerDefaultSources">Specifies the default sources to be used as per the PackageSourceProvider. These are always loaded
/// Default Feeds from PackageSourceProvider are generally the feeds from the NuGet Client like the NuGetOfficialFeed from the Visual Studio client for NuGet</param>
public PackageSourceProvider(ISettings settingsManager, IEnumerable<PackageSource> providerDefaultSources)
: this(settingsManager, providerDefaultSources, migratePackageSources: null)
{
}
public PackageSourceProvider(
ISettings settingsManager,
IEnumerable<PackageSource> providerDefaultSources,
IDictionary<PackageSource, PackageSource> migratePackageSources)
: this(settingsManager, providerDefaultSources, migratePackageSources, ConfigurationDefaults.Instance.DefaultPackageSources, new EnvironmentVariableWrapper())
{
}
internal PackageSourceProvider(
ISettings settingsManager,
IEnumerable<PackageSource> providerDefaultSources,
IDictionary<PackageSource, PackageSource> migratePackageSources,
IEnumerable<PackageSource> configurationDefaultSources,
IEnvironmentVariableReader environment)
{
if (settingsManager == null)
{
throw new ArgumentNullException("settingsManager");
}
_settingsManager = settingsManager;
_providerDefaultSources = providerDefaultSources ?? Enumerable.Empty<PackageSource>();
_migratePackageSources = migratePackageSources;
_configurationDefaultSources = configurationDefaultSources ?? Enumerable.Empty<PackageSource>();
_environment = environment;
}
/// <summary>
/// Returns PackageSources if specified in the config file. Else returns the default sources specified in the constructor.
/// If no default values were specified, returns an empty sequence.
/// </summary>
public IEnumerable<PackageSource> LoadPackageSources()
{
var sources = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
var settingsValue = new List<SettingValue>();
IList<SettingValue> values = _settingsManager.GetSettingValues(PackageSourcesSectionName, isPath: true);
var machineWideSourcesCount = 0;
if (!values.IsEmpty())
{
var machineWideSources = new List<SettingValue>();
// remove duplicate sources. Pick the one with the highest priority.
// note that Reverse() is needed because items in 'values' is in
// ascending priority order.
foreach (var settingValue in values.Reverse())
{
if (!sources.Contains(settingValue.Key))
{
if (settingValue.IsMachineWide)
{
machineWideSources.Add(settingValue);
}
else
{
settingsValue.Add(settingValue);
}
sources.Add(settingValue.Key);
}
}
// Reverse the the list to be backward compatible
settingsValue.Reverse();
machineWideSourcesCount = machineWideSources.Count;
// Add machine wide sources at the end
settingsValue.AddRange(machineWideSources);
}
var loadedPackageSources = new List<PackageSource>();
if (!settingsValue.IsEmpty())
{
// get list of disabled packages
var disabledSources = (_settingsManager.GetSettingValues(DisabledPackageSourcesSectionName, isPath: false) ?? Enumerable.Empty<SettingValue>())
.ToDictionary(s => s.Key, StringComparer.CurrentCultureIgnoreCase);
loadedPackageSources = settingsValue.
Select(p =>
{
string name = p.Key;
string src = p.Value;
PackageSourceCredential creds = ReadCredential(name);
bool isEnabled = true;
SettingValue disabledSource;
if (disabledSources.TryGetValue(name, out disabledSource) &&
disabledSource.Priority >= p.Priority)
{
isEnabled = false;
}
return new PackageSource(src, name, isEnabled)
{
UserName = creds != null ? creds.Username : null,
Password = creds != null ? creds.Password : null,
IsPasswordClearText = creds != null && creds.IsPasswordClearText,
IsMachineWide = p.IsMachineWide
};
}).ToList();
if (_migratePackageSources != null)
{
MigrateSources(loadedPackageSources);
}
}
SetDefaultPackageSources(loadedPackageSources, machineWideSourcesCount);
return loadedPackageSources;
}
private PackageSourceCredential ReadCredential(string sourceName)
{
PackageSourceCredential environmentCredentials = ReadCredentialFromEnvironment(sourceName);
if (environmentCredentials != null)
{
return environmentCredentials;
}
var values = _settingsManager.GetNestedValues(CredentialsSectionName, sourceName);
if (!values.IsEmpty())
{
string userName = values.FirstOrDefault(k => k.Key.Equals(UsernameToken, StringComparison.OrdinalIgnoreCase)).Value;
if (!String.IsNullOrEmpty(userName))
{
string encryptedPassword = values.FirstOrDefault(k => k.Key.Equals(PasswordToken, StringComparison.OrdinalIgnoreCase)).Value;
if (!String.IsNullOrEmpty(encryptedPassword))
{
return new PackageSourceCredential(userName, EncryptionUtility.DecryptString(encryptedPassword), isPasswordClearText: false);
}
string clearTextPassword = values.FirstOrDefault(k => k.Key.Equals(ClearTextPasswordToken, StringComparison.Ordinal)).Value;
if (!String.IsNullOrEmpty(clearTextPassword))
{
return new PackageSourceCredential(userName, clearTextPassword, isPasswordClearText: true);
}
}
}
return null;
}
private PackageSourceCredential ReadCredentialFromEnvironment(string sourceName)
{
string rawCredentials = _environment.GetEnvironmentVariable("NuGetPackageSourceCredentials_" + sourceName);
if (string.IsNullOrEmpty(rawCredentials))
{
return null;
}
var match = Regex.Match(rawCredentials.Trim(), @"^Username=(?<user>.*?);\s*Password=(?<pass>.*?)$", RegexOptions.IgnoreCase);
if (!match.Success)
{
return null;
}
return new PackageSourceCredential(match.Groups["user"].Value, match.Groups["pass"].Value, true);
}
private void MigrateSources(List<PackageSource> loadedPackageSources)
{
bool hasChanges = false;
List<PackageSource> packageSourcesToBeRemoved = new List<PackageSource>();
// doing migration
for (int i = 0; i < loadedPackageSources.Count; i++)
{
PackageSource ps = loadedPackageSources[i];
PackageSource targetPackageSource;
if (_migratePackageSources.TryGetValue(ps, out targetPackageSource))
{
if (loadedPackageSources.Any(p => p.Equals(targetPackageSource)))
{
packageSourcesToBeRemoved.Add(loadedPackageSources[i]);
}
else
{
loadedPackageSources[i] = targetPackageSource.Clone();
// make sure we preserve the IsEnabled property when migrating package sources
loadedPackageSources[i].IsEnabled = ps.IsEnabled;
}
hasChanges = true;
}
}
foreach (PackageSource packageSource in packageSourcesToBeRemoved)
{
loadedPackageSources.Remove(packageSource);
}
if (hasChanges)
{
SavePackageSources(loadedPackageSources);
}
}
private void SetDefaultPackageSources(List<PackageSource> loadedPackageSources, int machineWideSourcesCount)
{
// There are 4 different cases to consider for default package sources
// Case 1. Default Package Source is already present matching both feed source and the feed name
// Case 2. Default Package Source is already present matching feed source but with a different feed name. DO NOTHING
// Case 3. Default Package Source is not present, but there is another feed source with the same feed name. Override that feed entirely
// Case 4. Default Package Source is not present, simply, add it
IEnumerable<PackageSource> allDefaultPackageSources = _configurationDefaultSources;
if (allDefaultPackageSources.IsEmpty<PackageSource>())
{
// Update provider default sources and use provider default sources since _configurationDefaultSources is empty
UpdateProviderDefaultSources(loadedPackageSources);
allDefaultPackageSources = _providerDefaultSources;
}
var defaultPackageSourcesToBeAdded = new List<PackageSource>();
foreach (PackageSource packageSource in allDefaultPackageSources)
{
int sourceMatchingIndex = loadedPackageSources.FindIndex(p => p.Source.Equals(packageSource.Source, StringComparison.OrdinalIgnoreCase));
if (sourceMatchingIndex != -1)
{
if (loadedPackageSources[sourceMatchingIndex].Name.Equals(packageSource.Name, StringComparison.CurrentCultureIgnoreCase))
{
// Case 1: Both the feed name and source matches. DO NOTHING except set IsOfficial to true
loadedPackageSources[sourceMatchingIndex].IsOfficial = true;
}
else
{
// Case 2: Only feed source matches but name is different. DO NOTHING
}
}
else
{
int nameMatchingIndex = loadedPackageSources.FindIndex(p => p.Name.Equals(packageSource.Name, StringComparison.CurrentCultureIgnoreCase));
if (nameMatchingIndex != -1)
{
// Case 3: Only feed name matches but source is different. Override it entirely
loadedPackageSources[nameMatchingIndex] = packageSource;
}
else
{
// Case 4: Default package source is not present. Add it to the temp list. Later, the temp listed is inserted above the machine wide sources
defaultPackageSourcesToBeAdded.Add(packageSource);
}
}
}
loadedPackageSources.InsertRange(loadedPackageSources.Count - machineWideSourcesCount, defaultPackageSourcesToBeAdded);
}
private void UpdateProviderDefaultSources(List<PackageSource> loadedSources)
{
// If there are NO other non-machine wide sources, providerDefaultSource should be enabled
bool areProviderDefaultSourcesEnabled = loadedSources.Count == 0 || loadedSources.Where(p => !p.IsMachineWide).Count() == 0;
foreach (PackageSource packageSource in _providerDefaultSources)
{
packageSource.IsEnabled = areProviderDefaultSourcesEnabled;
packageSource.IsOfficial = true;
}
}
public void SavePackageSources(IEnumerable<PackageSource> sources)
{
// clear the old values
_settingsManager.DeleteSection(PackageSourcesSectionName);
// and write the new ones
_settingsManager.SetValues(
PackageSourcesSectionName,
sources.Where(p => !p.IsMachineWide && p.IsPersistable)
.Select(p => new KeyValuePair<string, string>(p.Name, p.Source))
.ToList());
// overwrite new values for the <disabledPackageSources> section
_settingsManager.DeleteSection(DisabledPackageSourcesSectionName);
_settingsManager.SetValues(
DisabledPackageSourcesSectionName,
sources.Where(p => !p.IsEnabled).Select(p => new KeyValuePair<string, string>(p.Name, "true")).ToList());
// Overwrite the <packageSourceCredentials> section
_settingsManager.DeleteSection(CredentialsSectionName);
var sourceWithCredentials = sources.Where(s => !String.IsNullOrEmpty(s.UserName) && !String.IsNullOrEmpty(s.Password));
foreach (var source in sourceWithCredentials)
{
_settingsManager.SetNestedValues(CredentialsSectionName, source.Name, new[] {
new KeyValuePair<string, string>(UsernameToken, source.UserName),
ReadPasswordValues(source)
});
}
if (PackageSourcesSaved != null)
{
PackageSourcesSaved(this, EventArgs.Empty);
}
}
private static KeyValuePair<string, string> ReadPasswordValues(PackageSource source)
{
string passwordToken = source.IsPasswordClearText ? ClearTextPasswordToken : PasswordToken;
string passwordValue = source.IsPasswordClearText ? source.Password : EncryptionUtility.EncryptString(source.Password);
return new KeyValuePair<string, string>(passwordToken, passwordValue);
}
public void DisablePackageSource(PackageSource source)
{
if (source == null)
{
throw new ArgumentNullException("source");
}
_settingsManager.SetValue(DisabledPackageSourcesSectionName, source.Name, "true");
}
public bool IsPackageSourceEnabled(PackageSource source)
{
if (source == null)
{
throw new ArgumentNullException("source");
}
string value = _settingsManager.GetValue(DisabledPackageSourcesSectionName, source.Name);
// It doesn't matter what value it is.
// As long as the package source name is persisted in the <disabledPackageSources> section, the source is disabled.
return String.IsNullOrEmpty(value);
}
private class PackageSourceCredential
{
public string Username { get; private set; }
public string Password { get; private set; }
public bool IsPasswordClearText { get; private set; }
public PackageSourceCredential(string username, string password, bool isPasswordClearText)
{
Username = username;
Password = password;
IsPasswordClearText = isPasswordClearText;
}
}
public event EventHandler PackageSourcesSaved;
}
}

View File

@@ -1,57 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace NuGet
{
public static class PackageSourceProviderExtensions
{
public static AggregateRepository CreateAggregateRepository(
this IPackageSourceProvider provider,
IPackageRepositoryFactory factory,
bool ignoreFailingRepositories)
{
return new AggregateRepository(
factory,
provider.GetEnabledPackageSources().Select(s => s.Source),
ignoreFailingRepositories);
}
public static IPackageRepository CreatePriorityPackageRepository(
this IPackageSourceProvider provider,
IPackageRepositoryFactory factory,
IPackageRepository primaryRepository)
{
var nonActivePackageSources = provider.GetEnabledPackageSources()
.Where(s => !s.Source.Equals(primaryRepository.Source, StringComparison.OrdinalIgnoreCase))
.ToArray();
if (nonActivePackageSources.Length == 0)
{
return primaryRepository;
}
var fallbackRepository = AggregateRepository.Create(factory, sources: nonActivePackageSources, ignoreFailingRepositories: true);
return new PriorityPackageRepository(primaryRepository, fallbackRepository);
}
/// <summary>
/// Resolves a package source by either Name or Source.
/// </summary>
public static string ResolveSource(this IPackageSourceProvider provider, string value)
{
var resolvedSource = (from source in provider.GetEnabledPackageSources()
where source.Name.Equals(value, StringComparison.CurrentCultureIgnoreCase) || source.Source.Equals(value, StringComparison.OrdinalIgnoreCase)
select source.Source
).FirstOrDefault();
return resolvedSource ?? value;
}
public static IEnumerable<PackageSource> GetEnabledPackageSources(this IPackageSourceProvider provider)
{
return provider.LoadPackageSources().Where(p => p.IsEnabled);
}
}
}

View File

@@ -1,12 +0,0 @@
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
[assembly: AssemblyTitle("NuGet.Core")]
[assembly: AssemblyDescription("NuGet.Core is the core framework assembly for NuGet that the rest of NuGet builds upon.")]
[assembly: CLSCompliant(true)]
[assembly: InternalsVisibleTo("NuGet.Test")]
[assembly: InternalsVisibleTo("NuGet.Test.Utility")]
[assembly: InternalsVisibleTo("NuGet.Test.Integration")]
[assembly: InternalsVisibleTo("NuGet.VisualStudio.Test")]

View File

@@ -1,17 +0,0 @@
<?xml version="1.0"?>
<package>
<metadata>
<id>$id$</id>
<version>$version$</version>
<description>$description$</description>
<authors>.NET Foundation</authors>
<owners>$author$</owners>
<licenseUrl>http://nuget.codeplex.com/license</licenseUrl>
<projectUrl>http://nuget.codeplex.com</projectUrl>
<copyright>$copyright$</copyright>
<tags>nuget</tags>
<dependencies>
<dependency id="Microsoft.Web.Xdt" version="2.1.0" />
</dependencies>
</metadata>
</package>

View File

@@ -1,330 +0,0 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Runtime.Versioning;
using System.Threading.Tasks;
namespace NuGet
{
public class AggregateRepository : PackageRepositoryBase, IPackageLookup, IDependencyResolver, IServiceBasedRepository, ICloneableRepository, IOperationAwareRepository
{
/// <summary>
/// When the ignore flag is set up, this collection keeps track of failing repositories so that the AggregateRepository
/// does not query them again.
/// </summary>
private readonly ConcurrentBag<IPackageRepository> _failingRepositories = new ConcurrentBag<IPackageRepository>();
private readonly IEnumerable<IPackageRepository> _repositories;
private readonly Lazy<bool> _supportsPrereleasePackages;
private const string SourceValue = "(Aggregate source)";
private ILogger _logger;
public override string Source
{
get { return SourceValue; }
}
public ILogger Logger
{
get { return _logger ?? NullLogger.Instance; }
set { _logger = value; }
}
/// <summary>
/// Determines if dependency resolution is performed serially on a per-repository basis. The first repository that has a compatible dependency
/// regardless of version would win if this property is true.
/// </summary>
public bool ResolveDependenciesVertically { get; set; }
public bool IgnoreFailingRepositories { get; set; }
/// <remarks>
/// Iterating over Repositories returned by this property may throw regardless of IgnoreFailingRepositories.
/// </remarks>
public IEnumerable<IPackageRepository> Repositories
{
get { return _repositories; }
}
public override bool SupportsPrereleasePackages
{
get
{
return _supportsPrereleasePackages.Value;
}
}
public AggregateRepository(IEnumerable<IPackageRepository> repositories)
{
if (repositories == null)
{
throw new ArgumentNullException("repositories");
}
_repositories = Flatten(repositories);
Func<IPackageRepository, bool> supportsPrereleasePackages = Wrap(r => r.SupportsPrereleasePackages, defaultValue: true);
_supportsPrereleasePackages = new Lazy<bool>(() => _repositories.All(supportsPrereleasePackages));
IgnoreFailingRepositories = true;
}
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "We want to suppress any exception that we may encounter.")]
public AggregateRepository(IPackageRepositoryFactory repositoryFactory, IEnumerable<string> packageSources, bool ignoreFailingRepositories)
{
IgnoreFailingRepositories = ignoreFailingRepositories;
Func<string, IPackageRepository> createRepository = repositoryFactory.CreateRepository;
if (ignoreFailingRepositories)
{
createRepository = (source) =>
{
try
{
return repositoryFactory.CreateRepository(source);
}
catch
{
return null;
}
};
}
_repositories = (from source in packageSources
let repository = createRepository(source)
where repository != null
select repository).ToArray();
Func<IPackageRepository, bool> supportsPrereleasePackages = Wrap(r => r.SupportsPrereleasePackages, defaultValue: true);
_supportsPrereleasePackages = new Lazy<bool>(() => _repositories.All(supportsPrereleasePackages));
}
public override IQueryable<IPackage> GetPackages()
{
// We need to follow this pattern in all AggregateRepository methods to ensure it suppresses exceptions that may occur if the Ignore flag is set. Oh how I despise my code.
var defaultResult = Enumerable.Empty<IPackage>().AsQueryable();
Func<IPackageRepository, IQueryable<IPackage>> getPackages = Wrap(r => r.GetPackages(), defaultResult);
return CreateAggregateQuery(Repositories.Select(getPackages));
}
public IPackage FindPackage(string packageId, SemanticVersion version)
{
// When we're looking for an exact package, we can optimize but searching each
// repository one by one until we find the package that matches.
Func<IPackageRepository, IPackage> findPackage = Wrap(r => r.FindPackage(packageId, version));
return Repositories.Select(findPackage)
.FirstOrDefault(p => p != null);
}
public bool Exists(string packageId, SemanticVersion version)
{
// When we're looking for an exact package, we can optimize but searching each
// repository one by one until we find the package that matches.
Func<IPackageRepository, bool> exists = Wrap(r => r.Exists(packageId, version));
return Repositories.Any(exists);
}
public IPackage ResolveDependency(PackageDependency dependency, IPackageConstraintProvider constraintProvider, bool allowPrereleaseVersions, bool preferListedPackages, DependencyVersion dependencyVersion)
{
if (ResolveDependenciesVertically)
{
Func<IPackageRepository, IPackage> resolveDependency = Wrap(
r => DependencyResolveUtility.ResolveDependency(r, dependency, constraintProvider, allowPrereleaseVersions, preferListedPackages, dependencyVersion));
return Repositories.Select(r => Task.Factory.StartNew(() => resolveDependency(r)))
.ToArray()
.WhenAny(package => package != null);
}
return DependencyResolveUtility.ResolveDependencyCore(this, dependency, constraintProvider, allowPrereleaseVersions, preferListedPackages, dependencyVersion);
}
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "We want to suppress any exception that we may encounter.")]
private Func<IPackageRepository, T> Wrap<T>(Func<IPackageRepository, T> factory, T defaultValue = default(T))
{
if (IgnoreFailingRepositories)
{
return repository =>
{
if (_failingRepositories.Contains(repository))
{
return defaultValue;
}
try
{
return factory(repository);
}
catch (Exception ex)
{
LogRepository(repository, ex);
return defaultValue;
}
};
}
return factory;
}
public void LogRepository(IPackageRepository repository, Exception ex)
{
_failingRepositories.Add(repository);
Logger.Log(MessageLevel.Warning, ExceptionUtility.Unwrap(ex).Message);
}
public IQueryable<IPackage> Search(string searchTerm, IEnumerable<string> targetFrameworks, bool allowPrereleaseVersions, bool includeDelisted)
{
return CreateAggregateQuery(Repositories.Select(r => r.Search(searchTerm, targetFrameworks, allowPrereleaseVersions, includeDelisted)));
}
public IPackageRepository Clone()
{
return new AggregateRepository(Repositories.Select(PackageRepositoryExtensions.Clone));
}
private AggregateQuery<IPackage> CreateAggregateQuery(IEnumerable<IQueryable<IPackage>> queries)
{
return new AggregateQuery<IPackage>(queries,
PackageEqualityComparer.IdAndVersion,
Logger,
IgnoreFailingRepositories);
}
internal static IEnumerable<IPackageRepository> Flatten(IEnumerable<IPackageRepository> repositories)
{
return repositories.SelectMany(repository =>
{
var aggrgeateRepository = repository as AggregateRepository;
if (aggrgeateRepository != null)
{
return aggrgeateRepository.Repositories.ToArray();
}
return new[] { repository };
});
}
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "We want to suppress any exception that we may encounter.")]
public IEnumerable<IPackage> FindPackagesById(string packageId)
{
var tasks = _repositories.Select(p => Task.Factory.StartNew(state => p.FindPackagesById(packageId), p)).ToArray();
try
{
Task.WaitAll(tasks);
}
catch (AggregateException)
{
if (!IgnoreFailingRepositories)
{
throw;
}
}
var allPackages = new List<IPackage>();
foreach (var task in tasks)
{
if (task.IsFaulted)
{
LogRepository((IPackageRepository)task.AsyncState, task.Exception);
}
else if (task.Result != null)
{
allPackages.AddRange(task.Result);
}
}
return allPackages;
}
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "We want to suppress any exception that we may encounter.")]
public IEnumerable<IPackage> GetUpdates(
IEnumerable<IPackageName> packages,
bool includePrerelease,
bool includeAllVersions,
IEnumerable<FrameworkName> targetFrameworks,
IEnumerable<IVersionSpec> versionConstraints)
{
// GetUpdatesCore returns all updates. We'll allow the extension method to determine if we need to collapse based on allVersion.
var tasks = _repositories.Select(p => Task.Factory.StartNew(state => p.GetUpdates(packages, includePrerelease, includeAllVersions, targetFrameworks, versionConstraints), p)).ToArray();
try
{
Task.WaitAll(tasks);
}
catch (AggregateException)
{
if (!IgnoreFailingRepositories)
{
throw;
}
}
var allPackages = new HashSet<IPackage>(PackageEqualityComparer.IdAndVersion);
foreach (var task in tasks)
{
if (task.IsFaulted)
{
LogRepository((IPackageRepository)task.AsyncState, task.Exception);
}
else if (task.Result != null)
{
allPackages.AddRange(task.Result);
}
}
if (includeAllVersions)
{
// If we return all packages, sort them by Id and Version to make the sequence predictable.
return allPackages.OrderBy(p => p.Id, StringComparer.OrdinalIgnoreCase)
.ThenBy(p => p.Version);
}
return allPackages.CollapseById();
}
public IDisposable StartOperation(string operation, string mainPackageId, string mainPackageVersion)
{
return DisposableAction.All(
Repositories.Select(r => r.StartOperation(operation, mainPackageId, mainPackageVersion)));
}
public static IPackageRepository Create(
IPackageRepositoryFactory factory,
IList<PackageSource> sources,
bool ignoreFailingRepositories)
{
if (sources.Count == 0)
{
return null;
}
if (sources.Count == 1)
{
// optimization: if there is only one package source, create a direct repository out of it.
return factory.CreateRepository(sources[0].Source);
}
Func<string, IPackageRepository> createRepository = factory.CreateRepository;
if (ignoreFailingRepositories)
{
createRepository = (source) =>
{
try
{
return factory.CreateRepository(source);
}
catch (InvalidOperationException)
{
return null;
}
};
}
var repositories = from source in sources
let repository = createRepository(source.Source)
where repository != null
select repository;
return new AggregateRepository(repositories)
{
IgnoreFailingRepositories = ignoreFailingRepositories
};
}
}
}

View File

@@ -1,289 +0,0 @@
using System;
using System.Collections.Generic;
using System.Data.Services.Client;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Windows;
using System.Xml.Linq;
namespace NuGet
{
[CLSCompliant(false)]
public class DataServiceContextWrapper : IDataServiceContext
{
private const string MetadataKey = "DataServiceMetadata|";
private static readonly MethodInfo _executeMethodInfo = typeof(DataServiceContext).GetMethod("Execute", new[] { typeof(Uri) });
private readonly DataServiceContext _context;
private readonly Uri _metadataUri;
public DataServiceContextWrapper(Uri serviceRoot)
{
if (serviceRoot == null)
{
throw new ArgumentNullException("serviceRoot");
}
_context = new DataServiceContext(serviceRoot)
{
MergeOption = MergeOption.NoTracking
};
_metadataUri = _context.GetMetadataUri();
AttachEvents();
}
private DataServiceClientRequestMessage ShimWebRequests(DataServiceClientRequestMessageArgs args)
{
// Shim the requests if needed
return HttpShim.Instance.ShimDataServiceRequest(args);
}
public bool ReceiveWeakEvent(Type managerType, object sender, EventArgs e)
{
if (managerType == typeof(Func<DataServiceClientRequestMessage, DataServiceClientRequestMessageArgs>))
{
return true;
}
else
{
return false;
}
}
private void AttachEvents()
{
_context.Configurations.RequestPipeline.OnMessageCreating += ShimWebRequests;
}
//private void DetachEvents()
//{
// _context.Configurations.RequestPipeline.OnMessageCreating -= ShimWebRequests;
//}
//public void Dispose()
//{
// DetachEvents();
//}
public Uri BaseUri
{
get
{
return _context.BaseUri;
}
}
public event EventHandler<SendingRequest2EventArgs> SendingRequest
{
add
{
_context.SendingRequest2 += value;
}
remove
{
_context.SendingRequest2 -= value;
}
}
public event EventHandler<ReadingWritingEntityEventArgs> ReadingEntity
{
add
{
_context.ReadingEntity += value;
}
remove
{
_context.ReadingEntity -= value;
}
}
public bool IgnoreMissingProperties
{
get
{
return _context.IgnoreMissingProperties;
}
set
{
_context.IgnoreMissingProperties = value;
}
}
private DataServiceMetadata ServiceMetadata
{
get
{
return MemoryCache.Instance.GetOrAdd(GetServiceMetadataKey(), () => GetDataServiceMetadata(_metadataUri), TimeSpan.FromMinutes(15));
}
}
public IDataServiceQuery<T> CreateQuery<T>(string entitySetName, IDictionary<string, object> queryOptions)
{
var query = _context.CreateQuery<T>(entitySetName);
foreach (var pair in queryOptions)
{
query = query.AddQueryOption(pair.Key, pair.Value);
}
return new DataServiceQueryWrapper<T>(this, query);
}
public IDataServiceQuery<T> CreateQuery<T>(string entitySetName)
{
return new DataServiceQueryWrapper<T>(this, _context.CreateQuery<T>(entitySetName));
}
public IEnumerable<T> Execute<T>(Type elementType, DataServiceQueryContinuation continuation)
{
// Get the generic execute method
MethodInfo executeMethod = _executeMethodInfo.MakeGenericMethod(elementType);
// Get the results from the continuation
return (IEnumerable<T>)executeMethod.Invoke(_context, new object[] { continuation.NextLinkUri });
}
public IEnumerable<T> ExecuteBatch<T>(DataServiceRequest request)
{
throw new NotImplementedException();
//return _context.ExecuteBatch(request)
// .Cast<QueryOperationResponse>()
// .SelectMany(o => o.Cast<T>());
}
public bool SupportsServiceMethod(string methodName)
{
return ServiceMetadata != null && ServiceMetadata.SupportedMethodNames.Contains(methodName);
}
public bool SupportsProperty(string propertyName)
{
return ServiceMetadata != null && ServiceMetadata.SupportedProperties.Contains(propertyName);
}
internal sealed class DataServiceMetadata
{
public HashSet<string> SupportedMethodNames { get; set; }
public HashSet<string> SupportedProperties { get; set; }
}
private string GetServiceMetadataKey()
{
return MetadataKey + _metadataUri.OriginalString;
}
private static DataServiceMetadata GetDataServiceMetadata(Uri metadataUri)
{
if (metadataUri == null)
{
return null;
}
// Make a request to the metadata uri and get the schema
var client = new HttpClient(metadataUri);
using (MemoryStream stream = new MemoryStream())
{
client.DownloadData(stream);
stream.Seek(0, SeekOrigin.Begin);
return ExtractMetadataFromSchema(stream);
}
}
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "If the docuument is in fails to parse in any way, we want to not fail.")]
internal static DataServiceMetadata ExtractMetadataFromSchema(Stream schemaStream)
{
if (schemaStream == null)
{
return null;
}
XDocument schemaDocument;
try
{
schemaDocument = XmlUtility.LoadSafe(schemaStream);
}
catch
{
// If the schema is malformed (for some reason) then just return empty list
return null;
}
return ExtractMetadataInternal(schemaDocument);
}
private static DataServiceMetadata ExtractMetadataInternal(XDocument schemaDocument)
{
// Get all entity containers
var entityContainers = from e in schemaDocument.Descendants()
where e.Name.LocalName == "EntityContainer"
select e;
// Find the entity container with the Packages entity set
var result = (from e in entityContainers
let entitySet = e.Elements().FirstOrDefault(el => el.Name.LocalName == "EntitySet")
let name = entitySet != null ? entitySet.Attribute("Name").Value : null
where name != null && name.Equals("Packages", StringComparison.OrdinalIgnoreCase)
select new { Container = e, EntitySet = entitySet }).FirstOrDefault();
if (result == null)
{
return null;
}
var packageEntityContainer = result.Container;
var packageEntityTypeAttribute = result.EntitySet.Attribute("EntityType");
string packageEntityName = null;
if (packageEntityTypeAttribute != null)
{
packageEntityName = packageEntityTypeAttribute.Value;
}
var metadata = new DataServiceMetadata
{
SupportedMethodNames = new HashSet<string>(
from e in packageEntityContainer.Elements()
where e.Name.LocalName == "FunctionImport"
select e.Attribute("Name").Value, StringComparer.OrdinalIgnoreCase),
SupportedProperties = new HashSet<string>(ExtractSupportedProperties(schemaDocument, packageEntityName),
StringComparer.OrdinalIgnoreCase)
};
return metadata;
}
private static IEnumerable<string> ExtractSupportedProperties(XDocument schemaDocument, string packageEntityName)
{
// The name is listed in the entity set listing as <EntitySet Name="Packages" EntityType="Gallery.Infrastructure.FeedModels.PublishedPackage" />
// We need to extract the name portion to look up the entity type <EntityType Name="PublishedPackage"
packageEntityName = TrimNamespace(packageEntityName);
var packageEntity = (from e in schemaDocument.Descendants()
where e.Name.LocalName == "EntityType"
let attribute = e.Attribute("Name")
where attribute != null && attribute.Value.Equals(packageEntityName, StringComparison.OrdinalIgnoreCase)
select e).FirstOrDefault();
if (packageEntity != null)
{
return from e in packageEntity.Elements()
where e.Name.LocalName == "Property"
select e.Attribute("Name").Value;
}
return Enumerable.Empty<string>();
}
private static string TrimNamespace(string packageEntityName)
{
int lastIndex = packageEntityName.LastIndexOf('.');
if (lastIndex > 0 && lastIndex < packageEntityName.Length)
{
packageEntityName = packageEntityName.Substring(lastIndex + 1);
}
return packageEntityName;
}
}
}

View File

@@ -1,492 +0,0 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data.Services.Client;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq;
using System.Runtime.Versioning;
using System.Windows;
using MissingFrom.Net;
using NuGet.Resources;
namespace NuGet
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling")]
public class DataServicePackageRepository :
PackageRepositoryBase,
IHttpClientEvents,
IServiceBasedRepository,
ICloneableRepository,
ICultureAwareRepository,
IOperationAwareRepository,
IPackageLookup,
ILatestPackageLookup
{
private const string FindPackagesByIdSvcMethod = "FindPackagesById";
private const string PackageServiceEntitySetName = "Packages";
private const string SearchSvcMethod = "Search";
private const string GetUpdatesSvcMethod = "GetUpdates";
private IDataServiceContext _context;
private readonly IHttpClient _httpClient;
private readonly PackageDownloader _packageDownloader;
private CultureInfo _culture;
private Tuple<string, string, string> _currentOperation;
private event EventHandler<WebRequestEventArgs> _sendingRequest;
private WeakEventManager manager = new WeakEventManager();
public DataServicePackageRepository(Uri serviceRoot)
: this(new HttpClient(serviceRoot))
{
}
public DataServicePackageRepository(IHttpClient client)
: this(client, new PackageDownloader())
{
}
public DataServicePackageRepository(IHttpClient client, PackageDownloader packageDownloader)
{
if (client == null)
{
throw new ArgumentNullException("client");
}
if (packageDownloader == null)
{
throw new ArgumentNullException("packageDownloader");
}
_httpClient = client;
_httpClient.AcceptCompression = true;
_packageDownloader = packageDownloader;
if (EnvironmentUtility.RunningFromCommandLine || EnvironmentUtility.IsMonoRuntime)
{
_packageDownloader.SendingRequest += OnPackageDownloaderSendingRequest;
}
else
{
// weak event pattern
manager.AddWeakEventListener<PackageDownloader, WebRequestEventArgs>(
_packageDownloader,
nameof(_packageDownloader.SendingRequest),
OnPackageDownloaderSendingRequest);
}
}
private void OnPackageDownloaderSendingRequest(object sender, WebRequestEventArgs e)
{
// add headers for the metric service
if (_currentOperation != null)
{
string operation = _currentOperation.Item1;
string mainPackageId = _currentOperation.Item2;
string mainPackageVersion = _currentOperation.Item3;
if (!String.IsNullOrEmpty(mainPackageId) && !String.IsNullOrEmpty(_packageDownloader.CurrentDownloadPackageId))
{
if (!mainPackageId.Equals(_packageDownloader.CurrentDownloadPackageId, StringComparison.OrdinalIgnoreCase))
{
operation = operation + "-Dependency";
}
}
// add the id and version to the headers
if (!String.IsNullOrEmpty(_packageDownloader.CurrentDownloadPackageId) && !String.IsNullOrEmpty(_packageDownloader.CurrentDownloadPackageVersion))
{
e.Request.Headers[RepositoryOperationNames.PackageId] = _packageDownloader.CurrentDownloadPackageId;
e.Request.Headers[RepositoryOperationNames.PackageVersion] = _packageDownloader.CurrentDownloadPackageVersion;
}
e.Request.Headers[RepositoryOperationNames.OperationHeaderName] = operation;
if (!operation.Equals(_currentOperation.Item1, StringComparison.OrdinalIgnoreCase))
{
e.Request.Headers[RepositoryOperationNames.DependentPackageHeaderName] = mainPackageId;
if (!String.IsNullOrEmpty(mainPackageVersion))
{
e.Request.Headers[RepositoryOperationNames.DependentPackageVersionHeaderName] = mainPackageVersion;
}
}
RaiseSendingRequest(e);
}
}
// Just forward calls to the package downloader
public event EventHandler<ProgressEventArgs> ProgressAvailable
{
add
{
_packageDownloader.ProgressAvailable += value;
}
remove
{
_packageDownloader.ProgressAvailable -= value;
}
}
public event EventHandler<WebRequestEventArgs> SendingRequest
{
add
{
_packageDownloader.SendingRequest += value;
_httpClient.SendingRequest += value;
_sendingRequest += value;
}
remove
{
_packageDownloader.SendingRequest -= value;
_httpClient.SendingRequest -= value;
_sendingRequest -= value;
}
}
public CultureInfo Culture
{
get
{
if (_culture == null)
{
// TODO: Technically, if this is a remote server, we have to return the culture of the server
// instead of invariant culture. However, there is no trivial way to retrieve the server's culture,
// So temporarily use Invariant culture here.
_culture = _httpClient.Uri.IsLoopback ? CultureInfo.CurrentCulture : CultureInfo.InvariantCulture;
}
return _culture;
}
}
// Do NOT delete this property. It is used by the functional test.
public PackageDownloader PackageDownloader
{
get { return _packageDownloader; }
}
public override string Source
{
get
{
return _httpClient.Uri.OriginalString;
}
}
public override bool SupportsPrereleasePackages
{
get
{
return Context.SupportsProperty("IsAbsoluteLatestVersion");
}
}
// Don't initialize the Context at the constructor time so that
// we don't make a web request if we are not going to actually use it
// since getting the Uri property of the RedirectedHttpClient will
// trigger that functionality.
internal IDataServiceContext Context
{
private get
{
if (_context == null)
{
_context = new DataServiceContextWrapper(_httpClient.Uri);
_context.SendingRequest += OnSendingRequest;
_context.ReadingEntity += OnReadingEntity;
_context.IgnoreMissingProperties = true;
}
return _context;
}
set
{
_context = value;
}
}
private void OnReadingEntity(object sender, ReadingWritingEntityEventArgs e)
{
var package = (DataServicePackage)e.Entity;
var downloadUri = e.Data.Element(e.Data.Name.Namespace.GetName("content"))
.Attribute(System.Xml.Linq.XName.Get("src")).Value;
package.DownloadUrl = new Uri(downloadUri);
package.Downloader = _packageDownloader;
}
private void OnSendingRequest(object sender, SendingRequest2EventArgs e)
{
var shimRequest = new ShimDataRequestMessage(e);
// Initialize the request
_httpClient.InitializeRequest(shimRequest.WebRequest);
RaiseSendingRequest(new WebRequestEventArgs(shimRequest.WebRequest));
}
private void RaiseSendingRequest(WebRequestEventArgs e)
{
if (_sendingRequest != null)
{
_sendingRequest(this, e);
}
}
public override IQueryable<IPackage> GetPackages()
{
// REVIEW: Is it ok to assume that the package entity set is called packages?
return new SmartDataServiceQuery<DataServicePackage>(Context, PackageServiceEntitySetName);
}
public IQueryable<IPackage> Search(string searchTerm, IEnumerable<string> targetFrameworks, bool allowPrereleaseVersions, bool includeDelisted)
{
if (!Context.SupportsServiceMethod(SearchSvcMethod))
{
// If there's no search method then we can't filter by target framework
var q = GetPackages()
.Find(searchTerm)
.FilterByPrerelease(allowPrereleaseVersions);
// filter out delisted packages if includeDelisted is false.
if (includeDelisted == false)
{
q = q.Where(p => p.IsListed());
}
return q.AsQueryable();
}
// Create a '|' separated string of framework names
string targetFrameworkString = String.Join("|", targetFrameworks);
var searchParameters = new Dictionary<string, object> {
{ "searchTerm", "'" + UrlEncodeOdataParameter(searchTerm) + "'" },
{ "targetFramework", "'" + UrlEncodeOdataParameter(targetFrameworkString) + "'" },
};
if (SupportsPrereleasePackages)
{
searchParameters.Add("includePrerelease", ToLowerCaseString(allowPrereleaseVersions));
}
if (includeDelisted)
{
searchParameters.Add("includeDelisted", "true");
}
// Create a query for the search service method
var query = Context.CreateQuery<DataServicePackage>(SearchSvcMethod, searchParameters);
return new SmartDataServiceQuery<DataServicePackage>(Context, query);
}
public bool Exists(string packageId, SemanticVersion version)
{
IQueryable<DataServicePackage> query = Context.CreateQuery<DataServicePackage>(PackageServiceEntitySetName).AsQueryable();
foreach (string versionString in version.GetComparableVersionStrings())
{
try
{
var packages = query.Where(p => p.Id == packageId && p.Version == versionString)
.Select(p => p.Id) // since we only want to check for existence, no need to get all attributes
.ToArray();
if (packages.Length == 1)
{
return true;
}
}
catch (DataServiceQueryException)
{
// DataServiceQuery exception will occur when the (id, version)
// combination doesn't exist.
}
}
return false;
}
public IPackage FindPackage(string packageId, SemanticVersion version)
{
IQueryable<DataServicePackage> query = Context.CreateQuery<DataServicePackage>(PackageServiceEntitySetName).AsQueryable();
foreach (string versionString in version.GetComparableVersionStrings())
{
try
{
var packages = query.Where(p => p.Id == packageId && p.Version == versionString).ToArray();
Debug.Assert(packages == null || packages.Length <= 1);
if (packages.Length != 0)
{
return packages[0];
}
}
catch (DataServiceQueryException)
{
// DataServiceQuery exception will occur when the (id, version)
// combination doesn't exist.
}
}
return null;
}
public IEnumerable<IPackage> FindPackagesById(string packageId)
{
try
{
if (!Context.SupportsServiceMethod(FindPackagesByIdSvcMethod))
{
// If there's no search method then we can't filter by target framework
return PackageRepositoryExtensions.FindPackagesByIdCore(this, packageId);
}
var serviceParameters = new Dictionary<string, object> {
{ "id", "'" + UrlEncodeOdataParameter(packageId) + "'" }
};
// Create a query for the search service method
var query = Context.CreateQuery<DataServicePackage>(FindPackagesByIdSvcMethod, serviceParameters);
return new SmartDataServiceQuery<DataServicePackage>(Context, query);
}
catch (Exception ex)
{
var message = string.Format(
CultureInfo.CurrentCulture,
NuGetResources.ErrorLoadingPackages,
_httpClient.OriginalUri,
ex.Message);
throw new InvalidOperationException(message, ex);
}
}
public IEnumerable<IPackage> GetUpdates(
IEnumerable<IPackageName> packages,
bool includePrerelease,
bool includeAllVersions,
IEnumerable<FrameworkName> targetFrameworks,
IEnumerable<IVersionSpec> versionConstraints)
{
if (!Context.SupportsServiceMethod(GetUpdatesSvcMethod))
{
// If there's no search method then we can't filter by target framework
return PackageRepositoryExtensions.GetUpdatesCore(this, packages, includePrerelease, includeAllVersions, targetFrameworks, versionConstraints);
}
// Pipe all the things!
string ids = String.Join("|", packages.Select(p => p.Id));
string versions = String.Join("|", packages.Select(p => p.Version.ToString()));
string targetFrameworksValue = targetFrameworks.IsEmpty() ? "" : String.Join("|", targetFrameworks.Select(VersionUtility.GetShortFrameworkName));
string versionConstraintsValue = versionConstraints.IsEmpty() ? "" : String.Join("|", versionConstraints.Select(v => v == null ? "" : v.ToString()));
var serviceParameters = new Dictionary<string, object> {
{ "packageIds", "'" + ids + "'" },
{ "versions", "'" + versions + "'" },
{ "includePrerelease", ToLowerCaseString(includePrerelease) },
{ "includeAllVersions", ToLowerCaseString(includeAllVersions) },
{ "targetFrameworks", "'" + UrlEncodeOdataParameter(targetFrameworksValue) + "'" },
{ "versionConstraints", "'" + UrlEncodeOdataParameter(versionConstraintsValue) + "'" }
};
var query = Context.CreateQuery<DataServicePackage>(GetUpdatesSvcMethod, serviceParameters);
return new SmartDataServiceQuery<DataServicePackage>(Context, query);
}
public IPackageRepository Clone()
{
return new DataServicePackageRepository(_httpClient, _packageDownloader);
}
public IDisposable StartOperation(string operation, string mainPackageId, string mainPackageVersion)
{
Tuple<string, string, string> oldOperation = _currentOperation;
_currentOperation = Tuple.Create(operation, mainPackageId, mainPackageVersion);
return new DisposableAction(() =>
{
_currentOperation = oldOperation;
});
}
public bool TryFindLatestPackageById(string id, out SemanticVersion latestVersion)
{
latestVersion = null;
try
{
var serviceParameters = new Dictionary<string, object> {
{ "id", "'" + UrlEncodeOdataParameter(id) + "'" }
};
// Create a query for the search service method
var query = Context.CreateQuery<DataServicePackage>(FindPackagesByIdSvcMethod, serviceParameters);
var packages = (IQueryable<DataServicePackage>)query.AsQueryable();
var latestPackage = packages.Where(p => p.IsLatestVersion)
.Select(p => new { p.Id, p.Version })
.FirstOrDefault();
if (latestPackage != null)
{
latestVersion = new SemanticVersion(latestPackage.Version);
return true;
}
}
catch (DataServiceQueryException)
{
}
return false;
}
public bool TryFindLatestPackageById(string id, bool includePrerelease, out IPackage package)
{
try
{
var serviceParameters = new Dictionary<string, object> {
{ "id", "'" + UrlEncodeOdataParameter(id) + "'" }
};
// Create a query for the search service method
var query = Context.CreateQuery<DataServicePackage>(FindPackagesByIdSvcMethod, serviceParameters);
var packages = (IQueryable<DataServicePackage>)query.AsQueryable();
if (includePrerelease)
{
package = packages.Where(p => p.IsAbsoluteLatestVersion).OrderByDescending(p => p.Version).FirstOrDefault();
}
else
{
package = packages.Where(p => p.IsLatestVersion).OrderByDescending(p => p.Version).FirstOrDefault();
}
return package != null;
}
catch (DataServiceQueryException)
{
package = null;
return false;
}
}
private static string UrlEncodeOdataParameter(string value)
{
if (!String.IsNullOrEmpty(value))
{
// OData requires that a single quote MUST be escaped as 2 single quotes.
// In .NET 4.5, Uri.EscapeDataString() escapes single quote as %27. Thus we must replace %27 with 2 single quotes.
// In .NET 4.0, Uri.EscapeDataString() doesn't escape single quote. Thus we must replace it with 2 single quotes.
return Uri.EscapeDataString(value).Replace("'", "''").Replace("%27", "''");
}
return value;
}
[SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase", Justification = "OData expects a lower case value.")]
private static string ToLowerCaseString(bool value)
{
return value.ToString().ToLowerInvariant();
}
}
}

View File

@@ -1,177 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data.Services.Client;
using System.Globalization;
using System.Linq;
using System.Linq.Expressions;
using System.Xml.Linq;
using NuGet.Resources;
namespace NuGet
{
[CLSCompliant(false)]
public class DataServiceQueryWrapper<T> : IDataServiceQuery<T>
{
/// <remarks>
/// Corresponds to the default value of "maxQueryString" in system.webserver.
/// </remarks>
private const int MaxUrlLength = 2048;
private readonly DataServiceQuery _query;
private readonly IDataServiceContext _context;
private readonly Type _concreteType;
public DataServiceQueryWrapper(IDataServiceContext context, DataServiceQuery query)
: this(context, query, typeof(T))
{
}
public DataServiceQueryWrapper(IDataServiceContext context, DataServiceQuery query, Type concreteType)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
if (query == null)
{
throw new ArgumentNullException("query");
}
_context = context;
_query = query;
_concreteType = concreteType;
}
public bool RequiresBatch(Expression expression)
{
// Absolute uri returns the escaped url that would be sent to the server. Escaping exapnds the value and IIS uses this escaped query to determine if the
// query is of acceptable length.
string requestUri = GetRequestUri(expression).AbsoluteUri;
return requestUri.Length >= MaxUrlLength;
}
public DataServiceRequest GetRequest(Expression expression)
{
return (DataServiceRequest)_query.Provider.CreateQuery(GetInnerExpression(expression));
}
public virtual Uri GetRequestUri(Expression expression)
{
return GetRequest(expression).RequestUri;
}
public TResult Execute<TResult>(Expression expression)
{
return Execute(() => _query.Provider.Execute<TResult>(GetInnerExpression(expression)));
}
public object Execute(Expression expression)
{
return Execute(() => _query.Provider.Execute(GetInnerExpression(expression)));
}
public IDataServiceQuery<TElement> CreateQuery<TElement>(Expression expression)
{
expression = GetInnerExpression(expression);
var query = (DataServiceQuery)_query.Provider.CreateQuery<TElement>(expression);
return new DataServiceQueryWrapper<TElement>(_context, query, typeof(T));
}
public IQueryable<T> AsQueryable()
{
return (IQueryable<T>)_query;
}
public IEnumerator<T> GetEnumerator()
{
return GetAll().GetEnumerator();
}
private IEnumerable<T> GetAll()
{
throw new NotImplementedException();
//DataServiceQuery fixedQuery = _query;
//// Hack for WCF 5.6.1 to avoid using the interface
//if (typeof(T) == typeof(IPackage))
//{
// fixedQuery = (DataServiceQuery)_query.Provider.CreateQuery<DataServicePackage>(_query.Expression).Cast<DataServicePackage>();
//}
//IEnumerable results = Execute(fixedQuery.Execute);
//DataServiceQueryContinuation continuation;
//do
//{
// lock (_context)
// {
// foreach (T item in results)
// {
// yield return item;
// }
// }
// continuation = ((QueryOperationResponse)results).GetContinuation();
// if (continuation != null)
// {
// results = _context.Execute<T>(_concreteType, continuation);
// }
//} while (continuation != null);
}
private Expression GetInnerExpression(Expression expression)
{
return QueryableUtility.ReplaceQueryableExpression(_query, expression);
}
public override string ToString()
{
return _query.ToString();
}
private TResult Execute<TResult>(Func<TResult> action)
{
try
{
return action();
}
catch (Exception exception)
{
string message = ExtractMessageFromClientException(exception);
if (!String.IsNullOrEmpty(message))
{
throw new InvalidOperationException(message, exception);
}
throw new InvalidOperationException(
String.Format(CultureInfo.CurrentCulture,
NuGetResources.InvalidFeed,
_context.BaseUri), exception);
}
}
private static string ExtractMessageFromClientException(Exception exception)
{
var dataServiceQueryException = exception as DataServiceQueryException;
if (dataServiceQueryException != null && dataServiceQueryException.InnerException != null)
{
var dataServiceClientException = dataServiceQueryException.InnerException as DataServiceClientException;
XDocument document;
if (dataServiceQueryException != null &&
XmlUtility.TryParseDocument(dataServiceClientException.Message, out document) &&
document.Root.Name.LocalName.Equals("error", StringComparison.OrdinalIgnoreCase))
{
return document.Root.GetOptionalElementValue("message");
}
}
return null;
}
}
}

View File

@@ -1,282 +0,0 @@
using NuGet.Resources;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Security;
using System.Threading;
namespace NuGet
{
/// <summary>
/// The machine cache represents a location on the machine where packages are cached. It is a specific implementation of a local repository and can be used as such.
/// NOTE: this is a shared location, and as such all IO operations need to be properly serialized
/// </summary>
public class MachineCache : LocalPackageRepository, IPackageCacheRepository
{
/// <summary>
/// Maximum number of packages that can live in this cache.
/// </summary>
private const int MaxPackages = 200;
private const string NuGetCachePathEnvironmentVariable = "NuGetCachePath";
private static readonly Lazy<MachineCache> _instance = new Lazy<MachineCache>(() => CreateDefault(GetCachePath));
internal MachineCache(IFileSystem fileSystem)
: base(new DefaultPackagePathResolver(fileSystem), fileSystem, enableCaching: false)
{
}
public static MachineCache Default
{
get { return _instance.Value; }
}
/// <summary>
/// Creates a Machine Cache instance, assigns it to the instance variable and returns it.
/// </summary>
internal static MachineCache CreateDefault(Func<string> getCachePath)
{
IFileSystem fileSystem;
try
{
string path = getCachePath();
if (String.IsNullOrEmpty(path))
{
// If we don't get a path, use a null file system to make the cache object do nothing
// This can happen when there is no LocalApplicationData folder
fileSystem = NullFileSystem.Instance;
}
else
{
fileSystem = new PhysicalFileSystem(path);
}
}
catch (SecurityException)
{
// We are unable to access the special directory. Create a machine cache using an empty file system
fileSystem = NullFileSystem.Instance;
}
return new MachineCache(fileSystem);
}
public override void AddPackage(IPackage package)
{
// If we exceed the package count then clear the cache.
var files = GetPackageFiles().ToList();
if (files.Count >= MaxPackages)
{
// It's expensive to hit the file system to get the last accessed date for files
// To reduce this cost from occuring frequently, we'll purge packages in batches allowing for a 20% buffer.
var filesToDelete = files.OrderBy(FileSystem.GetLastAccessed)
.Take(files.Count - (int)(0.8 * MaxPackages))
.ToList();
TryClear(filesToDelete);
}
string path = GetPackageFilePath(package);
TryAct(() =>
{
// we want to do this in the TryAct, i.e. in the mutex
// for cases where package was added to cache by another process
if (FileSystem.FileExists(path))
{
return true;
}
string tmp = GetTempFile(path);
using (var stream = package.GetStream())
{
FileSystem.AddFile(tmp, stream);
}
FileSystem.MoveFile(tmp, path);
return true;
}, path);
}
// Unfortunately, there are many locations that query directly the filesystem to
// assess if a package is present in the cache instead of calling into MachineCache.Exists
// To guard against file in use issues, we create the cache entry with a tmp name and
// rename when the file is ready for consumption.
private static string GetTempFile(string filename)
{
return filename + ".tmp";
}
public override bool Exists(string packageId, SemanticVersion version)
{
string packagePath = GetPackageFilePath(packageId, version);
return TryAct(() => FileSystem.FileExists(packagePath), packagePath);
}
public bool InvokeOnPackage(string packageId, SemanticVersion version, Action<Stream> action)
{
if (FileSystem is NullFileSystem)
{
return false;
}
string packagePath = GetPackageFilePath(packageId, version);
return TryAct(() =>
{
string tmp = GetTempFile(packagePath);
using (var stream = FileSystem.CreateFile(tmp))
{
if (stream == null)
{
return false;
}
action(stream);
// After downloading a package, check if it is an empty package
// If so, do not store it in the machine cache
if (stream == null || stream.Length == 0)
{
return false;
}
}
// fix up the package name if the nuspec gives the version in a different format
// this allows versions to be normalized on the server while still supporting legacy formats for package restore
IPackage package = OpenPackage(FileSystem.GetFullPath(tmp));
// for legacy support the package name needs to match the nuspec
// Ex: owin.1.0.0.nupkg -> Owin.1.0.nupkg
packagePath = GetPackageFilePath(package.Id, package.Version);
FileSystem.DeleteFile(packagePath);
FileSystem.MoveFile(tmp, packagePath);
return true;
}, packagePath);
}
protected override IPackage OpenPackage(string path)
{
OptimizedZipPackage package;
try
{
package = new OptimizedZipPackage(FileSystem, path);
}
catch (FileFormatException ex)
{
throw new InvalidDataException(String.Format(CultureInfo.CurrentCulture, NuGetResources.ErrorReadingPackage, path), ex);
}
return package;
}
public void Clear()
{
TryClear(GetPackageFiles().ToList());
}
private void TryClear(IEnumerable<string> files)
{
foreach (var packageFile in files)
{
TryAct(() =>
{
FileSystem.DeleteFileSafe(packageFile);
return true;
}, packageFile);
}
}
protected override string GetPackageFilePath(IPackage package)
{
return Path.GetFileName(base.GetPackageFilePath(package));
}
protected override string GetPackageFilePath(string id, SemanticVersion version)
{
return Path.GetFileName(base.GetPackageFilePath(id, version));
}
/// <summary>
/// Determines the cache path to use for NuGet.exe. By default, NuGet caches files under %LocalAppData%\NuGet\Cache.
/// This path can be overridden by specifying a value in the NuGetCachePath environment variable.
/// </summary>
internal static string GetCachePath()
{
return GetCachePath(Environment.GetEnvironmentVariable, Environment.GetFolderPath);
}
internal static string GetCachePath(Func<string, string> getEnvironmentVariable, Func<System.Environment.SpecialFolder, string> getFolderPath)
{
string cacheOverride = getEnvironmentVariable(NuGetCachePathEnvironmentVariable);
if (!String.IsNullOrEmpty(cacheOverride))
{
return cacheOverride;
}
else
{
string localAppDataPath = getFolderPath(Environment.SpecialFolder.LocalApplicationData);
if (String.IsNullOrEmpty(localAppDataPath))
{
// there's a bug on Windows Azure Web Sites environment where calling through the Environment.GetFolderPath()
// will returns empty string, but the environment variable will return the correct value
localAppDataPath = getEnvironmentVariable("LocalAppData");
}
if (String.IsNullOrEmpty(localAppDataPath))
{
return null;
}
return Path.Combine(localAppDataPath, "NuGet", "Cache");
}
}
/// <remarks>
/// We use this method instead of the "safe" methods in FileSystem because it attempts to retry multiple times with delays.
/// In our case, if we are unable to perform IO over the machine cache, we want to quit trying immediately.
/// </remarks>
private bool TryAct(Func<bool> action, string path)
{
try
{
// Global: machine cache is per user across TS sessions
var mutexName = "Global\\" + EncryptionUtility.GenerateUniqueToken(FileSystem.GetFullPath(path) ?? path);
using (var mutex = new Mutex(false, mutexName))
{
bool owner = false;
try
{
try
{
owner = mutex.WaitOne(TimeSpan.FromMinutes(3));
// ideally we should throw an exception here if !owner such as
// throw new TimeoutException(string.Format("Timeout waiting for Machine Cache mutex for {0}", fullPath));
// we decided against it: machine cache operations being "best effort" basis.
// this may cause "File in use" exceptions for long lasting operations such as downloading a large package on
// a slow network connection
}
catch (AbandonedMutexException)
{
// TODO: consider logging a warning; abandonning a mutex is an indication something wrong is going on
owner = true; // now mine
}
return action();
}
finally
{
if (owner)
{
mutex.ReleaseMutex();
}
}
}
}
catch (IOException)
{
}
catch (UnauthorizedAccessException)
{
// Do nothing if this fails.
}
return false;
}
}
}

View File

@@ -1,44 +0,0 @@
using System;
namespace NuGet
{
public class PackageRepositoryFactory : IPackageRepositoryFactory
{
private static readonly PackageRepositoryFactory _default = new PackageRepositoryFactory();
private static readonly Func<Uri, IHttpClient> _defaultHttpClientFactory = u => new RedirectedHttpClient(u);
private Func<Uri, IHttpClient> _httpClientFactory;
public static PackageRepositoryFactory Default
{
get
{
return _default;
}
}
public Func<Uri, IHttpClient> HttpClientFactory
{
get { return _httpClientFactory ?? _defaultHttpClientFactory; }
set { _httpClientFactory = value; }
}
public virtual IPackageRepository CreateRepository(string packageSource)
{
if (packageSource == null)
{
throw new ArgumentNullException("packageSource");
}
Uri uri = new Uri(packageSource);
if (uri.IsFile)
{
return new LocalPackageRepository(uri.LocalPath);
}
var client = HttpClientFactory(uri);
// Make sure we get resolve any fwlinks before creating the repository
return new DataServicePackageRepository(client);
}
}
}

View File

@@ -1,328 +0,0 @@
using System;
using System.Globalization;
using System.IO;
using System.Net;
using NuGet.Resources;
namespace NuGet
{
public class PackageServer
{
private const string ServiceEndpoint = "/api/v2/package";
private const string ApiKeyHeader = "X-NuGet-ApiKey";
private const int MaxRediretionCount = 20;
private Lazy<Uri> _baseUri;
private readonly string _source;
private readonly string _userAgent;
public event EventHandler<WebRequestEventArgs> SendingRequest = delegate { };
public PackageServer(string source, string userAgent)
{
if (String.IsNullOrEmpty(source))
{
throw new ArgumentException(CommonResources.Argument_Cannot_Be_Null_Or_Empty, "source");
}
_source = source;
_userAgent = userAgent;
_baseUri = new Lazy<Uri>(ResolveBaseUrl);
}
public string Source
{
get { return _source; }
}
/// <summary>
/// Pushes a package to the Source.
/// </summary>
/// <param name="apiKey">API key to be used to push the package.</param>
/// <param name="package">The package to be pushed.</param>
/// <param name="timeout">Time in milliseconds to timeout the server request.</param>
/// <param name="disableBuffering">Indicates if HttpWebRequest buffering should be disabled.</param>
public void PushPackage(string apiKey, IPackage package, long packageSize, int timeout, bool disableBuffering)
{
var sourceUri = new Uri(Source);
if (sourceUri.IsFile)
{
PushPackageToFileSystem(
new PhysicalFileSystem(sourceUri.LocalPath),
package);
}
else
{
PushPackageToServer(apiKey, package.GetStream, packageSize, timeout, disableBuffering);
}
}
/// <summary>
/// Pushes a package to the server that is represented by the stream.
/// </summary>
/// <param name="apiKey">API key to be used to push the package.</param>
/// <param name="packageStreamFactory">A delegate which can be used to open a stream for the package file.</param>
/// <param name="contentLength">Size of the package to be pushed.</param>
/// <param name="timeout">Time in milliseconds to timeout the server request.</param>
/// <param name="disableBuffering">Disable buffering.</param>
private void PushPackageToServer(
string apiKey,
Func<Stream> packageStreamFactory,
long packageSize,
int timeout,
bool disableBuffering)
{
int redirectionCount = 0;
while (true)
{
HttpClient client = GetClient("", "PUT", "application/octet-stream");
client.DisableBuffering = disableBuffering;
client.SendingRequest += (sender, e) =>
{
SendingRequest(this, e);
var request = (HttpWebRequest)e.Request;
// Set the timeout
if (timeout <= 0)
{
timeout = request.ReadWriteTimeout; // Default to 5 minutes if the value is invalid.
}
request.Timeout = timeout;
request.ReadWriteTimeout = timeout;
if (!String.IsNullOrEmpty(apiKey))
{
request.Headers.Add(ApiKeyHeader, apiKey);
}
var multiPartRequest = new MultipartWebRequest();
multiPartRequest.AddFile(packageStreamFactory, "package", packageSize);
multiPartRequest.CreateMultipartRequest(request);
};
// When AllowWriteStreamBuffering is set to false, redirection will not be handled
// automatically by HttpWebRequest. So we need to check redirect status code and
// update _baseUri and retry if redirection happens.
if (EnsureSuccessfulResponse(client))
{
return;
}
++redirectionCount;
if (redirectionCount > MaxRediretionCount)
{
throw new WebException(NuGetResources.Error_TooManyRedirections);
}
}
}
/// <summary>
/// Pushes a package to a FileSystem.
/// </summary>
/// <param name="fileSystem">The FileSystem that the package is pushed to.</param>
/// <param name="package">The package to be pushed.</param>
private static void PushPackageToFileSystem(IFileSystem fileSystem, IPackage package)
{
var pathResolver = new DefaultPackagePathResolver(fileSystem);
var packageFileName = pathResolver.GetPackageFileName(package);
using (var stream = package.GetStream())
{
fileSystem.AddFile(packageFileName, stream);
}
}
/// <summary>
/// Deletes a package from the Source.
/// </summary>
/// <param name="apiKey">API key to be used to delete the package.</param>
/// <param name="packageId">The package Id.</param>
/// <param name="packageVersion">The package version.</param>
public void DeletePackage(string apiKey, string packageId, string packageVersion)
{
var sourceUri = new Uri(Source);
if (sourceUri.IsFile)
{
DeletePackageFromFileSystem(
new PhysicalFileSystem(sourceUri.LocalPath),
packageId,
packageVersion);
}
else
{
DeletePackageFromServer(apiKey, packageId, packageVersion);
}
}
/// <summary>
/// Deletes a package from the server represented by the Source.
/// </summary>
/// <param name="apiKey">API key to be used to delete the package.</param>
/// <param name="packageId">The package Id.</param>
/// <param name="packageVersion">The package Id.</param>
private void DeletePackageFromServer(string apiKey, string packageId, string packageVersion)
{
// Review: Do these values need to be encoded in any way?
var url = String.Join("/", packageId, packageVersion);
HttpClient client = GetClient(url, "DELETE", "text/html");
client.SendingRequest += (sender, e) =>
{
SendingRequest(this, e);
var request = (HttpWebRequest)e.Request;
request.Headers.Add(ApiKeyHeader, apiKey);
};
EnsureSuccessfulResponse(client);
}
/// <summary>
/// Deletes a package from a FileSystem.
/// </summary>
/// <param name="fileSystem">The FileSystem where the specified package is deleted.</param>
/// <param name="packageId">The package Id.</param>
/// <param name="packageVersion">The package Id.</param>
private static void DeletePackageFromFileSystem(IFileSystem fileSystem, string packageId, string packageVersion)
{
var pathResolver = new DefaultPackagePathResolver(fileSystem);
var packageFileName = pathResolver.GetPackageFileName(packageId, new SemanticVersion(packageVersion));
fileSystem.DeleteFile(packageFileName);
}
private HttpClient GetClient(string path, string method, string contentType)
{
var baseUrl = _baseUri.Value;
Uri requestUri = GetServiceEndpointUrl(baseUrl, path);
var client = new HttpClient(requestUri)
{
ContentType = contentType,
Method = method
};
if (!String.IsNullOrEmpty(_userAgent))
{
client.UserAgent = HttpUtility.CreateUserAgentString(_userAgent);
}
return client;
}
internal static Uri GetServiceEndpointUrl(Uri baseUrl, string path)
{
Uri requestUri;
if (String.IsNullOrEmpty(baseUrl.AbsolutePath.TrimStart('/')))
{
// If there's no host portion specified, append the url to the client.
requestUri = new Uri(baseUrl, ServiceEndpoint + '/' + path);
}
else
{
requestUri = new Uri(baseUrl, path);
}
return requestUri;
}
/// <summary>
/// Ensures that success response is received.
/// </summary>
/// <param name="client">The client that is making the request.</param>
/// <param name="expectedStatusCode">The exected status code.</param>
/// <returns>True if success response is received; false if redirection response is received.
/// In this case, _baseUri will be updated to be the new redirected Uri and the requrest
/// should be retried.</returns>
private bool EnsureSuccessfulResponse(HttpClient client, HttpStatusCode? expectedStatusCode = null)
{
HttpWebResponse response = null;
try
{
response = (HttpWebResponse)client.GetResponse();
if (response != null &&
((expectedStatusCode.HasValue && expectedStatusCode.Value != response.StatusCode) ||
// If expected status code isn't provided, just look for anything 400 (Client Errors) or higher (incl. 500-series, Server Errors)
// 100-series is protocol changes, 200-series is success, 300-series is redirect.
(!expectedStatusCode.HasValue && (int)response.StatusCode >= 400)))
{
throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, NuGetResources.PackageServerError, response.StatusDescription, String.Empty));
}
return true;
}
catch (WebException e)
{
if (e.Response == null)
{
throw;
}
response = (HttpWebResponse)e.Response;
// Check if the error is caused by redirection
if (response.StatusCode == HttpStatusCode.MultipleChoices ||
response.StatusCode == HttpStatusCode.MovedPermanently ||
response.StatusCode == HttpStatusCode.Found ||
response.StatusCode == HttpStatusCode.SeeOther ||
response.StatusCode == HttpStatusCode.TemporaryRedirect)
{
var location = response.Headers["Location"];
Uri newUri;
if (!Uri.TryCreate(client.Uri, location, out newUri))
{
throw;
}
_baseUri = new Lazy<Uri>(() => newUri);
return false;
}
if (expectedStatusCode != response.StatusCode)
{
throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, NuGetResources.PackageServerError, response.StatusDescription, e.Message), e);
}
return true;
}
finally
{
if (response != null)
{
response.Close();
response = null;
}
}
}
private Uri ResolveBaseUrl()
{
Uri uri;
try
{
var client = new RedirectedHttpClient(new Uri(Source));
uri = client.Uri;
}
catch (WebException ex)
{
var response = (HttpWebResponse)ex.Response;
if (response == null)
{
throw;
}
uri = response.ResponseUri;
}
return EnsureTrailingSlash(uri);
}
private static Uri EnsureTrailingSlash(Uri uri)
{
string value = uri.OriginalString;
if (!value.EndsWith("/", StringComparison.OrdinalIgnoreCase))
{
value += "/";
}
return new Uri(value);
}
}
}

View File

@@ -1,35 +0,0 @@
using System;
using System.Security.Cryptography;
using System.Text;
namespace NuGet
{
public static class EncryptionUtility
{
private static readonly byte[] _entropyBytes = Encoding.UTF8.GetBytes("NuGet");
internal static string EncryptString(string value)
{
var decryptedByteArray = Encoding.UTF8.GetBytes(value);
var encryptedByteArray = ProtectedData.Protect(decryptedByteArray, _entropyBytes, DataProtectionScope.CurrentUser);
var encryptedString = Convert.ToBase64String(encryptedByteArray);
return encryptedString;
}
internal static string DecryptString(string encryptedString)
{
var encryptedByteArray = Convert.FromBase64String(encryptedString);
var decryptedByteArray = ProtectedData.Unprotect(encryptedByteArray, _entropyBytes, DataProtectionScope.CurrentUser);
return Encoding.UTF8.GetString(decryptedByteArray);
}
public static string GenerateUniqueToken(string caseInsensitiveKey)
{
// SHA256 is case sensitive; given that our key is case insensitive, we upper case it
var pathBytes = Encoding.UTF8.GetBytes(caseInsensitiveKey.ToUpperInvariant());
var hashProvider = new CryptoHashProvider("SHA256");
return Convert.ToBase64String(hashProvider.CalculateHash(pathBytes)).ToUpperInvariant();
}
}
}

View File

@@ -1,88 +0,0 @@
using System;
using System.Globalization;
using System.IO;
using NuGet.Resources;
namespace NuGet
{
public class PackageDownloader : IHttpClientEvents
{
private const string DefaultUserAgentClient = "NuGet Core";
public event EventHandler<ProgressEventArgs> ProgressAvailable = delegate { };
public event EventHandler<WebRequestEventArgs> SendingRequest = delegate { };
public string CurrentDownloadPackageId
{
get;
private set;
}
public string CurrentDownloadPackageVersion
{
get;
private set;
}
public virtual void DownloadPackage(Uri uri, IPackageMetadata package, Stream targetStream)
{
if (uri == null)
{
throw new ArgumentNullException("uri");
}
var downloadClient = new HttpClient(uri)
{
UserAgent = HttpUtility.CreateUserAgentString(DefaultUserAgentClient)
};
DownloadPackage(downloadClient, package, targetStream);
}
public void DownloadPackage(IHttpClient downloadClient, IPackageName package, Stream targetStream)
{
if (downloadClient == null)
{
throw new ArgumentNullException("downloadClient");
}
if (targetStream == null)
{
throw new ArgumentNullException("targetStream");
}
// Get the operation display text
string operation = String.Format(CultureInfo.CurrentCulture, NuGetResources.DownloadProgressStatus, package.Id, package.Version);
CurrentDownloadPackageId = package.Id;
CurrentDownloadPackageVersion = package.Version.ToString();
EventHandler<ProgressEventArgs> progressAvailableHandler = (sender, e) =>
{
OnPackageDownloadProgress(new ProgressEventArgs(operation, e.PercentComplete));
};
try
{
downloadClient.ProgressAvailable += progressAvailableHandler;
downloadClient.SendingRequest += OnSendingRequest;
downloadClient.DownloadData(targetStream);
}
finally
{
downloadClient.ProgressAvailable -= progressAvailableHandler;
downloadClient.SendingRequest -= OnSendingRequest;
CurrentDownloadPackageId = null;
}
}
private void OnPackageDownloadProgress(ProgressEventArgs e)
{
ProgressAvailable(this, e);
}
private void OnSendingRequest(object sender, WebRequestEventArgs webRequestArgs)
{
SendingRequest(this, webRequestArgs);
}
}
}