Fix script scheduling when protocol is continuing indefinitely

--- SensusService/Probes/User/Scripts/ScriptRunner.cs
+++ SensusService/Probes/User/Scripts/ScriptRunner.cs
@@ -491,12 +491,15 @@
                 DateTime protocolStopTime = new DateTime(_probe.Protocol.EndDate.Year, _probe.Protocol.EndDate.Month, _probe.Protocol.EndDate.Day, _probe.Protocol.EndTime.Hours, _probe.Protocol.EndTime.Minutes, 0);

                 int dayOffset = 0;
-                int daysUntilProtocolStop = protocolStopTime.Subtract(DateTime.Now).Days + 2;
+
+                // if the protocol is scheduled to stop, set daysUntilProtocolStop.
+                // if it's not, use 32 days.
+                int daysUntilProtocolStop = _probe.Protocol.ScheduledToStop ?  protocolStopTime.Subtract(DateTime.Now).Days + 2 : 32;

                 int numTriggerWindows = _triggerWindows.Count;

                 // build a list of trigger window callbacks to schedule
-                while (dayOffset < daysUntilProtocolStop && dayOffset < 32 && triggerWindowsToSchedule.Count < (32 / _probe.ScriptRunners.Count))
+                while (dayOffset < daysUntilProtocolStop && triggerWindowsToSchedule.Count < (32 / _probe.ScriptRunners.Count))
                 {
                     foreach (Tuple<DateTime, DateTime, DateTime?> triggerWindow in _triggerWindows)
                     {


GH-28 Use encrypted # in the feed tag URI

--- R7.News/Feeds/AtomFeed.cs
+++ R7.News/Feeds/AtomFeed.cs
@@ -49,7 +49,8 @@
             writer.WriteElementString ("name", portalSettings.PortalName);
             writer.WriteEndElement ();

-            writer.WriteElementString ("id", $"tag:{portalSettings.PortalAlias.HTTPAlias},{authorityDate}:stream#{module.TabModuleID}");
+            writer.WriteElementString ("id", $"tag:{portalSettings.PortalAlias.HTTPAlias},{authorityDate}:feed#"
+                + UrlUtils.EncryptParameter ($"{module.TabID}-{module.ModuleID}"));

             writer.WriteStartElement ("link");
             writer.WriteAttributeString ("rel", "self");


changes to ScriptRunner

changes to ScriptRunner

--- SensusService/Probes/User/Scripts/ScriptRunner.cs
+++ SensusService/Probes/User/Scripts/ScriptRunner.cs
@@ -31,13 +31,22 @@
     {
         #region private classes

-        private class TriggerWindow
-        {
+        private struct TriggerWindow: IComparable<TriggerWindow>
+        {
+            #region Static Methods
+            public static TriggerWindow Parse(string value)
+            {
+                return new TriggerWindow(value);
+            }
+            #endregion
+
+            #region Properties
             public DateTime Start { get; set; }
             public DateTime End { get; set; }
             public DateTime? MostRecentRun { get; set; }
-
-            public TriggerWindow() { }
+            #endregion
+
+            #region Constructors

             public TriggerWindow(TriggerWindow window)
             {
@@ -46,6 +55,22 @@
                 MostRecentRun = window.MostRecentRun;
             }

+            public TriggerWindow(string window)
+            {
+                string[] startEnd = window.Trim().Split('-');
+
+                Start = DateTime.Parse(startEnd[0].Trim());
+                End   = startEnd.Length == 1 ? Start : DateTime.Parse(startEnd[1].Trim());
+                MostRecentRun = null;
+
+                if (Start > End)
+                {
+                    throw new Exception($"Improper trigger window ({window})");
+                }
+            }
+            #endregion
+
+            #region Public Methods
             public DateTime CreateTriggerTime()
             {
                 var length    = (End - Start).TotalSeconds;
@@ -68,6 +93,34 @@
             {
                 return !(MostRecentRun.HasValue) || MostRecentRun.Value.Date < DateTime.Now.Date;
             }
+
+            public override string ToString()
+            {
+                return Start == End ? HourMinute(Start.TimeOfDay) : $"{HourMinute(Start.TimeOfDay)}-{HourMinute(End.TimeOfDay)}";
+            }
+
+            public int CompareTo(TriggerWindow compare)
+            {
+                int hourComparison = Start.Hour.CompareTo(compare.Start.Hour);
+
+                if (hourComparison != 0)
+                {
+                    return hourComparison;
+                }
+                else
+                {
+                    return Start.Minute.CompareTo(compare.Start.Minute);
+                }
+
+            }
+            #endregion
+
+            #region Private Methods
+            private string HourMinute(TimeSpan time)
+            {
+                return $"{time.Hours}:{time.Minutes.ToString().PadLeft(2, '0')}";
+            }
+            #endregion
         }

         #endregion
@@ -177,61 +230,42 @@
         {
             get
             {
-                if (_triggerWindows.Count == 0)
-                    return "";
-                else
-                    return string.Concat(_triggerWindows.Select((window, index) => (index == 0 ? "" : ", ") +
-                            (
-                                window.Start == window.End ? window.Start.Hour + ":" + window.Start.Minute.ToString().PadLeft(2, '0') :
-                                window.Start.Hour + ":" + window.Start.Minute.ToString().PadLeft(2, '0') + "-" + window.End.Hour + ":" + window.End.Minute.ToString().PadLeft(2, '0')
-                            )));
-            }
-            set
-            {
-                if (value == TriggerWindows)
-                    return;
-
-                _triggerWindows.Clear();
-
-                try
-                {
-                    foreach (string window in value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
-                    {
-                        string[] startEnd = window.Trim().Split('-');
-
-                        DateTime start = DateTime.Parse(startEnd[0].Trim());
-                        DateTime end = start;
-
-                        if (startEnd.Length > 1)
-                        {
-                            end = DateTime.Parse(startEnd[1].Trim());
-
-                            if (start > end)
-                                throw new Exception();
-                        }
-
-                        _triggerWindows.Add(new TriggerWindow { Start = start, End = end, MostRecentRun = null });
-                    }
-                }
-                catch (Exception)
-                {
-                }
-
-                // sort windows by increasing hour and minute of the window start (day, month, and year are irrelevant)
-                _triggerWindows.Sort((window1, window2) =>
-                {
-                    int hourComparison = window1.Start.Hour.CompareTo(window2.Start.Hour);
-
-                    if (hourComparison != 0)
-                        return hourComparison;
-                    else
-                        return window1.Start.Minute.CompareTo(window2.Start.Minute);
-                });
-
-                if (_probe != null && _probe.Running && _enabled && _triggerWindows.Count > 0)  // probe can be null during deserialization if this property is set first
+                lock(_triggerWindows)
+                {
+                    return string.Join(", ", _triggerWindows.Select(w => w.ToString()));
+                }
+            }
+            set
+            {
+                if (value == TriggerWindows) return;
+
+                lock(_triggerWindows)
+                {
+                    _triggerWindows.Clear();
+
+                    try
+                    {
+                        _triggerWindows.AddRange(value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(TriggerWindow.Parse));
+                    }
+                    catch
+                    {
+                        //ignore improperly formatted trigger windows
+                    }
+
+                    // sort windows by increasing hour and minute of the window start (day, month, and year are irrelevant)
+                    _triggerWindows.Sort();
+                }
+                // probe can be null during deserialization if this property is set first
+                if (_probe != null && _probe.Running && _enabled && _triggerWindows.Count > 0)
+                {
                     StartTriggerCallbacksAsync();
-                else if (SensusServiceHelper.Get() != null)  // service helper can be null when deserializing
+                }
+
+                // service helper can be null when deserializing
+                else if (SensusServiceHelper.Get() != null)
+                {
                     StopRandomTriggerCallbackAsync();
+                }
             }
         }

@@ -469,9 +503,11 @@
                     // Replace the element of _triggerWindows with start/end that match the current triggerWindow, setting
                     // the last-fired time to DateTime.Now.Date. make sure to lock _triggerWindows prior to iterating. also, prevent
                     // user from entering the same window twice (in setter).
-                    int replaceIndex = _triggerWindows.FindIndex(window => window.Start == triggerWindow.Start && window.End == triggerWindow.End);
-
-                    _triggerWindows[replaceIndex] = new TriggerWindow(triggerWindow) { MostRecentRun = DateTime.Now };
+                    lock(_triggerWindows)
+                    {
+                        int replaceIndex = _triggerWindows.FindIndex(window => window.Start.TimeOfDay == triggerWindow.Start.TimeOfDay && window.End.TimeOfDay == triggerWindow.End.TimeOfDay);
+                        _triggerWindows[replaceIndex] = new TriggerWindow(triggerWindow) { MostRecentRun = DateTime.Now };
+                    }

                     // attach run time to script so we can measure age
                     scriptCopyToRun.RunTimestamp = triggerTime;
@@ -557,39 +593,42 @@

         private IEnumerable<TriggerWindow> FindTriggerCallbacksByDay(int dayIndex, int dayIndexMax, DateTime protocolStop)
         {
-            foreach (TriggerWindow triggerWindow in _triggerWindows)
-            {
-                TriggerWindow window = new TriggerWindow
-                {
-                    Start = triggerWindow.Start.AddDays(dayIndex),
-                    End = triggerWindow.End.AddDays(dayIndex),
-                    MostRecentRun = triggerWindow.MostRecentRun
-                };
-
-                // skip already scheduled scripts
-                if (_mostRecentTriggerWindowCallback != null && window.End <= _triggerWindowCallbacks[_mostRecentTriggerWindowCallback].Item2)
-                {
-                    continue;
-                }
-
-                if (dayIndex == 0 && window.StartsLater())
-                {
-                    yield return window;
-                }
-
-                else if (dayIndex == 0 && window.EndsLater() && window.HasNotRunToday())
-                {
-                    yield return new TriggerWindow(window) { Start = DateTime.Now };
-                }
-
-                else if (0 < dayIndex && dayIndex + 1 < dayIndexMax)
-                {
-                    yield return window;
-                }
-
-                else if (window.Start.AddMinutes(5) <= protocolStop)
-                {
-                    yield return window;
+            lock(_triggerWindows)
+            {
+                foreach (TriggerWindow triggerWindow in _triggerWindows)
+                {
+                    TriggerWindow window = new TriggerWindow
+                    {
+                        Start = triggerWindow.Start.AddDays(dayIndex),
+                        End = triggerWindow.End.AddDays(dayIndex),
+                        MostRecentRun = triggerWindow.MostRecentRun
+                    };
+
+                    // skip already scheduled scripts
+                    if (_mostRecentTriggerWindowCallback != null && window.End <= _triggerWindowCallbacks[_mostRecentTriggerWindowCallback].Item2)
+                    {
+                        continue;
+                    }
+
+                    if (dayIndex == 0 && window.StartsLater())
+                    {
+                        yield return window;
+                    }
+
+                    else if (dayIndex == 0 && window.EndsLater() && window.HasNotRunToday())
+                    {
+                        yield return new TriggerWindow(window) { Start = DateTime.Now };
+                    }
+
+                    else if (0 < dayIndex && dayIndex + 1 < dayIndexMax)
+                    {
+                        yield return window;
+                    }
+
+                    else if (window.Start.AddMinutes(5) <= protocolStop)
+                    {
+                        yield return window;
+                    }
                 }
             }
         }


XmlRpcManager: getXMLRPCClient: "Sever the head or destroy the brain" (explicitly dispose of zombie CachedXmlRpcClients)

--- ROS_Comm/XmlRpcManager.cs
+++ ROS_Comm/XmlRpcManager.cs
@@ -178,7 +178,7 @@
                             client.client.Shutdown();
                             zombies.Add(client);
                         }
-                        else if (client.client.CheckIdentity(host, port, uri)) //client.client.Host == host && client.client.Port == port && client.client.Uri == uri)
+                        else if (client.client.CheckIdentity(host, port, uri))
                         {
                             c = client.client;
                             client.in_use = true;
@@ -187,8 +187,11 @@
                         }
                     }
                 }
-                zombies.Add(null);
-                clients = clients.Except(zombies).ToList();
+                foreach (CachedXmlRpcClient C in zombies)
+                {
+                    clients.Remove(C);
+                    C.client.Dispose();
+                }
                 if (c == null)
                 {
                     c = new XmlRpcClient(host, port, uri);


add sunken track, fix little dictionary bug

--- Initializer.cs
+++ Initializer.cs
@@ -76,11 +76,25 @@
                 if (tunnelPrefab != null)
                 {
                     SetupTunnelPrefab(tunnelPrefab, originalPrefab, elevatedPrefab);
-                    m_customPrefabs.Add(stationTrackTunnel, elevatedPrefab);
+                    m_customPrefabs.Add(stationTrackTunnel, tunnelPrefab);
                 }
                 else
                 {
                     Debug.LogError("ElevatedTrainStationTrack - Couldn't make tunnel prefab");
+                }
+            }
+            var stationTrackSunken = "Station Track Sunken";
+            if (!m_customPrefabs.ContainsKey(stationTrackSunken))
+            {
+                var sunkenPrefab = ClonePrefab(originalPrefab, stationTrackSunken);
+                if (sunkenPrefab != null)
+                {
+                    SetupSunkenPrefab(sunkenPrefab, originalPrefab);
+                    m_customPrefabs.Add(stationTrackSunken, sunkenPrefab);
+                }
+                else
+                {
+                    Debug.LogError("ElevatedTrainStationTrack - Couldn't make sunken prefab");
                 }
             }
         }
@@ -184,6 +198,41 @@
             }
         }

+        private static void SetupSunkenPrefab(NetInfo sunkenPrefab, NetInfo originalPrefab)
+        {
+            var stationAI = sunkenPrefab.GetComponent<TrainTrackAI>();
+            DestroyImmediate(stationAI);
+
+            var tunnelAI = sunkenPrefab.gameObject.AddComponent<TrainTrackTunnelAI>();
+            sunkenPrefab.m_netAI = tunnelAI;
+            tunnelAI.m_outsideConnection = originalPrefab.GetComponent<TrainTrackAI>().m_outsideConnection;
+            tunnelAI.m_constructionCost = 0;
+            tunnelAI.m_maintenanceCost = 0;
+            tunnelAI.m_info = sunkenPrefab;
+
+            sunkenPrefab.m_clipTerrain = false;
+
+            sunkenPrefab.m_createGravel = false;
+            sunkenPrefab.m_createPavement = false;
+            sunkenPrefab.m_createRuining = false;
+
+            sunkenPrefab.m_flattenTerrain = false;
+            sunkenPrefab.m_followTerrain = false;
+
+            sunkenPrefab.m_intersectClass = null;
+
+            sunkenPrefab.m_maxHeight = -1;
+            sunkenPrefab.m_minHeight = -3;
+
+            sunkenPrefab.m_requireSurfaceMaps = false;
+            sunkenPrefab.m_snapBuildingNodes = false;
+
+            sunkenPrefab.m_placementStyle = ItemClass.Placement.Procedural;
+            sunkenPrefab.m_useFixedHeight = true;
+            sunkenPrefab.m_lowerTerrain = false;
+            sunkenPrefab.m_availableIn = ItemClass.Availability.GameAndAsset;
+        }
+
         NetInfo ClonePrefab(NetInfo originalPrefab, string newName)
         {
             var instance = Instantiate(originalPrefab.gameObject);


Mark CheckoutService as obsolete

Mark CheckoutService as obsolete

The endpoints used in this service don't seem to be documented anywhere. Instead there are two endpoints at /checkout.json for counting/listing abandoned checkouts. A new AbandonedCheckoutService is being created for those endpoints.

--- ShopifySharp/Services/Checkout/CheckoutService.cs
+++ ShopifySharp/Services/Checkout/CheckoutService.cs
@@ -1,6 +1,4 @@
-using Newtonsoft.Json.Linq;
-using System.Net.Http;
-using ShopifySharp.Filters;
+using System.Net.Http;
 using System.Collections.Generic;
 using System.Threading.Tasks;
 using ShopifySharp.Infrastructure;
@@ -11,6 +9,7 @@
     /// <summary>
     /// A service for manipulating Shopify checkouts.
     /// </summary>
+    [Obsolete("The endpoints and methods on this service no longer appear to be documented by Shopify. It may be removed in a future version of ShopifySharp.")]
     public class CheckoutService : ShopifyService
     {
         /// <param name="myShopifyUrl">The shop's *.myshopify.com URL.</param>


fix incorrect solved conflict

fix incorrect solved conflict

--- Signum.Engine/DynamicQuery/ExpressionContainer.cs
+++ Signum.Engine/DynamicQuery/ExpressionContainer.cs
@@ -86,7 +86,7 @@
                });

             IEnumerable<QueryToken> extensionsTokens = dic == null ? Enumerable.Empty<QueryToken>() :
-                dic.Values.Where(ei => ei.Inherit || ei.SourceType == parentType)
+                dic.Values.Where(ei => ei.Inherit || compatibleTypes.Contains(ei.SourceType))
                 .Where(ei => ei.IsApplicable == null || ei.IsApplicable(parent))
                 .Select(v => v.CreateToken(parent));


(TFS CS 5664)

(TFS CS 5664)

--- Signum.Entities.Extensions/Basics/HourMinuteDN.cs
+++ Signum.Entities.Extensions/Basics/HourMinuteDN.cs
@@ -33,9 +33,11 @@
             return new TimeSpan(hour, minute, 0);
         }

+        static Expression<Func<HourMinuteDN, string>> ToStringExpression =
+            h => "{0:00}:{1:00}".Formato(h.Hour, h.Minute);
         public override string ToString()
         {
-            return ToTimeSpan().ToString();
+            return ToStringExpression.Invoke(this);
         }
     }
 }


Add robustness to the closing phase.

Add robustness to the closing phase.

--- src/src_standalone_launcher/StandaloneAdaptersLauncher.cs
+++ src/src_standalone_launcher/StandaloneAdaptersLauncher.cs
@@ -283,8 +283,18 @@

         public bool handleIOException(Exception exception)
         {
-            _log.Error("Connection to Lightstreamer Server closed");
-            _closed = true;
+            lock (this)
+            {
+                if (_closed)
+                {
+                    return false;
+                }
+                else
+                {
+                    _log.Error("Connection to Lightstreamer Server closed");
+                    _closed = true;
+                }
+            }
             _server.Close();
             System.Environment.Exit(0);
             return false;
@@ -292,12 +302,20 @@

         public bool handleException(Exception exception)
         {
-            if (!_closed)
-            {
-                _log.Error("Caught exception: " + exception.Message, exception);
-                _server.Close();
-                System.Environment.Exit(1);
-            }
+            lock (this)
+            {
+                if (_closed)
+                {
+                    return false;
+                }
+                else
+                {
+                    _log.Error("Caught exception: " + exception.Message, exception);
+                    _closed = true;
+                }
+            }
+            _server.Close();
+            System.Environment.Exit(1);
             return false;
         }


Update XMLTool.cs

Update XMLTool.cs

--- RecuperadorXml/XMLTool.cs
+++ RecuperadorXml/XMLTool.cs
@@ -57,7 +57,7 @@
                             }
                             else
                             {
-                                xNome = nomeF.Substring(0, 6).ToLower();
+                                xNome = nomeF.Substring(0, 6).ToLower().Trim();
                             }
                         }

@@ -67,7 +67,7 @@
                             NF = nota["nNF"].InnerText;
                         }

-                        File.Move(xmls, "C:\\asatransf\\" + xNome.Trim() + "" + NF + ".xml");
+                        File.Move(xmls, "C:\\asatransf\\" + xNome + "" + NF + ".xml");
                         tratado = true;
                 }
             }


A spot of polygon to svg debugging code.

--- utils/PolygonHelper.cs
+++ utils/PolygonHelper.cs
@@ -20,6 +20,7 @@

 using System;
 using System.Collections.Generic;
+using System.IO;
 using System.Diagnostics;

 using MatterSlice.ClipperLib;
@@ -176,6 +177,56 @@
             return output;
         }

+        public static void SaveToSvg(this Polygons polygons, string filename)
+        {
+            double scaleDenominator = 150;
+            IntRect bounds = Clipper.GetBounds(polygons);
+            IntPoint size = new IntPoint(bounds.right - bounds.left, bounds.top - bounds.bottom);
+            double scale = Math.Max(size.X, size.Y) / scaleDenominator;
+            StreamWriter stream = new StreamWriter(filename);
+            stream.Write("<!DOCTYPE html>\n");
+            stream.Write("<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" style='width:%ipx;height:%ipx'>\n", (int)(size.X / scale), (int)(size.Y / scale));
+            stream.Write("<marker id='MidMarker' viewBox='0 0 10 10' refX='5' refY='5' markerUnits='strokeWidth' markerWidth='10' markerHeight='10' stroke='lightblue' stroke-width='2' fill='none' orient='auto'>");
+            stream.Write("<path d='M 0 0 L 10 5 M 0 10 L 10 5'/>");
+            stream.Write("</marker>");
+            stream.Write("<g fill-rule='evenodd' style=\"fill: gray; stroke:black;stroke-width:1\">\n");
+            stream.Write("<path marker-mid='url(#MidMarker)' d=\"");
+            for (int polygonIndex = 0; polygonIndex < polygons.Count; polygonIndex++)
+            {
+                Polygon polygon = polygons[polygonIndex];
+                for (int intPointIndex = 0; intPointIndex < polygon.Count; intPointIndex++)
+                {
+                    if (intPointIndex == 0)
+                    {
+                        stream.Write("M");
+                    }
+                    else
+                    {
+                        stream.Write("L");
+                    }
+                    stream.Write("{0},{1} ", (double)(polygon[intPointIndex].X - bounds.left) / scale, (double)(polygon[intPointIndex].Y - bounds.bottom) / scale);
+                }
+                stream.Write("Z\n");
+            }
+            stream.Write("\"/>");
+            stream.Write("</g>\n");
+            for (int openPolygonIndex = 0; openPolygonIndex < polygons.Count; openPolygonIndex++)
+            {
+                Polygon openPolygon = polygons[openPolygonIndex];
+                if (openPolygon.Count < 1) continue;
+                stream.Write("<polyline marker-mid='url(#MidMarker)' points=\"");
+                for (int n = 0; n < openPolygon.Count; n++)
+                {
+                    stream.Write("{0},{1} ", (double)(openPolygon[n].X - bounds.left) / scale, (double)(openPolygon[n].Y - bounds.bottom) / scale);
+                }
+                stream.Write("\" style=\"fill: none; stroke:red;stroke-width:1\" />\n");
+            }
+            stream.Write("</svg>\n");
+
+            stream.Write("");
+            stream.Close();
+        }
+
         public static void AddAll(this Polygons polygons, Polygons other)
         {
             for (int n = 0; n < other.Count; n++)


Accessing an accessible drive (#29010)

Accessing an accessible drive (#29010)

--- src/System.IO.FileSystem/tests/Directory/Exists.cs
+++ src/System.IO.FileSystem/tests/Directory/Exists.cs
@@ -375,12 +375,16 @@
             Assert.False(result);
         }

+        // Not all drives may be accessible (locked, no rights, etc.), and as such would return false.
+        // eg. Create a new volume, bitlocker it, and lock it. This new volume is no longer accessible
+        // and any attempt to access this drive will return false.
+        // We just care that we can access an accessible drive directly, we don't care which one.
         [Fact]
         [PlatformSpecific(TestPlatforms.Windows)] // drive labels
         public void DriveAsPath()
         {
             Assert.False(Exists(IOServices.GetNonExistentDrive()));
-            Assert.All(IOServices.GetReadyDrives(), drive => Assert.True(Exists(drive)));
+            Assert.Contains(IOServices.GetReadyDrives(), drive => Exists(drive));
         }

         [ConditionalFact(nameof(UsingNewNormalization))]
@@ -388,7 +392,7 @@
         public void ExtendedDriveAsPath()
         {
             Assert.False(Exists(IOInputs.ExtendedPrefix + IOServices.GetNonExistentDrive()));
-            Assert.All(IOServices.GetReadyDrives(), drive => Assert.True(Exists(IOInputs.ExtendedPrefix + drive)));
+            Assert.Contains(IOServices.GetReadyDrives(), drive => Exists(IOInputs.ExtendedPrefix + drive));
         }

         [Fact]


adds tests

adds tests

--- src/Umbraco.Tests/Models/ContentExtensionsTests.cs
+++ src/Umbraco.Tests/Models/ContentExtensionsTests.cs
@@ -9,7 +9,37 @@
     [TestFixture]
     public class ContentExtensionsTests : BaseUmbracoConfigurationTest
     {
-
+
+        [Test]
+        public void Should_Persist_Values_When_Saving_After_Publishing_But_No_Data_Changed()
+        {
+            var contentType = MockedContentTypes.CreateTextpageContentType();
+            var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1);
+
+            content.ResetDirtyProperties(false);
+            content.ChangePublishedState(PublishedState.Published);
+            content.ResetDirtyProperties(false);
+
+            //no version will be created if no data is changed
+            content.Properties.First().Value = "hello world";
+
+            content.ChangePublishedState(PublishedState.Saved);
+            Assert.IsTrue(content.RequiresSaving());
+        }
+
+        [Test]
+        public void Should_Not_Persist_Values_When_Saving_After_Publishing_But_No_Data_Changed()
+        {
+            var contentType = MockedContentTypes.CreateTextpageContentType();
+            var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1);
+
+            content.ResetDirtyProperties(false);
+            content.ChangePublishedState(PublishedState.Published);
+            content.ResetDirtyProperties(false);
+
+            content.ChangePublishedState(PublishedState.Saved);
+            Assert.IsFalse(content.RequiresSaving());
+        }

         [Test]
         public void Should_Create_New_Version_When_Publishing()
@@ -32,6 +62,9 @@
             content.ResetDirtyProperties(false);
             content.ChangePublishedState(PublishedState.Published);
             content.ResetDirtyProperties(false);
+
+            //no version will be created if no data is changed
+            content.Properties.First().Value = "hello world";

             content.ChangePublishedState(PublishedState.Saved);
             Assert.IsTrue(content.ShouldCreateNewVersion());
@@ -83,7 +116,6 @@
             content.Properties.First().Value = "hello world";
             Assert.IsFalse(content.ShouldCreateNewVersion(PublishedState.Unpublished));
         }
-

         [Test]
         public void Should_Clear_Published_Flag_When_Newly_Published_Version()


updating unit tests.

updating unit tests.

--- src/Umbraco.Tests/Strings/StringExtensionsTests.cs
+++ src/Umbraco.Tests/Strings/StringExtensionsTests.cs
@@ -61,10 +61,10 @@
             Assert.AreEqual(stripped, result);
         }

-        [TestCase("'+alert(1234)+'", "alert1234")]
-        [TestCase("'+alert(56+78)+'", "alert5678")]
+        [TestCase("'+alert(1234)+'", "+alert1234+")]
+        [TestCase("'+alert(56+78)+'", "+alert56+78+")]
         [TestCase("{{file}}", "file")]
-        [TestCase("'+alert('hello')+'", "alerthello")]
+        [TestCase("'+alert('hello')+'", "+alerthello+")]
         [TestCase("Test", "Test")]
         public void Clean_From_XSS(string input, string result)
         {


Update MediaApp resolver with new aliases

--- src/Umbraco.Web/Models/Mapping/MediaAppResolver.cs
+++ src/Umbraco.Web/Models/Mapping/MediaAppResolver.cs
@@ -12,7 +12,7 @@
     {
         private static readonly ContentApp _contentApp = new ContentApp
         {
-            Alias = "content",
+            Alias = "umbContent",
             Name = "Content",
             Icon = "icon-document",
             View = "views/media/apps/content/content.html"
@@ -20,7 +20,7 @@

         private static readonly ContentApp _infoApp = new ContentApp
         {
-            Alias = "info",
+            Alias = "umbInfo",
             Name = "Info",
             Icon = "icon-info",
             View = "views/media/apps/info/info.html"


Disable warning about deprecated Live Share APIs

--- src/VisualStudio/LiveShare/Impl/ProjectsHandler.cs
+++ src/VisualStudio/LiveShare/Impl/ProjectsHandler.cs
@@ -28,12 +28,16 @@
                 foreach (var sourceFile in project.Documents)
                 {
                     var uri = new Uri(sourceFile.FilePath);
+#pragma warning disable 0612
                     if (!requestContext.ProtocolConverter.IsContainedInRootFolders(uri))
+#pragma warning restore 0612
                     {
                         externalUris.Add(uri);
                     }
                 }
+#pragma warning disable 0612
                 await requestContext.ProtocolConverter.RegisterExternalFilesAsync(externalUris.ToArrayAndFree()).ConfigureAwait(false);
+#pragma warning restore 0612

                 var lspProject = new CustomProtocol.Project
                 {


Disable UnsupportedTextType only on netcore

--- src/XMakeTasks/UnitTests/GenerateResource_Tests.cs
+++ src/XMakeTasks/UnitTests/GenerateResource_Tests.cs
@@ -1469,7 +1469,11 @@
         /// <summary>
         ///  Non-string resource with text output
         /// </summary>
+#if RUNTIME_TYPE_NETCORE
         [Fact (Skip = "https://github.com/Microsoft/msbuild/issues/308")]
+#else
+        [Fact]
+#endif
         public void UnsupportedTextType()
         {
             string bitmap = Utilities.CreateWorldsSmallestBitmap();


refs #1436 - Foutje gemaakt bij mergen. Foei.

--- Solution/Chiro.Gap.Services/GroepenService.svc.cs
+++ Solution/Chiro.Gap.Services/GroepenService.svc.cs
@@ -89,12 +89,11 @@
         /// <param name="groepsWerkJarenMgr">Businesslogica wat betreft groepswerkjaren</param>
         /// <param name="functiesMgr">Businesslogica aangaande functies</param>
         /// <param name="jaarOvergangMgr">Businesslogica aangaande de jaarovergang</param>
-        /// <param name="veelGebruikt">Cache voor veelgebruikte zaken</param>
         /// <param name="repositoryProvider">De repository provider levert alle nodige repository's op.</param>
         public GroepenService(IAfdelingsJaarManager afdelingsJaarMgr, IAuthenticatieManager authenticatieMgr, IAutorisatieManager autorisatieMgr,
                               IGroepenManager groepenMgr, IJaarOvergangManager jaarOvergangMgr,
                                 IChiroGroepenManager chiroGroepenMgr, IGroepsWerkJarenManager groepsWerkJarenMgr,
-                              IFunctiesManager functiesMgr, IVeelGebruikt veelGebruikt,
+                              IFunctiesManager functiesMgr,
                               IRepositoryProvider repositoryProvider, IGroepenSync groepenSync)
         {
             _straatRepo = repositoryProvider.RepositoryGet<StraatNaam>();
@@ -121,7 +120,6 @@
             _afdelingsJaarMgr = afdelingsJaarMgr;
             _authenticatieMgr = authenticatieMgr;
             _autorisatieMgr = autorisatieMgr;
-            _veelGebruikt = veelGebruikt;
             _groepenSync = groepenSync;
             _gav = new GavChecker(_autorisatieMgr);
         }
@@ -1053,14 +1051,6 @@

         #endregion

-
-        Groep GetGroepEnCheckGav(int groepId)
-        {
-            var groep = _groepenRepo.ByID(groepId);
-            Gav.Check(groep);
-            return groep;
-        }
-
         #region adresgegevens ophalen

         /// <summary>


Rename test.

Rename test.

--- src/EditorFeatures/CSharpTest/UseIndexOrRangeOperator/UseIndexOperatorTests.cs
+++ src/EditorFeatures/CSharpTest/UseIndexOrRangeOperator/UseIndexOperatorTests.cs
@@ -136,7 +136,7 @@
         }

         [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseIndexOperator)]
-        public async Task TestNotWithoutMultipleArgs()
+        public async Task TestNotWithMultipleArgs()
         {
             await TestMissingAsync(
 @"


Smaller scoped shade fix for CreateList items w/ Shade 0 (#3066)

--- Source/ACE.Server/Factories/WorldObjectFactory.cs
+++ Source/ACE.Server/Factories/WorldObjectFactory.cs
@@ -400,7 +400,7 @@
                 wo.PaletteTemplate = item.Palette;

             // if treasure, this is probability instead of shade
-            if (!isTreasure && item.Shade > 0)
+            if (!isTreasure)
                 wo.Shade = item.Shade;

             return wo;


Added connection string parameters to Downloader.cs to support active FTP.

--- Source/Applications/openMIC/openMIC/Downloader.cs
+++ Source/Applications/openMIC/openMIC/Downloader.cs
@@ -433,6 +433,54 @@
         }

         /// <summary>
+        /// Gets or sets mode of FTP connection.
+        /// </summary>
+        [ConnectionStringParameter,
+        Description("Defines mode of FTP connection."),
+        DefaultValue(true)]
+        public bool PassiveFtp
+        {
+            get;
+            set;
+        }
+
+        /// <summary>
+        /// Gets or sets mode of FTP connection.
+        /// </summary>
+        [ConnectionStringParameter,
+        Description("Defines IP address to send in FTP PORT command."),
+        DefaultValue("")]
+        public string ActiveFtpAddress
+        {
+            get;
+            set;
+        }
+
+        /// <summary>
+        /// Gets or sets mode of FTP connection.
+        /// </summary>
+        [ConnectionStringParameter,
+        Description("Defines minimum port in active FTP port range."),
+        DefaultValue(0)]
+        public int MinActiveFtpPort
+        {
+            get;
+            set;
+        }
+
+        /// <summary>
+        /// Gets or sets mode of FTP connection.
+        /// </summary>
+        [ConnectionStringParameter,
+        Description("Defines maximum port in active FTP port range."),
+        DefaultValue(0)]
+        public int MaxActiveFtpPort
+        {
+            get;
+            set;
+        }
+
+        /// <summary>
         /// Gets or sets flag that determines if connection messages should be logged.
         /// </summary>
         [ConnectionStringParameter,
@@ -968,6 +1016,10 @@
                         }

                         client.Timeout = ConnectionTimeout;
+                        client.Passive = PassiveFtp;
+                        client.ActiveAddress = ActiveFtpAddress;
+                        client.MinActivePort = MinActiveFtpPort;
+                        client.MaxActivePort = MaxActiveFtpPort;
                         client.Connect(ConnectionUserName, ConnectionPassword);
                         OnStatusMessage("Connected to FTP server \"{0}@{1}\"", ConnectionUserName, ConnectionHostName);
                     }


Add comment

Add comment

--- src/Features/Core/Portable/UnifiedSuggestions/UnifiedSuggestedActionsSource.cs
+++ src/Features/Core/Portable/UnifiedSuggestions/UnifiedSuggestedActionsSource.cs
@@ -41,6 +41,10 @@
         {
             // Intentionally switch to a threadpool thread to compute fixes.  We do not want to accidentally
             // run any of this on the UI thread and potentially allow any code to take a dependency on that.
+            //
+            // Only request suppression fixes if we're in the norma priority group.  The high priority group
+            // should not show them as that would cause them to appear higher than normal pri fixes and we
+            // always want these last.
             var fixes = await Task.Run(() => codeFixService.GetFixesAsync(
                 document,
                 selection,


fix warning in ButtonControl

fix warning in ButtonControl

--- Source/Code/EditorPlugin/Modules/ButtonControl.cs
+++ Source/Code/EditorPlugin/Modules/ButtonControl.cs
@@ -142,7 +142,7 @@
 				InputManager.SetButtonRiseTime (btnName, value);
 			}
 			catch (Exception) {
-				riseTimeTextBox.Text = InputManager.GetButton (btnName).RiseTime.ToString ();
+				riseTimeTextBox.Text = InputManager.GetButton (btnName).RiseTime.ToString ("G");
 			}
 		}
 	}


Update PartSelection.cs

Update PartSelection.cs

--- Source/PartSelection.cs
+++ Source/PartSelection.cs
@@ -12,7 +12,7 @@
         public Rect selection;
         public List<Part> selectedParts = new List<Part>();
         Vector2 mousePos = Input.mousePosition;
-
+
         public void Update(Vector2 mousePos)
         {
             if (Input.GetMouseButtonDown(0))
@@ -23,7 +23,7 @@
             else if (Input.GetMouseButtonUp(0))
             {
                 selectedParts.Clear();
-                foreach (Part part in EditorLogic.SortedShipList)
+                foreach (Part part in WernherChecker.VesselParts)
                 {
                     Vector3 origScreenPoint = EditorCamera.Instance.camera.WorldToScreenPoint(part.partTransform.position);
                     Vector3 correctedScreenPoint = new Vector3(origScreenPoint.x, Screen.height - origScreenPoint.y, origScreenPoint.z);
@@ -52,7 +52,7 @@
                 }

                 GUI.DrawTexture(selection, (Texture)GameDatabase.Instance.GetTexture("WernherChecker/Data/selection", false));
-                foreach (Part part in EditorLogic.SortedShipList)
+                foreach (Part part in WernherChecker.VesselParts)
                 {
                     Vector3 origScreenPoint = EditorCamera.Instance.camera.WorldToScreenPoint(part.partTransform.position);
                     Vector3 correctedScreenPoint = new Vector3(origScreenPoint.x, Screen.height - origScreenPoint.y, origScreenPoint.z);


support string transformer

support string transformer

--- src/FlowBasis/FlowBasisJsonUnitTests/Json/DefaultJObjectMapperProviderTests.cs
+++ src/FlowBasis/FlowBasisJsonUnitTests/Json/DefaultJObjectMapperProviderTests.cs
@@ -27,6 +27,30 @@
             // And it should be deserialized back into TestObject from a string.
             var result = jsonSerializer.Parse<TestObject>(json);
             Assert.AreEqual("Abc", result.SomeStr);
+        }
+
+
+        [TestMethod]
+        public void Test_StringInputTransform()
+        {
+            DefaultJObjectMapperProvider mapperProvider = new DefaultJObjectMapperProvider(
+                new DefaultJObjectMapperProviderOptions
+                {
+                    StringInputTransform = (str) =>
+                    {
+                        return "TRANSFORMED" + (str ?? "");
+                    }
+                });
+
+            var jsonSerializer = new JsonSerializationService(() => new JObjectRootMapper(mapperProvider));
+
+            // TestObject should get converted into reversed case string when serialized with custom mapper.
+            string json = jsonSerializer.Stringify(new TestObject() { SomeStr = "Abc" });
+            Assert.AreEqual("{\"someStr\":\"Abc\"}", json);
+
+            // And it should be deserialized back into TestObject from a string.
+            var result = jsonSerializer.Parse<TestObject>(json);
+            Assert.AreEqual("TRANSFORMEDAbc", result.SomeStr);
         }


ADDED: Line Segment - Finding intersection point of two line segments.

--- Source/GameMath/Intersections/LineIntersection.cs
+++ Source/GameMath/Intersections/LineIntersection.cs
@@ -54,6 +54,42 @@
         public static bool Intersects(this LineSegment2F line, CircleF circle)
         {
             return line.GetDistance(circle.Center) < circle.Radius;
+        }
+
+        /// <summary>
+        ///   Checks whether the specified line segment intersects the passed one.
+        /// </summary>
+        /// <param name="first">Line segment to check.</param>
+        /// <param name="second">Line segment to check.</param>
+        /// <param name="intersectionPoint">Intersection point, if found.</param>
+        /// <returns>
+        ///   <c>true</c>, if both line segments intersect each other, and <c>false</c> otherwise.
+        /// </returns>
+        public static bool Intersects(this LineSegment2F first, LineSegment2F second, out Vector2F intersectionPoint)
+        {
+            // http://www.wyrmtale.com/blog/2013/115/2d-line-intersection-in-c
+            // Get A,B,C of first line - points ps1 to pe1.
+            var a1 = first.Q.Y - first.P.Y;
+            var b1 = first.P.X - first.Q.X;
+            var c1 = a1 * first.P.X + b1 * first.P.Y;
+
+            // Get A,B,C of second line - points ps2 to pe2.
+            var a2 = second.Q.Y - second.P.Y;
+            var b2 = second.P.X - second.Q.X;
+            var c2 = a2 * second.P.X + b2 * second.P.Y;
+
+            // Get delta and check if the lines are parallel.
+            var delta = a1 * b2 - a2 * b1;
+
+            if (Math.Abs(delta) < float.Epsilon)
+            {
+                intersectionPoint = Vector2F.Zero;
+                return false;
+            }
+
+            // Return intersection point.
+            intersectionPoint = new Vector2F((b2 * c1 - b1 * c2) / delta, (a1 * c2 - a2 * c1) / delta);
+            return first.Contains(intersectionPoint) && second.Contains(intersectionPoint);
         }

         /// <summary>


Fixed some messages related to the betting pool not being sent. Using users' display name in the command logs and mod managing commands.

--- ModBot/Irc.cs
+++ ModBot/Irc.cs
@@ -693,7 +693,7 @@
                                         temp += "(" + (i + 1).ToString() + ") " + betOptions[i] + " ";
                                     }
                                     sendMessage(temp);
-                                    sendMessage("Bet by typing \"!bet 50 option1name\" to bet 50 " + currency + " on option 1, \"!bet 25 option2name\" to bet 25 on option 2, etc. You can also bet with \"!bet <amount> #OptionNumber\"");
+                                    sendMessage("Bet by typing \"!bet 50 option1name\" to bet 50 " + currency + " on option 1, \"!bet 25 option2name\" to bet 25 on option 2, etc. You can also bet with \"!bet 10 #OptionNumber\"");
                                 }
                                 else
                                 {
@@ -848,7 +848,7 @@
                                 temp += "(" + (i + 1).ToString() + ") " + betOptions[i] + " ";
                             }
                             sendMessage(temp);
-                            sendMessage("Bet by typing \"!bet 50 option1name\" to bet 50 " + currency + " on option 1, \"bet 25 option2name\" to bet 25 on option 2, etc. You can also bet with \"!bet <amount> #OptionNumber\"");
+                            sendMessage("Bet by typing \"!bet 50 option1name\" to bet 50 " + currency + " on option 1, \"bet 25 option2name\" to bet 25 on option 2, etc. You can also bet with \"!bet 10 #OptionNumber\".");
                         }
                     }
                     else if (int.TryParse(args[0], out betAmount) && args.Length >= 2 && bettingOpen && !poolLocked)
@@ -1039,22 +1039,22 @@
                     {
                         if (Database.addSub(args[1]))
                         {
-                            sendMessage(Api.capName(args[1]) + " added as a subscriber.");
+                            sendMessage(Api.GetDisplayName(args[1]) + " added as a subscriber.");
                         }
                         else
                         {
-                            sendMessage(Api.capName(args[1]) + " does not exist in the database. Have them type !<currency> then try again.");
+                            sendMessage(Api.GetDisplayName(args[1]) + " does not exist in the database. Have them type !<currency> then try again.");
                         }
                     }
                     if (args[0].Equals("removesub") && args.Length >= 2)
                     {
                         if (Database.removeSub(args[1]))
                         {
-                            sendMessage(Api.capName(args[1]) + " removed from subscribers.");
+                            sendMessage(Api.GetDisplayName(args[1]) + " removed from subscribers.");
                         }
                         else
                         {
-                            sendMessage(Api.capName(args[1]) + " does not exist in the database.");
+                            sendMessage(Api.GetDisplayName(args[1]) + " does not exist in the database.");
                         }
                     }
                 }
@@ -1062,13 +1062,13 @@
                 {
                     if (args[0].Equals("addmod") && args.Length >= 2)
                     {
-                        string tNick = Api.capName(args[1]);
+                        string tNick = Api.GetDisplayName(args[1]);
                         if (Database.userExists(tNick))
                         {
                             if (!tNick.Equals(admin, StringComparison.OrdinalIgnoreCase) && (Database.getUserLevel(tNick) < 3 && Database.getUserLevel(user) == 3 || Database.getUserLevel(user) >= 4))
                             {
                                 Database.setUserLevel(tNick, 1);
-                                sendMessage(tNick + " added as a bot moderator.", user + " added " + tNick + "as a bot moderator.");
+                                sendMessage(tNick + " added as a bot moderator.", Api.GetDisplayName(user) + " added " + tNick + "as a bot moderator.");
                             }
                             else
                             {
@@ -1082,13 +1082,13 @@
                     }
                     if (args[0].Equals("addsuper") && args.Length >= 2)
                     {
-                        string tNick = Api.capName(args[1]);
+                        string tNick = Api.GetDisplayName(args[1]);
                         if (Database.userExists(tNick))
                         {
                             if (!tNick.Equals(admin, StringComparison.OrdinalIgnoreCase) && (Database.getUserLevel(tNick) < 3 && Database.getUserLevel(user) == 3 || Database.getUserLevel(user) >= 4))
                             {
                                 Database.setUserLevel(tNick, 2);
-                                sendMessage(tNick + " added as a bot Super Mod.", user + " added " + tNick + "as a super bot moderator.");
+                                sendMessage(tNick + " added as a bot Super Mod.", Api.GetDisplayName(user) + " added " + tNick + "as a super bot moderator.");
                             }
                             else
                             {
@@ -1102,7 +1102,7 @@
                     }
                     if (args[0].Equals("demote") && args.Length >= 2)
                     {
-                        string tNick = Api.capName(args[1]);
+                        string tNick = Api.GetDisplayName(args[1]);
                         if (Database.userExists(tNick))
                         {
                             if (Database.getUserLevel(tNick) > 0)
@@ -1110,7 +1110,7 @@
                                 if (!tNick.Equals(admin, StringComparison.OrdinalIgnoreCase) && (Database.getUserLevel(tNick) < 3 && Database.getUserLevel(user) == 3 || Database.getUserLevel(user) >= 4))
                                 {
                                     Database.setUserLevel(tNick, Database.getUserLevel(tNick) - 1);
-                                    sendMessage(tNick + " demoted.", user + "demoted " + tNick);
+                                    sendMessage(tNick + " has been demoted.", Api.GetDisplayName(user) + "demoted " + tNick);
                                 }
                                 else
                                 {
@@ -1129,7 +1129,7 @@
                     }
                     if (args[0].Equals("setlevel") && args.Length >= 3)
                     {
-                        string tNick = Api.capName(args[1]);
+                        string tNick = Api.GetDisplayName(args[1]);
                         if (Database.userExists(tNick))
                         {
                             if (!tNick.Equals(admin, StringComparison.OrdinalIgnoreCase) && (Database.getUserLevel(tNick) < 3 && Database.getUserLevel(user) == 3 || Database.getUserLevel(user) >= 4))
@@ -1138,7 +1138,7 @@
                                 if (int.TryParse(args[2], out level) && level >= 0 && (level < 4 && Database.getUserLevel(user) >= 4 || level < 3))
                                 {
                                     Database.setUserLevel(tNick, level);
-                                    sendMessage(tNick + " set to Access Level " + level, user + "set " + tNick + "'s Access Level to " + level);
+                                    sendMessage(tNick + " set to Access Level " + level, Api.GetDisplayName(user) + "set " + tNick + "'s Access Level to " + level);
                                 }
                                 else sendMessage("Level must be greater than or equal to 0, and less than 3 (0>=Level<3)");
                             }
@@ -1166,7 +1166,7 @@
                                     output += args[i] + " ";
                                 }
                                 Commands.addCommand(command, level, output.Substring(0, output.Length - 1));
-                                sendMessage(command + " command added.", user + " added the command " + command);
+                                sendMessage(command + " command added.", Api.GetDisplayName(user) + " added the command " + command);
                             }
                             else
                             {
@@ -1184,7 +1184,7 @@
                         if (Commands.cmdExists(command))
                         {
                             Commands.removeCommand(command);
-                            sendMessage(command + " command removed.", user + " removed the command " + command);
+                            sendMessage(command + " command removed.", Api.GetDisplayName(user) + " removed the command " + command);
                         }
                         else
                         {


Makes Analyze Hotspots sample tolerant of bad dates

--- src/Forms/Shared/Samples/Geoprocessing/AnalyzeHotspots/AnalyzeHotspots.xaml.cs
+++ src/Forms/Shared/Samples/Geoprocessing/AnalyzeHotspots/AnalyzeHotspots.xaml.cs
@@ -58,8 +58,22 @@
             MyActivityInidicator.IsRunning = true;

             // Get the 'from' and 'to' dates from the date pickers for the geoprocessing analysis
-            DateTime myFromDate = Convert.ToDateTime(StartDate.Text);
-            DateTime myToDate = Convert.ToDateTime(EndDate.Text);
+            DateTime myFromDate;
+            DateTime myToDate;
+            try
+            {
+                myFromDate = Convert.ToDateTime(StartDate.Text);
+                myToDate = Convert.ToDateTime(EndDate.Text);
+            } catch (Exception)
+            {
+                // Handle badly formatted dates
+                await DisplayAlert("Invalid date", "Please enter a valid date", "OK");
+
+                // Remove the busy activity indication
+                MyActivityInidicator.IsRunning = false;
+                MyActivityInidicator.IsVisible = false;
+                return;
+            }

             // The end date must be at least one day after the start date
             if (myToDate <= myFromDate.AddDays(1))


Adds support for ILMerge's /allowMultiple switch.

--- Source/MSBuild.Community.Tasks/ILMerge/ILMerge.cs
+++ Source/MSBuild.Community.Tasks/ILMerge/ILMerge.cs
@@ -135,6 +135,16 @@
         public bool CopyAttributes { get; set; }

         /// <summary>
+        /// Gets or sets a value indicating whether to copy assembly attributes from all merged assemblies
+        /// into the unified assembly even if duplicate assembly attributes would result.
+        /// </summary>
+        /// <remarks>
+        /// <para>Applicable only when <see cref="CopyAttributes"/> is <c>true</c></para>
+        /// <para>Corresponds to command line option "/allowMultiple".</para>
+        /// </remarks>
+        public bool AllowDuplicateAttributes { get; set; }
+
+        /// <summary>
         /// Gets or sets a value indicating whether
         /// to preserve any .pdb files
         /// that are found for the input assemblies
@@ -361,7 +371,13 @@
                 builder.AppendSwitch("/closed");

             if (CopyAttributes)
+            {
                 builder.AppendSwitch("/copyattrs");
+                if (AllowDuplicateAttributes)
+                {
+                    builder.AppendSwitch("/allowMultiple");
+                }
+            }

             if (!DebugInfo)
                 builder.AppendSwitch("/ndebug");


[Toolkit.Game] Added few comments to GameWindow

--- Source/Toolkit/SharpDX.Toolkit.Game/GameWindow.cs
+++ Source/Toolkit/SharpDX.Toolkit.Game/GameWindow.cs
@@ -31,9 +31,15 @@
         private string title;

         #region Public Events
-
+
+        /// <summary>
+        /// Occurs, when device client size is changed.
+        /// </summary>
         public event EventHandler<EventArgs> ClientSizeChanged;

+        /// <summary>
+        /// Occurs, when device orientation is changed.
+        /// </summary>
         public event EventHandler<EventArgs> OrientationChanged;

         internal event EventHandler<EventArgs> Activated;
@@ -43,7 +49,10 @@
         #endregion

         #region Public Properties
-
+
+        /// <summary>
+        /// Gets or sets, user possibility to resize this window.
+        /// </summary>
         public abstract bool AllowUserResizing { get; set; }

         /// <summary>
@@ -156,4 +165,4 @@
             }
         }
     }
-}+}


Fix list serialization in abstract class

--- Spark/Spark.DataType.cs
+++ Spark/Spark.DataType.cs
@@ -65,18 +65,15 @@

 			m_assignableTypes = TryGetAsAttributeParams(type.GetCustomAttributes(false));

-			if (m_assignableTypes != null)
-			{
-				for (int i = 0; i < m_assignableTypes.Count; ++i)
-				{
-					if (!type.IsAssignableFrom(m_assignableTypes[i].Type))
-						throw new ArgumentException(string.Format("Type '{0}' is not assignable from {1}", type, m_assignableTypes[i].Type));
-				}
+			for (int i = 0; i < m_assignableTypes.Count; ++i)
+			{
+				if (!type.IsAssignableFrom(m_assignableTypes[i].Type))
+					throw new ArgumentException(string.Format("Type '{0}' is not assignable from {1}", type, m_assignableTypes[i].Type));
 			}

 			TypeFlags typeFlags = GetTypeFlags(type);

-			if ((m_assignableTypes == null) && (typeFlags.Is(TypeFlags.List) || typeFlags.Is(TypeFlags.Dictionary)))
+			if ((typeFlags.Is(TypeFlags.List) || typeFlags.Is(TypeFlags.Dictionary)))
 			{
 				ConstructorParameterType[0] = typeof(int);
 				m_constructor = type.GetConstructor(ConstructorParameterType);
@@ -86,14 +83,14 @@
 				m_constructor = type.GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, Type.EmptyTypes, null);
 			}

-			if ((m_constructor == null) && (m_assignableTypes == null))
+			if ((m_constructor == null) && (m_assignableTypes.Count == 0))
 				throw new ArgumentException(string.Format("Required default constructor for type '{0}'", type));
 		}

 		public void InitMembers()
 		{
 			if (m_members != null)
-				throw new System.InvalidOperationException();
+				return;

 			Type type = m_type;

@@ -316,7 +313,7 @@
 		/// <summary> Записывает все поля {instance} в массив байт {data} начиная с индекса {startInder} </summary>
 		public void WriteValues(object instance, byte[] data, ref int startIndex, QueueWithIndexer<int> sizes, QueueWithIndexer<object> values)
 		{
-			if (m_assignableTypes != null)
+			if (m_assignableTypes.Count != 0)
 			{
 				Type instanceType = instance.GetType();

@@ -342,7 +339,7 @@
 		/// <summary> Возвращает количество байт, которое потребуется для записи {instance} </summary>
 		public int GetDataSize(object instance, QueueWithIndexer<int> sizes, QueueWithIndexer<object> values)
 		{
-			if (m_assignableTypes != null)
+			if (m_assignableTypes.Count != 0)
 			{
 				Type instanceType = instance.GetType();


removed some of the deprecated API usage warnings

--- StringSearch/Command.cs
+++ StringSearch/Command.cs
@@ -62,20 +62,20 @@
     /// Revit 2011, we implement it ourselves for
     /// backwards compatibility.
     /// </summary>
-    ICollection<ElementId> GetSelectedElementIds(
-      UIDocument uidoc )
-    {
-      SelElementSet ss = uidoc.Selection.Elements;
-
-      List<ElementId> ids = new List<ElementId>(
-        ss.Size );
-
-      foreach( Element e in ss )
-      {
-        ids.Add( e.Id );
-      }
-      return ids;
-    }
+    //ICollection<ElementId> GetSelectedElementIds(
+    //  UIDocument uidoc )
+    //{
+    //  SelElementSet ss = uidoc.Selection.Elements;
+
+    //  List<ElementId> ids = new List<ElementId>(
+    //    ss.Size );
+
+    //  foreach( Element e in ss )
+    //  {
+    //    ids.Add( e.Id );
+    //  }
+    //  return ids;
+    //}

     /// <summary>
     /// External command mainline.
@@ -94,7 +94,7 @@
       Application app = uiapp.Application;
       Document doc = uidoc.Document;

-      ICollection<ElementId> selids = GetSelectedElementIds( uidoc );
+      ICollection<ElementId> selids = uidoc.Selection.GetElementIds();

       try
       {
@@ -130,8 +130,8 @@
                 ? new FilteredElementCollector(
                   doc, doc.ActiveView.Id )
               : form.CurrentSelection
-                ? new FilteredElementCollector(
-                    doc, GetSelectedElementIds( uidoc ) )
+                ? new FilteredElementCollector( doc,
+                    uidoc.Selection.GetElementIds() )
               : new FilteredElementCollector( doc );

             if( form.ElementType && form.NonElementType )


Removed searchPath member.

Removed searchPath member.

--- Symbols/SymbolReader.cs
+++ Symbols/SymbolReader.cs
@@ -13,13 +13,9 @@
 		private ComDisposableWrapper<DiaSource> diaSource;
 		private ComDisposableWrapper<IDiaSession> diaSession;

-		private readonly string searchPath;
-
-		public SymbolReader(string searchPath)
+		public SymbolReader()
 		{
 			diaSource = new ComDisposableWrapper<DiaSource>(new DiaSource());
-
-			this.searchPath = searchPath;
 		}

 		protected virtual void Dispose(bool disposing)
@@ -62,7 +58,7 @@
 		{
 			Contract.Requires(module != null);

-			var reader = new SymbolReader(searchPath);
+			var reader = new SymbolReader();
 			reader.diaSource.Interface.loadDataForExe(module.Path, searchPath, null);
 			reader.CreateSession();
 			return reader;
@@ -72,7 +68,7 @@
 		{
 			Contract.Requires(path != null);

-			var reader = new SymbolReader(null);
+			var reader = new SymbolReader();
 			reader.diaSource.Interface.loadDataFromPdb(path);
 			reader.CreateSession();
 			return reader;


Add test for CallableInterceptorAsyncAdapter.

--- src/MassiveDynamicProxyGenerator.Tests/CallableInterceptorAsyncAdapterTests.cs
+++ src/MassiveDynamicProxyGenerator.Tests/CallableInterceptorAsyncAdapterTests.cs
@@ -322,6 +322,39 @@

         #endregion

+        #region Test supression call
+
+        [TestMethod]
+        public async Task CallableInterceptorAsyncAdapter_TaskGenericMethod_SupressParent()
+        {
+            object invocationMetaData = new object();
+            IGrapth graph = (new Mock<IGrapth>().Object);
+            Mock<IMethodWraper> methodWraper = new Mock<IMethodWraper>();
+            methodWraper.Setup(t => t.OnEnterInvoke(It.IsNotNull<ICallableInvocation>()))
+                .Callback<ICallableInvocation>(invocation =>
+                {
+                    invocation.MethodName.ShouldBe("ReadContextAsync");
+                    invocation.ReturnValue = Task.FromResult(graph);
+                }).Returns(invocationMetaData);
+
+            methodWraper.Setup(t => t.OnExitInvoke(It.IsNotNull<ICallableInvocation>(), invocationMetaData));
+
+            Mock<IAsyncInterface> asyncInterfaceMock = new Mock<IAsyncInterface>(MockBehavior.Strict);
+
+            ICallableInterceptor interceptor = new CallableInterceptorAsyncImpl(methodWraper.Object);
+
+            ProxygGenerator generator = new ProxygGenerator();
+
+            IAsyncInterface instance = generator.GenerateDecorator<IAsyncInterface>(interceptor, asyncInterfaceMock.Object);
+
+            IGrapth graphResult = await instance.ReadContextAsync();
+            graphResult.ShouldBe(graph);
+
+            methodWraper.VerifyAll();
+            asyncInterfaceMock.VerifyAll();
+        }
+        #endregion
+
         private async Task ThrowAsyncException()
         {
             await Task.Delay(50);


Added static and renamed method

Added static and renamed method

--- Test2d/Shapes/XPoint.cs
+++ Test2d/Shapes/XPoint.cs
@@ -49,10 +49,9 @@
         /// <param name="binding"></param>
         /// <param name="record"></param>
         /// <param name="value"></param>
-        private void BindToDouble(ShapeBinding binding, Record record, ref double value)
+        private static void BindToDouble(ShapeBinding binding, Record record, ref double value)
         {
             var columns = record.Columns;
-
             for (int i = 0; i < columns.Length; i++)
             {
                 if (columns[i].Name == binding.Path)
@@ -77,7 +76,7 @@
         /// <param name="record"></param>
         /// <param name="propertyNameX"></param>
         /// <param name="propertyNameY"></param>
-        private void TryToBindInternal(
+        private void TryToBind(
             ImmutableArray<ShapeBinding> bindings,
             Record record,
             string propertyNameX,
@@ -118,7 +117,7 @@
             var bindings = this.Bindings;
             string propertyNameX = "X";
             string propertyNameY = "Y";
-            TryToBindInternal(bindings, record, propertyNameX, propertyNameY);
+            TryToBind(bindings, record, propertyNameX, propertyNameY);
         }

         /// <summary>
@@ -131,7 +130,7 @@
         {
             string propertyNameX = propertyName + ".X";
             string propertyNameY = propertyName + ".Y";
-            TryToBindInternal(bindings, record, propertyNameX, propertyNameY);
+            TryToBind(bindings, record, propertyNameX, propertyNameY);
         }

         /// <summary>


1608: fix mouse up event propagation

1608: fix mouse up event propagation

--- src/PixelFarm/PaintLab.YourImplementation/1_Events/RenderElementEventPortal.cs
+++ src/PixelFarm/PaintLab.YourImplementation/1_Events/RenderElementEventPortal.cs
@@ -211,7 +211,7 @@
                     e.CurrentContextElement = currentMouseDown = null; //clear
                     ForEachEventListenerBubbleUp(e, hitPointChain, listener =>
                     {
-
+
                         if (listener.BypassAllMouseEvents)
                         {
                             return false;
@@ -372,8 +372,15 @@
                 {
                     ForEachEventListenerBubbleUp(e, hitPointChain, (listener) =>
                     {
+
+                        if (listener.BypassAllMouseEvents)
+                        {
+                            return false;
+                        }
                         listener.ListenMouseUp(e);
-                        return true;
+                        //retrun true to stop this loop (no further bubble up)
+                        //return false to bubble this to upper control
+                        return e.CancelBubbling || !listener.BypassAllMouseEvents;

                     });
                 }


add hot update test

add hot update test

--- Test461/TestRmDeLinq.cs
+++ Test461/TestRmDeLinq.cs
@@ -113,6 +113,24 @@
                ++actual;

             Assert.AreEqual (0, actual);
+        }
+
+        [TestMethod]
+#if ! TEST_BCL
+        [ExpectedException (typeof (InvalidOperationException))]
+#endif
+        public void CrashRmq_ReverseHotUpdate()
+        {
+            var rm = new RankedMap<string,int> { {"aa",1}, {"bb",2}, {"cc",3}, {"dd",4} };
+            int n = 0;
+
+#if TEST_BCL
+            foreach (var key in Enumerable.Reverse (rm))
+#else
+            foreach (var kv in rm.Reverse())
+#endif
+                if (++n == 2)
+                    rm.Clear();
         }

         [TestMethod]


Format options for both string and number

--- Types/TabsterVersion.cs
+++ Types/TabsterVersion.cs
@@ -19,19 +19,25 @@
         None = 0x0,

         /// <summary>
-        ///     Specifies that the build version should be appended to the version string. (Ex: 1.0.2 (Build 12))
+        ///     Specifies that the build version should be appended to the version string.
         /// </summary>
         Build = 0x1,

         /// <summary>
+        ///     Specifies that the build version should be appended in a human-friendly format to the version string. (Ex: 1.0.2
+        ///     (Build 12))
+        /// </summary>
+        BuildString = 0x2,
+
+        /// <summary>
         ///     Specifies that the hash should be appended to the version string. (Ex: 1.0.2 c42ff11)
         /// </summary>
-        Hash = 0x2,
+        Hash = 0x4,

         /// <summary>
         ///     Specifies that the version string should be truncated of trailing zeros.
         /// </summary>
-        Truncated = 0x4,
+        Truncated = 0x8,
     }

     /// <summary>
@@ -331,7 +337,7 @@
             var baseStr = string.Format("{0}.{1}.{2}", Major, Minor, Revision);

             // include build component if it's not to be appended
-            if ((flags & TabsterVersionFormatFlags.Build) != TabsterVersionFormatFlags.Build)
+            if ((flags & TabsterVersionFormatFlags.Build) == TabsterVersionFormatFlags.Build)
                 baseStr += string.Format(".{0}", Build);

             // truncate version string
@@ -344,7 +350,7 @@
                     baseStr = string.Format("{0}.0", baseStr);
             }

-            if ((flags & TabsterVersionFormatFlags.Build) == TabsterVersionFormatFlags.Build && Build > 0)
+            if ((flags & TabsterVersionFormatFlags.BuildString) == TabsterVersionFormatFlags.BuildString && Build > 0)
                 baseStr += string.Format(" (Build {0})", Build);

             if ((flags & TabsterVersionFormatFlags.Hash) == TabsterVersionFormatFlags.Hash && !string.IsNullOrEmpty(Hash))


Update IPartialConfiguration.cs

Update IPartialConfiguration.cs

--- TIKSN.Core/Configuration/IPartialConfiguration.cs
+++ TIKSN.Core/Configuration/IPartialConfiguration.cs
@@ -4,4 +4,4 @@
     {
         T GetConfiguration();
     }
-}+}


Correct problem with modifying collection in loop while polling Syncromatics routes

--- TrolleyTracker/Controllers/PollTrolleysHandler.cs
+++ TrolleyTracker/Controllers/PollTrolleysHandler.cs
@@ -130,7 +130,11 @@

         private async Task TrackGhostVehicles(bool saveTrolleysToDB)
         {
-            foreach (var syncroRoute in ghostRoutes)
+            // Copy array to handle ghost route modification in loop
+            var workGhostRoutes = new Syncromatics.Route[ghostRoutes.Count];
+            ghostRoutes.CopyTo(workGhostRoutes);
+
+            foreach (var syncroRoute in workGhostRoutes)
             {
                 await CheckForVehiclesOnRoute(syncroRoute, saveTrolleysToDB);
             }


fix(Presence): remove console warning in position rewind

The PositionRewind script was throwing a console warning because
the script was trying to do a Vector3 to null comparison which
will never be able to succeed.

--- Assets/VRTK/Scripts/Presence/VRTK_PositionRewind.cs
+++ Assets/VRTK/Scripts/Presence/VRTK_PositionRewind.cs
@@ -111,7 +111,7 @@
         /// </summary>
         public virtual void RewindPosition()
         {
-            if (lastGoodStandingPosition != null && headset != null)
+            if (headset != null)
             {
                 Vector3 storedPosition = playArea.position;
                 Vector3 resetVector = lastGoodHeadsetPosition - headset.position;


不要なフィールドを削除

不要なフィールドを削除

--- NotifyForm.cs
+++ NotifyForm.cs
@@ -541,7 +541,6 @@
         #endregion

         #region Fields
-        private NotifyStyle _defaultStyle = null;
         private Dictionary<NotifyLevel, NotifyStyle> _styles = new Dictionary<NotifyLevel, NotifyStyle>();
         #endregion
     }


要素に節点数を返すプロパティを追加したので，テストを修正．

要素に節点数を返すプロパティを追加したので，テストを修正．

--- UnitTest/ElementTest.cs
+++ UnitTest/ElementTest.cs
@@ -29,6 +29,7 @@
         {
             var elm = new Element(type, line);

+            Assert.AreEqual(nodes.Length, (int)elm.Count());
             Assert.AreEqual(id, elm.id, "ID");

             for (uint i = 0; i < nodes.Length; i++)


By Unit is list

By Unit is list

--- Battery-Commander.Web/Controllers/SUTAController.cs
+++ Battery-Commander.Web/Controllers/SUTAController.cs
@@ -48,7 +48,7 @@
         public async Task<IActionResult> Details(GetSUTARequest request) => View(await dispatcher.Send(request));

         [HttpGet("~/Units/{Unit}/SUTA")]
-        public async Task<IActionResult> ByUnit(GetSUTARequests request) => View(await dispatcher.Send(request));
+        public async Task<IActionResult> ByUnit(GetSUTARequests request) => View("List", await dispatcher.Send(request));

         [HttpGet("{Id}/Edit")]
         public async Task<IActionResult> Edit(GetSUTARequest request) => View(await dispatcher.Send(request));


DBAccess returns string[] instead of Account DBAccess dont talk to model anymore

--- BlackJackSolution/BlackJackSolution/DAL/DBAccess.cs
+++ BlackJackSolution/BlackJackSolution/DAL/DBAccess.cs
@@ -4,7 +4,7 @@
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
-using BlackJackSolution.Model;
+

 namespace BlackJackSolution.DAL
 {
@@ -47,6 +47,7 @@

                 if (read.HasRows)
                 {
+
                         while (read.Read())
                         {
                             Card card = new Card();
@@ -132,11 +133,11 @@
             }
         }

-        public Account GetAccount(string aname)
-        {
-            try
-            {
-                Account account = new Account();
+        public string[] GetAccount(string aname)
+        {
+            try
+            {
+                string[] result = new string[4];
                 SqlConnection connection = Connect();
                 SqlCommand command = new SqlCommand("EXEC [dbo].[GETUSER] @USERNAME = '" + aname + "'", connection);
                 command.ExecuteNonQuery();
@@ -144,11 +145,11 @@

                 if (read != null)
                 {
-                    account.setAname(read.GetString(read.GetOrdinal("aname")));
-                    account.setAstatus(read.GetString(read.GetOrdinal("astatus")));
-                    account.setBalance(read.GetDouble(read.GetOrdinal("balance")));
-                    account.setPassword(read.GetString(read.GetOrdinal("password")));
-                    return account;
+                    result[0] = read.GetString(read.GetOrdinal("aname"));
+                    result[1] = read.GetString(read.GetOrdinal("astatus"));
+                    result[2] = read.GetDouble(read.GetOrdinal("balance")).ToString();
+                    result[3] = read.GetString(read.GetOrdinal("password"));
+                    return result;
                 }
                 else
                 {


Format hex string with invariant culture

--- src/Cryptography/Nonce.cs
+++ src/Cryptography/Nonce.cs
@@ -1,6 +1,7 @@
 using System;
 using System.ComponentModel;
 using System.Diagnostics;
+using System.Globalization;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 using System.Text;
@@ -323,12 +324,12 @@
             StringBuilder sb = new StringBuilder(size * 2 + 4).Append('[');
             for (int i = 0; i < init; i++)
             {
-                sb.Append(Unsafe.Add(ref bytes, i).ToString("X2"));
+                sb.Append(Unsafe.Add(ref bytes, i).ToString("X2", CultureInfo.InvariantCulture));
             }
             sb.Append(']').Append('[');
             for (int i = init; i < size; i++)
             {
-                sb.Append(Unsafe.Add(ref bytes, i).ToString("X2"));
+                sb.Append(Unsafe.Add(ref bytes, i).ToString("X2", CultureInfo.InvariantCulture));
             }
             return sb.Append(']').ToString();
         }


Make asteroid source accessible through CustomAsteroidData.

--- src/CustomAsteroidData.cs
+++ src/CustomAsteroidData.cs
@@ -18,6 +18,18 @@
         [KSPField (guiActive = true, guiActiveEditor = true,
                    guiName = "#autoLOC_CustomAsteroids_GuiClass")]
         public string displayComposition;
+
+        ///
+        /// The unique ID of the asteroid set that created this asteroid.
+        ///
+        /// <value>The name of the set, or null if inapplicable or unknown.</value>
+        /// <remarks>The returned name is not guaranteed to match any currently
+        /// loaded asteroid config.</remarks>
+        public string parentSet {
+            get {
+                return CustomAsteroidRegistry.Instance.LookupAsteroid (vessel).parentSet;
+            }
+        }

         public CustomAsteroidData ()
         {


Added Color->Vector4. More Vector2 swizzles

--- PopVectorX.cs
+++ PopVectorX.cs
@@ -10,6 +10,11 @@
 	public static Color WithAlpha(this Color rgba, float Alpha)
 	{
 		return new Color(rgba.r, rgba.g, rgba.b, Alpha);
+	}
+
+	public static Vector4 GetVector4(this Color rgba)
+	{
+		return new Vector4(rgba.r, rgba.g, rgba.b, rgba.a);
 	}

 	//	converts a normalised float from red(0) to green(1). Blue if OOB
@@ -93,6 +98,8 @@
 {
 	public static Vector2 yx(this Vector2 two) { return new Vector2(two.y, two.x); }
 	public static Vector3 xy0(this Vector2 two) { return new Vector3(two.x, two.y, 0); }
+	public static Vector4 xy00(this Vector2 two) { return new Vector4(two.x, two.y, 0,0); }
+	public static Vector4 xy01(this Vector2 two) { return new Vector4(two.x, two.y, 0,1); }
 	public static Vector3 xyz(this Vector2 two, float z) { return new Vector3(two.x, two.y, z); }
 	public static Vector4 xyzw(this Vector2 two, float z, float w) { return new Vector4(two.x, two.y, z, w); }


Implemented Media Web Service

Implemented Media Web Service

[TFS Changeset #63870]

--- components/umbraco.webservices/MediaService.asmx.cs
+++ components/umbraco.webservices/MediaService.asmx.cs
@@ -11,6 +11,11 @@
 using umbraco.cms.businesslogic.web;
 using umbraco.cms;
 using umbraco.cms.businesslogic.member;
+using umbraco.cms.businesslogic.media;
+using System.IO;
+using umbraco.cms.businesslogic.property;
+using umbraco.IO;
+using System.Text.RegularExpressions;

 namespace umbraco.webservices.media
 {
@@ -28,6 +33,305 @@
                 return Services.MediaService;
             }
         }
+
+        [WebMethod]
+        public void update(mediaCarrier carrier, string username, string password) {
+
+            Authenticate(username, password);
+
+            if (carrier == null) throw new Exception("No carrier specified");
+
+            Media m = new Media(carrier.Id);
+
+            if (carrier.MediaProperties != null)
+            {
+                foreach (mediaProperty updatedproperty in carrier.MediaProperties)
+                {
+                    if (!(updatedproperty.Key.ToLower().Equals("umbracofile")))
+                    {
+                        Property property = m.getProperty(updatedproperty.Key);
+                        if (property == null)
+                            throw new Exception("property " + updatedproperty.Key + " was not found");
+                        property.Value = updatedproperty.PropertyValue;
+                    }
+                }
+            }
+
+            m.Save();
+        }
+
+        [WebMethod]
+        public int create(mediaCarrier carrier, string username, string password)
+        {
+
+            Authenticate(username, password);
+
+            if (carrier == null) throw new Exception("No carrier specified");
+            if (carrier.ParentId == 0) throw new Exception("Media needs a parent");
+            if (carrier.TypeId == 0) throw new Exception("Type must be specified");
+            if (carrier.Text == null || carrier.Text.Length == 0) carrier.Text = "unnamed";
+
+            umbraco.BusinessLogic.User user = GetUser(username, password);
+
+
+            MediaType mt = new MediaType(carrier.TypeId);
+
+            Media m = Media.MakeNew(carrier.Text, mt, user, carrier.ParentId);
+
+            if (carrier.MediaProperties != null)
+            {
+                foreach (mediaProperty updatedproperty in carrier.MediaProperties)
+                {
+                    if(!(updatedproperty.Key.ToLower().Equals("umbracofile"))) {
+                        Property property = m.getProperty(updatedproperty.Key);
+                        if (property == null)
+                            throw new Exception("property " + updatedproperty.Key + " was not found");
+                        property.Value = updatedproperty.PropertyValue;
+                    }
+                }
+            }
+
+            return m.Id;
+        }
+
+        [WebMethod]
+        public void delete(int id, string username, string password)
+        {
+            Authenticate(username, password);
+
+            Media m = new Media(id);
+
+            if (m.HasChildren)
+                throw new Exception("Cannot delete Media " + id + " as it has child nodes");
+
+            Property p = m.getProperty("umbracoFile");
+            if (p != null)
+            {
+                if (!(p.Value == System.DBNull.Value))
+                {
+                    string fileName = (string)p.Value;
+                    string filePath = umbraco.IO.IOHelper.MapPath(fileName);
+                    if (File.Exists(filePath))
+                    {
+                        File.Delete(filePath);
+                    }
+                }
+            }
+
+            m.delete();
+
+        }
+
+        [WebMethod]
+        public void writeContents(int id, string filename, Byte[] contents, string username, string password)
+        {
+            Authenticate(username, password);
+
+            filename = filename.Replace("/", IOHelper.DirSepChar.ToString());
+            filename = filename.Replace(@"\", IOHelper.DirSepChar.ToString());
+            filename = filename.Substring(filename.LastIndexOf(IOHelper.DirSepChar) + 1, filename.Length - filename.LastIndexOf(IOHelper.DirSepChar) - 1).ToLower();
+
+            Media m = new Media(id);
+
+
+            System.IO.Directory.CreateDirectory(IOHelper.MapPath(SystemDirectories.Media + "/" + m.getProperty("umbracoFile").Id ));
+            string fullFilePath = IOHelper.MapPath(SystemDirectories.Media + "/" + m.getProperty("umbracoFile").Id + "/" + filename);
+
+            File.WriteAllBytes(fullFilePath, contents);
+
+            FileInfo f = new FileInfo(fullFilePath);
+            m.getProperty("umbracoFile").Value = SystemDirectories.Media + "/" + filename;
+            m.getProperty("umbracoExtension").Value = f.Extension.Replace(".","");
+            m.getProperty("umbracoBytes").Value = f.Length.ToString();
+
+
+        }
+
+        [WebMethod]
+        public mediaCarrier read(int id, string username, string password)
+        {
+            Authenticate(username, password);
+
+
+            Media m = new Media(id);
+
+
+            return createCarrier(m);
+        }
+
+        [WebMethod]
+        public List<mediaCarrier> readList(int parentId, string username, string password)
+        {
+            Authenticate(username, password);
+
+            List<mediaCarrier> carriers = new List<mediaCarrier>();
+            Media[] mediaList;
+
+            if (parentId < 1)
+            {
+                mediaList = Media.GetRootMedias();
+            }
+            else
+            {
+                Media m = new Media(parentId);
+                mediaList = m.Children;
+            }
+
+            foreach (Media child in mediaList)
+            {
+                carriers.Add(createCarrier(child));
+            }
+
+            return carriers;
+        }

+        private mediaCarrier createCarrier(Media m)
+        {
+            mediaCarrier carrier = new mediaCarrier();
+            carrier.Id = m.Id;
+            carrier.Text = m.Text;
+
+            carrier.TypeAlias = m.ContentType.Alias;
+            carrier.TypeId = m.ContentType.Id;
+
+            carrier.CreateDateTime = m.CreateDateTime;
+            carrier.HasChildren = m.HasChildren;
+            carrier.Level = m.Level;
+
+            carrier.Path = m.Path;
+            carrier.SortOrder = m.sortOrder;
+
+            try
+            {
+                carrier.ParentId = m.Parent.Id;
+            }
+            catch
+            {
+                carrier.ParentId = -1;
+            }
+
+            foreach(Property p in m.getProperties) {
+
+                mediaProperty carrierprop = new mediaProperty();
+
+                if (p.Value == System.DBNull.Value)
+                {
+                    carrierprop.PropertyValue = "";
+                }
+                else
+                {
+                    carrierprop.PropertyValue = p.Value;
+                }
+
+                carrierprop.Key = p.PropertyType.Alias;
+                carrier.MediaProperties.Add(carrierprop);
+
+            }
+
+            return carrier;
+        }
+
     }
+
+
+
+    [Serializable]
+    [XmlType(Namespace = "http://umbraco.org/webservices/")]
+    public class mediaCarrier
+    {
+
+        public int Id
+        {
+            get;
+            set;
+        }
+        public string Text
+        {
+            get;
+            set;
+
+        }
+
+        public string TypeAlias
+        {
+            get;
+            set;
+        }
+
+        public int TypeId
+        {
+            get;
+            set;
+        }
+
+        public DateTime CreateDateTime
+        {
+            get;
+            set;
+        }
+
+        public Boolean HasChildren
+        {
+            get;
+            set;
+        }
+
+        public int Level
+        {
+            get;
+            set;
+        }
+
+        public int ParentId
+        {
+            get;
+            set;
+
+        }
+
+        public string Path
+        {
+            get;
+            set;
+        }
+
+        public int SortOrder
+        {
+            get;
+            set;
+        }
+
+        public List<mediaProperty> MediaProperties
+        {
+            get;
+            set;
+        }
+
+        public mediaCarrier()
+        {
+            MediaProperties = new List<mediaProperty>();
+        }
+    }
+
+    [XmlType(Namespace = "http://umbraco.org/webservices/")]
+    public class mediaProperty
+    {
+        public mediaProperty()
+        {
+        }
+
+        public object PropertyValue
+        {
+            get;
+            set;
+        }
+
+        public string Key
+        {
+            get;
+            set;
+        }
+    }
+
+
 }