diff --git a/Duplicati.sln b/Duplicati.sln index e42f23af3..66cbbb572 100644 --- a/Duplicati.sln +++ b/Duplicati.sln @@ -57,11 +57,15 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Backend.S EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Server", "Duplicati\Server\Duplicati.Server.csproj", "{19E661D2-C5DA-4F35-B3EE-7586E5734B5F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Server.Serialization", "Duplicati\Server\Duplicati.Server.Serialization\Duplicati.Server.Serialization.csproj", "{33FD1D24-C28F-4C71-933F-98F1586EA76C}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.GUI.TrayIcon", "Duplicati\GUI\Duplicati.GUI.TrayIcon\Duplicati.GUI.TrayIcon.csproj", "{17566860-3D98-4604-AA5B-47661F75609F}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Server.Serialization", "Duplicati\Server\Duplicati.Server.Serialization\Duplicati.Server.Serialization.csproj", "{33FD1D24-C28F-4C71-933F-98F1586EA76C}" +EndProject Global + GlobalSection(SubversionScc) = preSolution + Svn-Managed = True + Manager = AnkhSVN - Subversion Support for Visual Studio + EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Debug|x86 = Debug|x86 @@ -69,22 +73,6 @@ Global Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {0CA86ECF-5BEC-4909-B4F6-110A03B30B92}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0CA86ECF-5BEC-4909-B4F6-110A03B30B92}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0CA86ECF-5BEC-4909-B4F6-110A03B30B92}.Debug|x86.ActiveCfg = Debug|x86 - {0CA86ECF-5BEC-4909-B4F6-110A03B30B92}.Debug|x86.Build.0 = Debug|x86 - {0CA86ECF-5BEC-4909-B4F6-110A03B30B92}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0CA86ECF-5BEC-4909-B4F6-110A03B30B92}.Release|Any CPU.Build.0 = Release|Any CPU - {0CA86ECF-5BEC-4909-B4F6-110A03B30B92}.Release|x86.ActiveCfg = Release|x86 - {0CA86ECF-5BEC-4909-B4F6-110A03B30B92}.Release|x86.Build.0 = Release|x86 - {10D2D1B7-C664-41D8-9B3A-00040C3D421B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {10D2D1B7-C664-41D8-9B3A-00040C3D421B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {10D2D1B7-C664-41D8-9B3A-00040C3D421B}.Debug|x86.ActiveCfg = Debug|x86 - {10D2D1B7-C664-41D8-9B3A-00040C3D421B}.Debug|x86.Build.0 = Debug|x86 - {10D2D1B7-C664-41D8-9B3A-00040C3D421B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {10D2D1B7-C664-41D8-9B3A-00040C3D421B}.Release|Any CPU.Build.0 = Release|Any CPU - {10D2D1B7-C664-41D8-9B3A-00040C3D421B}.Release|x86.ActiveCfg = Release|x86 - {10D2D1B7-C664-41D8-9B3A-00040C3D421B}.Release|x86.Build.0 = Release|x86 {1470F75F-D364-4010-91D0-FD4DDA1C5159}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1470F75F-D364-4010-91D0-FD4DDA1C5159}.Debug|Any CPU.Build.0 = Debug|Any CPU {1470F75F-D364-4010-91D0-FD4DDA1C5159}.Debug|x86.ActiveCfg = Debug|x86 @@ -93,140 +81,6 @@ Global {1470F75F-D364-4010-91D0-FD4DDA1C5159}.Release|Any CPU.Build.0 = Release|Any CPU {1470F75F-D364-4010-91D0-FD4DDA1C5159}.Release|x86.ActiveCfg = Release|x86 {1470F75F-D364-4010-91D0-FD4DDA1C5159}.Release|x86.Build.0 = Release|x86 - {19ECCE09-B5EB-406C-8C57-BAC66997D469}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {19ECCE09-B5EB-406C-8C57-BAC66997D469}.Debug|Any CPU.Build.0 = Debug|Any CPU - {19ECCE09-B5EB-406C-8C57-BAC66997D469}.Debug|x86.ActiveCfg = Debug|x86 - {19ECCE09-B5EB-406C-8C57-BAC66997D469}.Debug|x86.Build.0 = Debug|x86 - {19ECCE09-B5EB-406C-8C57-BAC66997D469}.Release|Any CPU.ActiveCfg = Release|Any CPU - {19ECCE09-B5EB-406C-8C57-BAC66997D469}.Release|Any CPU.Build.0 = Release|Any CPU - {19ECCE09-B5EB-406C-8C57-BAC66997D469}.Release|x86.ActiveCfg = Release|x86 - {19ECCE09-B5EB-406C-8C57-BAC66997D469}.Release|x86.Build.0 = Release|x86 - {1BFAE226-8364-4086-825C-BB83F6F3EE4C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1BFAE226-8364-4086-825C-BB83F6F3EE4C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1BFAE226-8364-4086-825C-BB83F6F3EE4C}.Debug|x86.ActiveCfg = Debug|x86 - {1BFAE226-8364-4086-825C-BB83F6F3EE4C}.Debug|x86.Build.0 = Debug|x86 - {1BFAE226-8364-4086-825C-BB83F6F3EE4C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1BFAE226-8364-4086-825C-BB83F6F3EE4C}.Release|Any CPU.Build.0 = Release|Any CPU - {1BFAE226-8364-4086-825C-BB83F6F3EE4C}.Release|x86.ActiveCfg = Release|x86 - {1BFAE226-8364-4086-825C-BB83F6F3EE4C}.Release|x86.Build.0 = Release|x86 - {42C91180-11EB-4590-82EA-80FE9D4DEBEC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {42C91180-11EB-4590-82EA-80FE9D4DEBEC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {42C91180-11EB-4590-82EA-80FE9D4DEBEC}.Debug|x86.ActiveCfg = Debug|Any CPU - {42C91180-11EB-4590-82EA-80FE9D4DEBEC}.Debug|x86.Build.0 = Debug|x86 - {42C91180-11EB-4590-82EA-80FE9D4DEBEC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {42C91180-11EB-4590-82EA-80FE9D4DEBEC}.Release|Any CPU.Build.0 = Release|Any CPU - {42C91180-11EB-4590-82EA-80FE9D4DEBEC}.Release|x86.ActiveCfg = Release|Any CPU - {47FE73E1-0832-44F7-96B9-2580273206C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {47FE73E1-0832-44F7-96B9-2580273206C3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {47FE73E1-0832-44F7-96B9-2580273206C3}.Debug|x86.ActiveCfg = Debug|x86 - {47FE73E1-0832-44F7-96B9-2580273206C3}.Debug|x86.Build.0 = Debug|x86 - {47FE73E1-0832-44F7-96B9-2580273206C3}.Release|Any CPU.ActiveCfg = Release|Any CPU - {47FE73E1-0832-44F7-96B9-2580273206C3}.Release|Any CPU.Build.0 = Release|Any CPU - {47FE73E1-0832-44F7-96B9-2580273206C3}.Release|x86.ActiveCfg = Release|x86 - {47FE73E1-0832-44F7-96B9-2580273206C3}.Release|x86.Build.0 = Release|x86 - {4D012CB1-4B92-47F4-89B7-BF80A73A2E99}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4D012CB1-4B92-47F4-89B7-BF80A73A2E99}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4D012CB1-4B92-47F4-89B7-BF80A73A2E99}.Debug|x86.ActiveCfg = Debug|x86 - {4D012CB1-4B92-47F4-89B7-BF80A73A2E99}.Debug|x86.Build.0 = Debug|x86 - {4D012CB1-4B92-47F4-89B7-BF80A73A2E99}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4D012CB1-4B92-47F4-89B7-BF80A73A2E99}.Release|Any CPU.Build.0 = Release|Any CPU - {4D012CB1-4B92-47F4-89B7-BF80A73A2E99}.Release|x86.ActiveCfg = Release|x86 - {4D012CB1-4B92-47F4-89B7-BF80A73A2E99}.Release|x86.Build.0 = Release|x86 - {52826615-7964-47FE-B4B3-1B2DBDF605B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {52826615-7964-47FE-B4B3-1B2DBDF605B9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {52826615-7964-47FE-B4B3-1B2DBDF605B9}.Debug|x86.ActiveCfg = Debug|x86 - {52826615-7964-47FE-B4B3-1B2DBDF605B9}.Debug|x86.Build.0 = Debug|x86 - {52826615-7964-47FE-B4B3-1B2DBDF605B9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {52826615-7964-47FE-B4B3-1B2DBDF605B9}.Release|Any CPU.Build.0 = Release|Any CPU - {52826615-7964-47FE-B4B3-1B2DBDF605B9}.Release|x86.ActiveCfg = Release|x86 - {52826615-7964-47FE-B4B3-1B2DBDF605B9}.Release|x86.Build.0 = Release|x86 - {7886BA79-A38A-4288-8B8A-9F29D0E15AC0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7886BA79-A38A-4288-8B8A-9F29D0E15AC0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7886BA79-A38A-4288-8B8A-9F29D0E15AC0}.Debug|x86.ActiveCfg = Debug|x86 - {7886BA79-A38A-4288-8B8A-9F29D0E15AC0}.Debug|x86.Build.0 = Debug|x86 - {7886BA79-A38A-4288-8B8A-9F29D0E15AC0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7886BA79-A38A-4288-8B8A-9F29D0E15AC0}.Release|Any CPU.Build.0 = Release|Any CPU - {7886BA79-A38A-4288-8B8A-9F29D0E15AC0}.Release|x86.ActiveCfg = Release|x86 - {7886BA79-A38A-4288-8B8A-9F29D0E15AC0}.Release|x86.Build.0 = Release|x86 - {81765A64-3661-4E3E-B850-2F6F87A51F74}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {81765A64-3661-4E3E-B850-2F6F87A51F74}.Debug|Any CPU.Build.0 = Debug|Any CPU - {81765A64-3661-4E3E-B850-2F6F87A51F74}.Debug|x86.ActiveCfg = Debug|x86 - {81765A64-3661-4E3E-B850-2F6F87A51F74}.Debug|x86.Build.0 = Debug|x86 - {81765A64-3661-4E3E-B850-2F6F87A51F74}.Release|Any CPU.ActiveCfg = Release|Any CPU - {81765A64-3661-4E3E-B850-2F6F87A51F74}.Release|Any CPU.Build.0 = Release|Any CPU - {81765A64-3661-4E3E-B850-2F6F87A51F74}.Release|x86.ActiveCfg = Release|x86 - {81765A64-3661-4E3E-B850-2F6F87A51F74}.Release|x86.Build.0 = Release|x86 - {94484FDB-2EFA-4CF0-9BE6-A561157B4F87}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {94484FDB-2EFA-4CF0-9BE6-A561157B4F87}.Debug|Any CPU.Build.0 = Debug|Any CPU - {94484FDB-2EFA-4CF0-9BE6-A561157B4F87}.Debug|x86.ActiveCfg = Debug|x86 - {94484FDB-2EFA-4CF0-9BE6-A561157B4F87}.Debug|x86.Build.0 = Debug|x86 - {94484FDB-2EFA-4CF0-9BE6-A561157B4F87}.Release|Any CPU.ActiveCfg = Release|Any CPU - {94484FDB-2EFA-4CF0-9BE6-A561157B4F87}.Release|Any CPU.Build.0 = Release|Any CPU - {94484FDB-2EFA-4CF0-9BE6-A561157B4F87}.Release|x86.ActiveCfg = Release|x86 - {94484FDB-2EFA-4CF0-9BE6-A561157B4F87}.Release|x86.Build.0 = Release|x86 - {B60D0993-B0C5-457A-90D9-DB6EEB33CE47}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B60D0993-B0C5-457A-90D9-DB6EEB33CE47}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B60D0993-B0C5-457A-90D9-DB6EEB33CE47}.Debug|x86.ActiveCfg = Debug|x86 - {B60D0993-B0C5-457A-90D9-DB6EEB33CE47}.Debug|x86.Build.0 = Debug|x86 - {B60D0993-B0C5-457A-90D9-DB6EEB33CE47}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B60D0993-B0C5-457A-90D9-DB6EEB33CE47}.Release|Any CPU.Build.0 = Release|Any CPU - {B60D0993-B0C5-457A-90D9-DB6EEB33CE47}.Release|x86.ActiveCfg = Release|x86 - {B60D0993-B0C5-457A-90D9-DB6EEB33CE47}.Release|x86.Build.0 = Release|x86 - {BAE27510-8B5D-44B2-B33E-372A98908041}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BAE27510-8B5D-44B2-B33E-372A98908041}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BAE27510-8B5D-44B2-B33E-372A98908041}.Debug|x86.ActiveCfg = Debug|x86 - {BAE27510-8B5D-44B2-B33E-372A98908041}.Debug|x86.Build.0 = Debug|x86 - {BAE27510-8B5D-44B2-B33E-372A98908041}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BAE27510-8B5D-44B2-B33E-372A98908041}.Release|Any CPU.Build.0 = Release|Any CPU - {BAE27510-8B5D-44B2-B33E-372A98908041}.Release|x86.ActiveCfg = Release|x86 - {BAE27510-8B5D-44B2-B33E-372A98908041}.Release|x86.Build.0 = Release|x86 - {C0270709-2A40-43B5-8CF1-69581B9FA2A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C0270709-2A40-43B5-8CF1-69581B9FA2A1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C0270709-2A40-43B5-8CF1-69581B9FA2A1}.Debug|x86.ActiveCfg = Debug|x86 - {C0270709-2A40-43B5-8CF1-69581B9FA2A1}.Debug|x86.Build.0 = Debug|x86 - {C0270709-2A40-43B5-8CF1-69581B9FA2A1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C0270709-2A40-43B5-8CF1-69581B9FA2A1}.Release|Any CPU.Build.0 = Release|Any CPU - {C0270709-2A40-43B5-8CF1-69581B9FA2A1}.Release|x86.ActiveCfg = Release|x86 - {C0270709-2A40-43B5-8CF1-69581B9FA2A1}.Release|x86.Build.0 = Release|x86 - {C03F6DFD-805A-4BE0-9338-64870ADDB4A2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C03F6DFD-805A-4BE0-9338-64870ADDB4A2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C03F6DFD-805A-4BE0-9338-64870ADDB4A2}.Debug|x86.ActiveCfg = Debug|x86 - {C03F6DFD-805A-4BE0-9338-64870ADDB4A2}.Debug|x86.Build.0 = Debug|x86 - {C03F6DFD-805A-4BE0-9338-64870ADDB4A2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C03F6DFD-805A-4BE0-9338-64870ADDB4A2}.Release|Any CPU.Build.0 = Release|Any CPU - {C03F6DFD-805A-4BE0-9338-64870ADDB4A2}.Release|x86.ActiveCfg = Release|x86 - {C03F6DFD-805A-4BE0-9338-64870ADDB4A2}.Release|x86.Build.0 = Release|x86 - {C5899F45-B0FF-483C-9D38-24A9FCAAB237}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C5899F45-B0FF-483C-9D38-24A9FCAAB237}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C5899F45-B0FF-483C-9D38-24A9FCAAB237}.Debug|x86.ActiveCfg = Debug|x86 - {C5899F45-B0FF-483C-9D38-24A9FCAAB237}.Debug|x86.Build.0 = Debug|x86 - {C5899F45-B0FF-483C-9D38-24A9FCAAB237}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C5899F45-B0FF-483C-9D38-24A9FCAAB237}.Release|Any CPU.Build.0 = Release|Any CPU - {C5899F45-B0FF-483C-9D38-24A9FCAAB237}.Release|x86.ActiveCfg = Release|x86 - {C5899F45-B0FF-483C-9D38-24A9FCAAB237}.Release|x86.Build.0 = Release|x86 - {CCD76347-7DC7-4B42-B7E1-E500E624CAC3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CCD76347-7DC7-4B42-B7E1-E500E624CAC3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CCD76347-7DC7-4B42-B7E1-E500E624CAC3}.Debug|x86.ActiveCfg = Debug|Any CPU - {CCD76347-7DC7-4B42-B7E1-E500E624CAC3}.Debug|x86.Build.0 = Debug|x86 - {CCD76347-7DC7-4B42-B7E1-E500E624CAC3}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CCD76347-7DC7-4B42-B7E1-E500E624CAC3}.Release|Any CPU.Build.0 = Release|Any CPU - {CCD76347-7DC7-4B42-B7E1-E500E624CAC3}.Release|x86.ActiveCfg = Release|Any CPU - {D10A5FC0-11B4-4E70-86AA-8AEA52BD9798}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D10A5FC0-11B4-4E70-86AA-8AEA52BD9798}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D10A5FC0-11B4-4E70-86AA-8AEA52BD9798}.Debug|x86.ActiveCfg = Debug|x86 - {D10A5FC0-11B4-4E70-86AA-8AEA52BD9798}.Debug|x86.Build.0 = Debug|x86 - {D10A5FC0-11B4-4E70-86AA-8AEA52BD9798}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D10A5FC0-11B4-4E70-86AA-8AEA52BD9798}.Release|Any CPU.Build.0 = Release|Any CPU - {D10A5FC0-11B4-4E70-86AA-8AEA52BD9798}.Release|x86.ActiveCfg = Release|x86 - {D10A5FC0-11B4-4E70-86AA-8AEA52BD9798}.Release|x86.Build.0 = Release|x86 - {D63E53E4-A458-4C2F-914D-92F715F58ACE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D63E53E4-A458-4C2F-914D-92F715F58ACE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D63E53E4-A458-4C2F-914D-92F715F58ACE}.Debug|x86.ActiveCfg = Debug|x86 - {D63E53E4-A458-4C2F-914D-92F715F58ACE}.Debug|x86.Build.0 = Debug|x86 - {D63E53E4-A458-4C2F-914D-92F715F58ACE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D63E53E4-A458-4C2F-914D-92F715F58ACE}.Release|Any CPU.Build.0 = Release|Any CPU - {D63E53E4-A458-4C2F-914D-92F715F58ACE}.Release|x86.ActiveCfg = Release|x86 - {D63E53E4-A458-4C2F-914D-92F715F58ACE}.Release|x86.Build.0 = Release|x86 {DE3E5D4C-51AB-4E5E-BEE8-E636CEBFBA65}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {DE3E5D4C-51AB-4E5E-BEE8-E636CEBFBA65}.Debug|Any CPU.Build.0 = Debug|Any CPU {DE3E5D4C-51AB-4E5E-BEE8-E636CEBFBA65}.Debug|x86.ActiveCfg = Debug|x86 @@ -235,38 +89,14 @@ Global {DE3E5D4C-51AB-4E5E-BEE8-E636CEBFBA65}.Release|Any CPU.Build.0 = Release|Any CPU {DE3E5D4C-51AB-4E5E-BEE8-E636CEBFBA65}.Release|x86.ActiveCfg = Release|x86 {DE3E5D4C-51AB-4E5E-BEE8-E636CEBFBA65}.Release|x86.Build.0 = Release|x86 - {E2AF781D-D1E1-4512-BF2C-D6DA8D0F797F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E2AF781D-D1E1-4512-BF2C-D6DA8D0F797F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E2AF781D-D1E1-4512-BF2C-D6DA8D0F797F}.Debug|x86.ActiveCfg = Debug|x86 - {E2AF781D-D1E1-4512-BF2C-D6DA8D0F797F}.Debug|x86.Build.0 = Debug|x86 - {E2AF781D-D1E1-4512-BF2C-D6DA8D0F797F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E2AF781D-D1E1-4512-BF2C-D6DA8D0F797F}.Release|Any CPU.Build.0 = Release|Any CPU - {E2AF781D-D1E1-4512-BF2C-D6DA8D0F797F}.Release|x86.ActiveCfg = Release|x86 - {E2AF781D-D1E1-4512-BF2C-D6DA8D0F797F}.Release|x86.Build.0 = Release|x86 - {E7280DCA-7776-4A73-B9B5-41FD77FC8799}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E7280DCA-7776-4A73-B9B5-41FD77FC8799}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E7280DCA-7776-4A73-B9B5-41FD77FC8799}.Debug|x86.ActiveCfg = Debug|x86 - {E7280DCA-7776-4A73-B9B5-41FD77FC8799}.Debug|x86.Build.0 = Debug|x86 - {E7280DCA-7776-4A73-B9B5-41FD77FC8799}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E7280DCA-7776-4A73-B9B5-41FD77FC8799}.Release|Any CPU.Build.0 = Release|Any CPU - {E7280DCA-7776-4A73-B9B5-41FD77FC8799}.Release|x86.ActiveCfg = Release|x86 - {E7280DCA-7776-4A73-B9B5-41FD77FC8799}.Release|x86.Build.0 = Release|x86 - {F2854848-BF78-4A6D-9A2A-2AE2AFB70DF1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F2854848-BF78-4A6D-9A2A-2AE2AFB70DF1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F2854848-BF78-4A6D-9A2A-2AE2AFB70DF1}.Debug|x86.ActiveCfg = Debug|x86 - {F2854848-BF78-4A6D-9A2A-2AE2AFB70DF1}.Debug|x86.Build.0 = Debug|x86 - {F2854848-BF78-4A6D-9A2A-2AE2AFB70DF1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F2854848-BF78-4A6D-9A2A-2AE2AFB70DF1}.Release|Any CPU.Build.0 = Release|Any CPU - {F2854848-BF78-4A6D-9A2A-2AE2AFB70DF1}.Release|x86.ActiveCfg = Release|x86 - {F2854848-BF78-4A6D-9A2A-2AE2AFB70DF1}.Release|x86.Build.0 = Release|x86 - {F61679A9-E5DE-468A-B5A4-05F92D0143D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F61679A9-E5DE-468A-B5A4-05F92D0143D2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F61679A9-E5DE-468A-B5A4-05F92D0143D2}.Debug|x86.ActiveCfg = Debug|x86 - {F61679A9-E5DE-468A-B5A4-05F92D0143D2}.Debug|x86.Build.0 = Debug|x86 - {F61679A9-E5DE-468A-B5A4-05F92D0143D2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F61679A9-E5DE-468A-B5A4-05F92D0143D2}.Release|Any CPU.Build.0 = Release|Any CPU - {F61679A9-E5DE-468A-B5A4-05F92D0143D2}.Release|x86.ActiveCfg = Release|x86 - {F61679A9-E5DE-468A-B5A4-05F92D0143D2}.Release|x86.Build.0 = Release|x86 + {10D2D1B7-C664-41D8-9B3A-00040C3D421B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {10D2D1B7-C664-41D8-9B3A-00040C3D421B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {10D2D1B7-C664-41D8-9B3A-00040C3D421B}.Debug|x86.ActiveCfg = Debug|x86 + {10D2D1B7-C664-41D8-9B3A-00040C3D421B}.Debug|x86.Build.0 = Debug|x86 + {10D2D1B7-C664-41D8-9B3A-00040C3D421B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {10D2D1B7-C664-41D8-9B3A-00040C3D421B}.Release|Any CPU.Build.0 = Release|Any CPU + {10D2D1B7-C664-41D8-9B3A-00040C3D421B}.Release|x86.ActiveCfg = Release|x86 + {10D2D1B7-C664-41D8-9B3A-00040C3D421B}.Release|x86.Build.0 = Release|x86 {FC9B7611-836F-4127-8B44-A7C31F506807}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {FC9B7611-836F-4127-8B44-A7C31F506807}.Debug|Any CPU.Build.0 = Debug|Any CPU {FC9B7611-836F-4127-8B44-A7C31F506807}.Debug|x86.ActiveCfg = Debug|x86 @@ -275,14 +105,180 @@ Global {FC9B7611-836F-4127-8B44-A7C31F506807}.Release|Any CPU.Build.0 = Release|Any CPU {FC9B7611-836F-4127-8B44-A7C31F506807}.Release|x86.ActiveCfg = Release|x86 {FC9B7611-836F-4127-8B44-A7C31F506807}.Release|x86.Build.0 = Release|x86 - {6BA21DCB-1701-4936-B177-3B6D4DE3474E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6BA21DCB-1701-4936-B177-3B6D4DE3474E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6BA21DCB-1701-4936-B177-3B6D4DE3474E}.Debug|x86.ActiveCfg = Debug|x86 - {6BA21DCB-1701-4936-B177-3B6D4DE3474E}.Debug|x86.Build.0 = Debug|x86 - {6BA21DCB-1701-4936-B177-3B6D4DE3474E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6BA21DCB-1701-4936-B177-3B6D4DE3474E}.Release|Any CPU.Build.0 = Release|Any CPU - {6BA21DCB-1701-4936-B177-3B6D4DE3474E}.Release|x86.ActiveCfg = Release|x86 - {6BA21DCB-1701-4936-B177-3B6D4DE3474E}.Release|x86.Build.0 = Release|x86 + {F61679A9-E5DE-468A-B5A4-05F92D0143D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F61679A9-E5DE-468A-B5A4-05F92D0143D2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F61679A9-E5DE-468A-B5A4-05F92D0143D2}.Debug|x86.ActiveCfg = Debug|x86 + {F61679A9-E5DE-468A-B5A4-05F92D0143D2}.Debug|x86.Build.0 = Debug|x86 + {F61679A9-E5DE-468A-B5A4-05F92D0143D2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F61679A9-E5DE-468A-B5A4-05F92D0143D2}.Release|Any CPU.Build.0 = Release|Any CPU + {F61679A9-E5DE-468A-B5A4-05F92D0143D2}.Release|x86.ActiveCfg = Release|x86 + {F61679A9-E5DE-468A-B5A4-05F92D0143D2}.Release|x86.Build.0 = Release|x86 + {19ECCE09-B5EB-406C-8C57-BAC66997D469}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {19ECCE09-B5EB-406C-8C57-BAC66997D469}.Debug|Any CPU.Build.0 = Debug|Any CPU + {19ECCE09-B5EB-406C-8C57-BAC66997D469}.Debug|x86.ActiveCfg = Debug|x86 + {19ECCE09-B5EB-406C-8C57-BAC66997D469}.Debug|x86.Build.0 = Debug|x86 + {19ECCE09-B5EB-406C-8C57-BAC66997D469}.Release|Any CPU.ActiveCfg = Release|Any CPU + {19ECCE09-B5EB-406C-8C57-BAC66997D469}.Release|Any CPU.Build.0 = Release|Any CPU + {19ECCE09-B5EB-406C-8C57-BAC66997D469}.Release|x86.ActiveCfg = Release|x86 + {19ECCE09-B5EB-406C-8C57-BAC66997D469}.Release|x86.Build.0 = Release|x86 + {94484FDB-2EFA-4CF0-9BE6-A561157B4F87}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {94484FDB-2EFA-4CF0-9BE6-A561157B4F87}.Debug|Any CPU.Build.0 = Debug|Any CPU + {94484FDB-2EFA-4CF0-9BE6-A561157B4F87}.Debug|x86.ActiveCfg = Debug|x86 + {94484FDB-2EFA-4CF0-9BE6-A561157B4F87}.Debug|x86.Build.0 = Debug|x86 + {94484FDB-2EFA-4CF0-9BE6-A561157B4F87}.Release|Any CPU.ActiveCfg = Release|Any CPU + {94484FDB-2EFA-4CF0-9BE6-A561157B4F87}.Release|Any CPU.Build.0 = Release|Any CPU + {94484FDB-2EFA-4CF0-9BE6-A561157B4F87}.Release|x86.ActiveCfg = Release|x86 + {94484FDB-2EFA-4CF0-9BE6-A561157B4F87}.Release|x86.Build.0 = Release|x86 + {47FE73E1-0832-44F7-96B9-2580273206C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {47FE73E1-0832-44F7-96B9-2580273206C3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {47FE73E1-0832-44F7-96B9-2580273206C3}.Debug|x86.ActiveCfg = Debug|x86 + {47FE73E1-0832-44F7-96B9-2580273206C3}.Debug|x86.Build.0 = Debug|x86 + {47FE73E1-0832-44F7-96B9-2580273206C3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {47FE73E1-0832-44F7-96B9-2580273206C3}.Release|Any CPU.Build.0 = Release|Any CPU + {47FE73E1-0832-44F7-96B9-2580273206C3}.Release|x86.ActiveCfg = Release|x86 + {47FE73E1-0832-44F7-96B9-2580273206C3}.Release|x86.Build.0 = Release|x86 + {D10A5FC0-11B4-4E70-86AA-8AEA52BD9798}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D10A5FC0-11B4-4E70-86AA-8AEA52BD9798}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D10A5FC0-11B4-4E70-86AA-8AEA52BD9798}.Debug|x86.ActiveCfg = Debug|x86 + {D10A5FC0-11B4-4E70-86AA-8AEA52BD9798}.Debug|x86.Build.0 = Debug|x86 + {D10A5FC0-11B4-4E70-86AA-8AEA52BD9798}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D10A5FC0-11B4-4E70-86AA-8AEA52BD9798}.Release|Any CPU.Build.0 = Release|Any CPU + {D10A5FC0-11B4-4E70-86AA-8AEA52BD9798}.Release|x86.ActiveCfg = Release|x86 + {D10A5FC0-11B4-4E70-86AA-8AEA52BD9798}.Release|x86.Build.0 = Release|x86 + {C03F6DFD-805A-4BE0-9338-64870ADDB4A2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C03F6DFD-805A-4BE0-9338-64870ADDB4A2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C03F6DFD-805A-4BE0-9338-64870ADDB4A2}.Debug|x86.ActiveCfg = Debug|x86 + {C03F6DFD-805A-4BE0-9338-64870ADDB4A2}.Debug|x86.Build.0 = Debug|x86 + {C03F6DFD-805A-4BE0-9338-64870ADDB4A2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C03F6DFD-805A-4BE0-9338-64870ADDB4A2}.Release|Any CPU.Build.0 = Release|Any CPU + {C03F6DFD-805A-4BE0-9338-64870ADDB4A2}.Release|x86.ActiveCfg = Release|x86 + {C03F6DFD-805A-4BE0-9338-64870ADDB4A2}.Release|x86.Build.0 = Release|x86 + {81765A64-3661-4E3E-B850-2F6F87A51F74}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {81765A64-3661-4E3E-B850-2F6F87A51F74}.Debug|Any CPU.Build.0 = Debug|Any CPU + {81765A64-3661-4E3E-B850-2F6F87A51F74}.Debug|x86.ActiveCfg = Debug|x86 + {81765A64-3661-4E3E-B850-2F6F87A51F74}.Debug|x86.Build.0 = Debug|x86 + {81765A64-3661-4E3E-B850-2F6F87A51F74}.Release|Any CPU.ActiveCfg = Release|Any CPU + {81765A64-3661-4E3E-B850-2F6F87A51F74}.Release|Any CPU.Build.0 = Release|Any CPU + {81765A64-3661-4E3E-B850-2F6F87A51F74}.Release|x86.ActiveCfg = Release|x86 + {81765A64-3661-4E3E-B850-2F6F87A51F74}.Release|x86.Build.0 = Release|x86 + {E2AF781D-D1E1-4512-BF2C-D6DA8D0F797F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E2AF781D-D1E1-4512-BF2C-D6DA8D0F797F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E2AF781D-D1E1-4512-BF2C-D6DA8D0F797F}.Debug|x86.ActiveCfg = Debug|x86 + {E2AF781D-D1E1-4512-BF2C-D6DA8D0F797F}.Debug|x86.Build.0 = Debug|x86 + {E2AF781D-D1E1-4512-BF2C-D6DA8D0F797F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E2AF781D-D1E1-4512-BF2C-D6DA8D0F797F}.Release|Any CPU.Build.0 = Release|Any CPU + {E2AF781D-D1E1-4512-BF2C-D6DA8D0F797F}.Release|x86.ActiveCfg = Release|x86 + {E2AF781D-D1E1-4512-BF2C-D6DA8D0F797F}.Release|x86.Build.0 = Release|x86 + {BAE27510-8B5D-44B2-B33E-372A98908041}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BAE27510-8B5D-44B2-B33E-372A98908041}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BAE27510-8B5D-44B2-B33E-372A98908041}.Debug|x86.ActiveCfg = Debug|x86 + {BAE27510-8B5D-44B2-B33E-372A98908041}.Debug|x86.Build.0 = Debug|x86 + {BAE27510-8B5D-44B2-B33E-372A98908041}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BAE27510-8B5D-44B2-B33E-372A98908041}.Release|Any CPU.Build.0 = Release|Any CPU + {BAE27510-8B5D-44B2-B33E-372A98908041}.Release|x86.ActiveCfg = Release|x86 + {BAE27510-8B5D-44B2-B33E-372A98908041}.Release|x86.Build.0 = Release|x86 + {1BFAE226-8364-4086-825C-BB83F6F3EE4C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1BFAE226-8364-4086-825C-BB83F6F3EE4C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1BFAE226-8364-4086-825C-BB83F6F3EE4C}.Debug|x86.ActiveCfg = Debug|x86 + {1BFAE226-8364-4086-825C-BB83F6F3EE4C}.Debug|x86.Build.0 = Debug|x86 + {1BFAE226-8364-4086-825C-BB83F6F3EE4C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1BFAE226-8364-4086-825C-BB83F6F3EE4C}.Release|Any CPU.Build.0 = Release|Any CPU + {1BFAE226-8364-4086-825C-BB83F6F3EE4C}.Release|x86.ActiveCfg = Release|x86 + {1BFAE226-8364-4086-825C-BB83F6F3EE4C}.Release|x86.Build.0 = Release|x86 + {B60D0993-B0C5-457A-90D9-DB6EEB33CE47}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B60D0993-B0C5-457A-90D9-DB6EEB33CE47}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B60D0993-B0C5-457A-90D9-DB6EEB33CE47}.Debug|x86.ActiveCfg = Debug|x86 + {B60D0993-B0C5-457A-90D9-DB6EEB33CE47}.Debug|x86.Build.0 = Debug|x86 + {B60D0993-B0C5-457A-90D9-DB6EEB33CE47}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B60D0993-B0C5-457A-90D9-DB6EEB33CE47}.Release|Any CPU.Build.0 = Release|Any CPU + {B60D0993-B0C5-457A-90D9-DB6EEB33CE47}.Release|x86.ActiveCfg = Release|x86 + {B60D0993-B0C5-457A-90D9-DB6EEB33CE47}.Release|x86.Build.0 = Release|x86 + {F2854848-BF78-4A6D-9A2A-2AE2AFB70DF1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F2854848-BF78-4A6D-9A2A-2AE2AFB70DF1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F2854848-BF78-4A6D-9A2A-2AE2AFB70DF1}.Debug|x86.ActiveCfg = Debug|x86 + {F2854848-BF78-4A6D-9A2A-2AE2AFB70DF1}.Debug|x86.Build.0 = Debug|x86 + {F2854848-BF78-4A6D-9A2A-2AE2AFB70DF1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F2854848-BF78-4A6D-9A2A-2AE2AFB70DF1}.Release|Any CPU.Build.0 = Release|Any CPU + {F2854848-BF78-4A6D-9A2A-2AE2AFB70DF1}.Release|x86.ActiveCfg = Release|x86 + {F2854848-BF78-4A6D-9A2A-2AE2AFB70DF1}.Release|x86.Build.0 = Release|x86 + {E7280DCA-7776-4A73-B9B5-41FD77FC8799}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E7280DCA-7776-4A73-B9B5-41FD77FC8799}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E7280DCA-7776-4A73-B9B5-41FD77FC8799}.Debug|x86.ActiveCfg = Debug|x86 + {E7280DCA-7776-4A73-B9B5-41FD77FC8799}.Debug|x86.Build.0 = Debug|x86 + {E7280DCA-7776-4A73-B9B5-41FD77FC8799}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E7280DCA-7776-4A73-B9B5-41FD77FC8799}.Release|Any CPU.Build.0 = Release|Any CPU + {E7280DCA-7776-4A73-B9B5-41FD77FC8799}.Release|x86.ActiveCfg = Release|x86 + {E7280DCA-7776-4A73-B9B5-41FD77FC8799}.Release|x86.Build.0 = Release|x86 + {C5899F45-B0FF-483C-9D38-24A9FCAAB237}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C5899F45-B0FF-483C-9D38-24A9FCAAB237}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C5899F45-B0FF-483C-9D38-24A9FCAAB237}.Debug|x86.ActiveCfg = Debug|x86 + {C5899F45-B0FF-483C-9D38-24A9FCAAB237}.Debug|x86.Build.0 = Debug|x86 + {C5899F45-B0FF-483C-9D38-24A9FCAAB237}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C5899F45-B0FF-483C-9D38-24A9FCAAB237}.Release|Any CPU.Build.0 = Release|Any CPU + {C5899F45-B0FF-483C-9D38-24A9FCAAB237}.Release|x86.ActiveCfg = Release|x86 + {C5899F45-B0FF-483C-9D38-24A9FCAAB237}.Release|x86.Build.0 = Release|x86 + {0CA86ECF-5BEC-4909-B4F6-110A03B30B92}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0CA86ECF-5BEC-4909-B4F6-110A03B30B92}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0CA86ECF-5BEC-4909-B4F6-110A03B30B92}.Debug|x86.ActiveCfg = Debug|x86 + {0CA86ECF-5BEC-4909-B4F6-110A03B30B92}.Debug|x86.Build.0 = Debug|x86 + {0CA86ECF-5BEC-4909-B4F6-110A03B30B92}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0CA86ECF-5BEC-4909-B4F6-110A03B30B92}.Release|Any CPU.Build.0 = Release|Any CPU + {0CA86ECF-5BEC-4909-B4F6-110A03B30B92}.Release|x86.ActiveCfg = Release|x86 + {0CA86ECF-5BEC-4909-B4F6-110A03B30B92}.Release|x86.Build.0 = Release|x86 + {D63E53E4-A458-4C2F-914D-92F715F58ACE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D63E53E4-A458-4C2F-914D-92F715F58ACE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D63E53E4-A458-4C2F-914D-92F715F58ACE}.Debug|x86.ActiveCfg = Debug|x86 + {D63E53E4-A458-4C2F-914D-92F715F58ACE}.Debug|x86.Build.0 = Debug|x86 + {D63E53E4-A458-4C2F-914D-92F715F58ACE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D63E53E4-A458-4C2F-914D-92F715F58ACE}.Release|Any CPU.Build.0 = Release|Any CPU + {D63E53E4-A458-4C2F-914D-92F715F58ACE}.Release|x86.ActiveCfg = Release|x86 + {D63E53E4-A458-4C2F-914D-92F715F58ACE}.Release|x86.Build.0 = Release|x86 + {4D012CB1-4B92-47F4-89B7-BF80A73A2E99}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4D012CB1-4B92-47F4-89B7-BF80A73A2E99}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4D012CB1-4B92-47F4-89B7-BF80A73A2E99}.Debug|x86.ActiveCfg = Debug|x86 + {4D012CB1-4B92-47F4-89B7-BF80A73A2E99}.Debug|x86.Build.0 = Debug|x86 + {4D012CB1-4B92-47F4-89B7-BF80A73A2E99}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4D012CB1-4B92-47F4-89B7-BF80A73A2E99}.Release|Any CPU.Build.0 = Release|Any CPU + {4D012CB1-4B92-47F4-89B7-BF80A73A2E99}.Release|x86.ActiveCfg = Release|x86 + {4D012CB1-4B92-47F4-89B7-BF80A73A2E99}.Release|x86.Build.0 = Release|x86 + {7886BA79-A38A-4288-8B8A-9F29D0E15AC0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7886BA79-A38A-4288-8B8A-9F29D0E15AC0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7886BA79-A38A-4288-8B8A-9F29D0E15AC0}.Debug|x86.ActiveCfg = Debug|x86 + {7886BA79-A38A-4288-8B8A-9F29D0E15AC0}.Debug|x86.Build.0 = Debug|x86 + {7886BA79-A38A-4288-8B8A-9F29D0E15AC0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7886BA79-A38A-4288-8B8A-9F29D0E15AC0}.Release|Any CPU.Build.0 = Release|Any CPU + {7886BA79-A38A-4288-8B8A-9F29D0E15AC0}.Release|x86.ActiveCfg = Release|x86 + {7886BA79-A38A-4288-8B8A-9F29D0E15AC0}.Release|x86.Build.0 = Release|x86 + {52826615-7964-47FE-B4B3-1B2DBDF605B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {52826615-7964-47FE-B4B3-1B2DBDF605B9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {52826615-7964-47FE-B4B3-1B2DBDF605B9}.Debug|x86.ActiveCfg = Debug|x86 + {52826615-7964-47FE-B4B3-1B2DBDF605B9}.Debug|x86.Build.0 = Debug|x86 + {52826615-7964-47FE-B4B3-1B2DBDF605B9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {52826615-7964-47FE-B4B3-1B2DBDF605B9}.Release|Any CPU.Build.0 = Release|Any CPU + {52826615-7964-47FE-B4B3-1B2DBDF605B9}.Release|x86.ActiveCfg = Release|x86 + {52826615-7964-47FE-B4B3-1B2DBDF605B9}.Release|x86.Build.0 = Release|x86 + {C0270709-2A40-43B5-8CF1-69581B9FA2A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C0270709-2A40-43B5-8CF1-69581B9FA2A1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C0270709-2A40-43B5-8CF1-69581B9FA2A1}.Debug|x86.ActiveCfg = Debug|x86 + {C0270709-2A40-43B5-8CF1-69581B9FA2A1}.Debug|x86.Build.0 = Debug|x86 + {C0270709-2A40-43B5-8CF1-69581B9FA2A1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C0270709-2A40-43B5-8CF1-69581B9FA2A1}.Release|Any CPU.Build.0 = Release|Any CPU + {C0270709-2A40-43B5-8CF1-69581B9FA2A1}.Release|x86.ActiveCfg = Release|x86 + {C0270709-2A40-43B5-8CF1-69581B9FA2A1}.Release|x86.Build.0 = Release|x86 + {CCD76347-7DC7-4B42-B7E1-E500E624CAC3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CCD76347-7DC7-4B42-B7E1-E500E624CAC3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CCD76347-7DC7-4B42-B7E1-E500E624CAC3}.Debug|x86.ActiveCfg = Debug|Any CPU + {CCD76347-7DC7-4B42-B7E1-E500E624CAC3}.Debug|x86.Build.0 = Debug|Any CPU + {CCD76347-7DC7-4B42-B7E1-E500E624CAC3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CCD76347-7DC7-4B42-B7E1-E500E624CAC3}.Release|Any CPU.Build.0 = Release|Any CPU + {CCD76347-7DC7-4B42-B7E1-E500E624CAC3}.Release|x86.ActiveCfg = Release|Any CPU + {42C91180-11EB-4590-82EA-80FE9D4DEBEC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {42C91180-11EB-4590-82EA-80FE9D4DEBEC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {42C91180-11EB-4590-82EA-80FE9D4DEBEC}.Debug|x86.ActiveCfg = Debug|Any CPU + {42C91180-11EB-4590-82EA-80FE9D4DEBEC}.Debug|x86.Build.0 = Debug|Any CPU + {42C91180-11EB-4590-82EA-80FE9D4DEBEC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {42C91180-11EB-4590-82EA-80FE9D4DEBEC}.Release|Any CPU.Build.0 = Release|Any CPU + {42C91180-11EB-4590-82EA-80FE9D4DEBEC}.Release|x86.ActiveCfg = Release|Any CPU {FF2BF37C-E502-4C98-BEA0-701671DDFA08}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {FF2BF37C-E502-4C98-BEA0-701671DDFA08}.Debug|Any CPU.Build.0 = Debug|Any CPU {FF2BF37C-E502-4C98-BEA0-701671DDFA08}.Debug|x86.ActiveCfg = Debug|x86 @@ -291,6 +287,14 @@ Global {FF2BF37C-E502-4C98-BEA0-701671DDFA08}.Release|Any CPU.Build.0 = Release|Any CPU {FF2BF37C-E502-4C98-BEA0-701671DDFA08}.Release|x86.ActiveCfg = Release|x86 {FF2BF37C-E502-4C98-BEA0-701671DDFA08}.Release|x86.Build.0 = Release|x86 + {19E661D2-C5DA-4F35-B3EE-7586E5734B5F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {19E661D2-C5DA-4F35-B3EE-7586E5734B5F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {19E661D2-C5DA-4F35-B3EE-7586E5734B5F}.Debug|x86.ActiveCfg = Debug|x86 + {19E661D2-C5DA-4F35-B3EE-7586E5734B5F}.Debug|x86.Build.0 = Debug|x86 + {19E661D2-C5DA-4F35-B3EE-7586E5734B5F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {19E661D2-C5DA-4F35-B3EE-7586E5734B5F}.Release|Any CPU.Build.0 = Release|Any CPU + {19E661D2-C5DA-4F35-B3EE-7586E5734B5F}.Release|x86.ActiveCfg = Release|x86 + {19E661D2-C5DA-4F35-B3EE-7586E5734B5F}.Release|x86.Build.0 = Release|x86 {17566860-3D98-4604-AA5B-47661F75609F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {17566860-3D98-4604-AA5B-47661F75609F}.Debug|Any CPU.Build.0 = Debug|Any CPU {17566860-3D98-4604-AA5B-47661F75609F}.Debug|x86.ActiveCfg = Debug|x86 @@ -307,27 +311,34 @@ Global {33FD1D24-C28F-4C71-933F-98F1586EA76C}.Release|Any CPU.Build.0 = Release|Any CPU {33FD1D24-C28F-4C71-933F-98F1586EA76C}.Release|x86.ActiveCfg = Release|x86 {33FD1D24-C28F-4C71-933F-98F1586EA76C}.Release|x86.Build.0 = Release|x86 - {19E661D2-C5DA-4F35-B3EE-7586E5734B5F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {19E661D2-C5DA-4F35-B3EE-7586E5734B5F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {19E661D2-C5DA-4F35-B3EE-7586E5734B5F}.Debug|x86.ActiveCfg = Debug|x86 - {19E661D2-C5DA-4F35-B3EE-7586E5734B5F}.Debug|x86.Build.0 = Debug|x86 - {19E661D2-C5DA-4F35-B3EE-7586E5734B5F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {19E661D2-C5DA-4F35-B3EE-7586E5734B5F}.Release|Any CPU.Build.0 = Release|Any CPU - {19E661D2-C5DA-4F35-B3EE-7586E5734B5F}.Release|x86.ActiveCfg = Release|x86 - {19E661D2-C5DA-4F35-B3EE-7586E5734B5F}.Release|x86.Build.0 = Release|x86 - EndGlobalSection - GlobalSection(MonoDevelopProperties) = preSolution - StartupItem = Duplicati\GUI\Duplicati.csproj - Policies = $0 - $0.StandardHeader = $1 - $1.Text = @ Copyright (C) 2011, Kenneth Skovhede\r\n http://www.hexad.dk, opensource@hexad.dk\n \n This library is free software; you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as\n published by the Free Software Foundation; either version 2.1 of the\n License, or (at your option) any later version.\n\n This library is distributed in the hope that it will be useful, but\n WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public\n License along with this library; if not, write to the Free Software\n Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - $1.IncludeInNewFiles = True EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection - GlobalSection(SubversionScc) = preSolution - Svn-Managed = True - Manager = AnkhSVN - Subversion Support for Visual Studio + GlobalSection(MonoDevelopProperties) = preSolution + StartupItem = Duplicati\Server\Duplicati.Server.csproj + Policies = $0 + $0.StandardHeader = $1 + $1.Text = @ Copyright (C) 2011, Kenneth Skovhede\r\n http://www.hexad.dk, opensource@hexad.dk\n \n This library is free software; you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as\n published by the Free Software Foundation; either version 2.1 of the\n License, or (at your option) any later version.\n\n This library is distributed in the hope that it will be useful, but\n WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public\n License along with this library; if not, write to the Free Software\n Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + $1.IncludeInNewFiles = True + $0.DotNetNamingPolicy = $2 + $2.DirectoryNamespaceAssociation = None + $2.ResourceNamePolicy = FileFormatDefault + $0.TextStylePolicy = $3 + $3.FileWidth = 120 + $3.EolMarker = Windows + $3.inheritsSet = VisualStudio + $3.inheritsScope = text/plain + $3.scope = text/x-csharp + $0.CSharpFormattingPolicy = $4 + $4.BeforeMethodCallParentheses = False + $4.BeforeConstructorDeclarationParentheses = False + $4.BeforeIndexerDeclarationBracket = False + $4.BeforeDelegateDeclarationParentheses = False + $4.NewParentheses = False + $4.SpacesBeforeBrackets = False + $4.inheritsSet = Mono + $4.inheritsScope = text/x-csharp + $4.scope = text/x-csharp EndGlobalSection EndGlobal diff --git a/Duplicati/GUI/Duplicati.GUI.TrayIcon/Duplicati.GUI.TrayIcon.csproj b/Duplicati/GUI/Duplicati.GUI.TrayIcon/Duplicati.GUI.TrayIcon.csproj index 57760743b..606c39e28 100644 --- a/Duplicati/GUI/Duplicati.GUI.TrayIcon/Duplicati.GUI.TrayIcon.csproj +++ b/Duplicati/GUI/Duplicati.GUI.TrayIcon/Duplicati.GUI.TrayIcon.csproj @@ -1,4 +1,4 @@ - + Debug @@ -11,6 +11,21 @@ Duplicati.GUI.TrayIcon Duplicati.GUI.TrayIcon 512 + false + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + true x86 @@ -35,12 +50,14 @@ bin\Debug - none + full true true true 4 false + DEBUG + true bin\Release @@ -51,6 +68,15 @@ true 4 + + Duplicati.GUI.TrayIcon.Program + + + true + + + Duplicati.snk + @@ -63,17 +89,28 @@ - + + + + True + True + WindowsMainForm.resx + + Form - - MainForm.cs + + WindowsMainForm.cs - - MainForm.cs + + ResXFileCodeGenerator + WindowsMainForm.Designer.cs + + + WindowsMainForm.cs ResXFileCodeGenerator @@ -83,7 +120,10 @@ True Resources.resx + True + + SettingsSingleFileGenerator Settings.Designer.cs @@ -95,11 +135,94 @@ + + {19E661D2-C5DA-4F35-B3EE-7586E5734B5F} + Duplicati.Server + {33FD1D24-C28F-4C71-933F-98F1586EA76C} Duplicati.Server.Serialization + + + False + Microsoft .NET Framework 4 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + false + + + False + Windows Installer 3.1 + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -68,9 +69,10 @@ - + + @@ -85,9 +87,10 @@ - + + @@ -109,9 +112,67 @@ 2.0 - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + ..\Resources\Clock05.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\Clock15.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\Clock30.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\Clock60.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\CloseMenuIcon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\Delay.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\Pause.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\Play.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\SettingsMenuIcon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\StatusMenuIcon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\Stop.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\Throttle.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\TrayNormal.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\TrayNormalError.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\TrayNormalPause.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\TrayNormalWarning.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\TrayWorking.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\TrayWorkingPause.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\WizardMenuIcon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + \ No newline at end of file diff --git a/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/Clock05.png b/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/Clock05.png new file mode 100644 index 000000000..6873b0b7f Binary files /dev/null and b/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/Clock05.png differ diff --git a/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/Clock15.png b/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/Clock15.png new file mode 100644 index 000000000..78fe0d0ac Binary files /dev/null and b/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/Clock15.png differ diff --git a/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/Clock30.png b/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/Clock30.png new file mode 100644 index 000000000..ca138602a Binary files /dev/null and b/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/Clock30.png differ diff --git a/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/Clock60.png b/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/Clock60.png new file mode 100644 index 000000000..7f0915d73 Binary files /dev/null and b/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/Clock60.png differ diff --git a/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/CloseMenuIcon.png b/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/CloseMenuIcon.png new file mode 100644 index 000000000..f41600e44 Binary files /dev/null and b/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/CloseMenuIcon.png differ diff --git a/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/Delay.png b/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/Delay.png new file mode 100644 index 000000000..e8376aba0 Binary files /dev/null and b/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/Delay.png differ diff --git a/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/Pause.png b/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/Pause.png new file mode 100644 index 000000000..3d717e46a Binary files /dev/null and b/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/Pause.png differ diff --git a/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/Play.png b/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/Play.png new file mode 100644 index 000000000..f513b25ff Binary files /dev/null and b/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/Play.png differ diff --git a/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/SettingsMenuIcon.png b/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/SettingsMenuIcon.png new file mode 100644 index 000000000..5f0cad037 Binary files /dev/null and b/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/SettingsMenuIcon.png differ diff --git a/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/StatusMenuIcon.png b/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/StatusMenuIcon.png new file mode 100644 index 000000000..c342475a2 Binary files /dev/null and b/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/StatusMenuIcon.png differ diff --git a/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/Stop.png b/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/Stop.png new file mode 100644 index 000000000..635251190 Binary files /dev/null and b/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/Stop.png differ diff --git a/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/Throttle.png b/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/Throttle.png new file mode 100644 index 000000000..5c09d3849 Binary files /dev/null and b/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/Throttle.png differ diff --git a/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/TrayNormal.ico b/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/TrayNormal.ico new file mode 100644 index 000000000..f4b15562a Binary files /dev/null and b/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/TrayNormal.ico differ diff --git a/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/TrayNormalError.ico b/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/TrayNormalError.ico new file mode 100644 index 000000000..d1c54b982 Binary files /dev/null and b/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/TrayNormalError.ico differ diff --git a/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/TrayNormalPause.ico b/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/TrayNormalPause.ico new file mode 100644 index 000000000..cfde181ac Binary files /dev/null and b/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/TrayNormalPause.ico differ diff --git a/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/TrayNormalWarning.ico b/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/TrayNormalWarning.ico new file mode 100644 index 000000000..90a9b030e Binary files /dev/null and b/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/TrayNormalWarning.ico differ diff --git a/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/TrayWorking.ico b/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/TrayWorking.ico new file mode 100644 index 000000000..d04740be3 Binary files /dev/null and b/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/TrayWorking.ico differ diff --git a/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/TrayWorkingPause.ico b/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/TrayWorkingPause.ico new file mode 100644 index 000000000..eaad5208b Binary files /dev/null and b/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/TrayWorkingPause.ico differ diff --git a/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/WizardMenuIcon.png b/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/WizardMenuIcon.png new file mode 100644 index 000000000..a72337d3d Binary files /dev/null and b/Duplicati/GUI/Duplicati.GUI.TrayIcon/Resources/WizardMenuIcon.png differ diff --git a/Duplicati/GUI/Duplicati.GUI.TrayIcon/SerializationHelper.cs b/Duplicati/GUI/Duplicati.GUI.TrayIcon/SerializationHelper.cs new file mode 100644 index 000000000..f572accd7 --- /dev/null +++ b/Duplicati/GUI/Duplicati.GUI.TrayIcon/SerializationHelper.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Duplicati.GUI.TrayIcon +{ + public enum RunnerState + { + Started, + Suspended, + Running, + Stopped, + } + + public enum LiveControlState + { + Running, + Paused + } +} diff --git a/Duplicati/GUI/Duplicati.GUI.TrayIcon/Strings/WindowsMainForm.Designer.cs b/Duplicati/GUI/Duplicati.GUI.TrayIcon/Strings/WindowsMainForm.Designer.cs new file mode 100644 index 000000000..eda351cb2 --- /dev/null +++ b/Duplicati/GUI/Duplicati.GUI.TrayIcon/Strings/WindowsMainForm.Designer.cs @@ -0,0 +1,81 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.239 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Duplicati.GUI.TrayIcon.Strings { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class WindowsMainForm { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal WindowsMainForm() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Duplicati.GUI.TrayIcon.Strings.WindowsMainForm", typeof(WindowsMainForm).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Pause. + /// + internal static string PauseMenuText { + get { + return ResourceManager.GetString("PauseMenuText", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Resume. + /// + internal static string ResumeMenuText { + get { + return ResourceManager.GetString("ResumeMenuText", resourceCulture); + } + } + } +} diff --git a/Duplicati/GUI/Duplicati.GUI.TrayIcon/Strings/WindowsMainForm.resx b/Duplicati/GUI/Duplicati.GUI.TrayIcon/Strings/WindowsMainForm.resx new file mode 100644 index 000000000..e88f78c78 --- /dev/null +++ b/Duplicati/GUI/Duplicati.GUI.TrayIcon/Strings/WindowsMainForm.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Pause + + + Resume + + \ No newline at end of file diff --git a/Duplicati/GUI/Duplicati.GUI.TrayIcon/WindowsMainForm.Designer.cs b/Duplicati/GUI/Duplicati.GUI.TrayIcon/WindowsMainForm.Designer.cs new file mode 100644 index 000000000..7767e0e20 --- /dev/null +++ b/Duplicati/GUI/Duplicati.GUI.TrayIcon/WindowsMainForm.Designer.cs @@ -0,0 +1,251 @@ +namespace Duplicati.GUI.TrayIcon +{ + partial class WindowsMainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(WindowsMainForm)); + this.label1 = new System.Windows.Forms.Label(); + this.TrayMenu = new System.Windows.Forms.ContextMenuStrip(this.components); + this.statusToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.wizardToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); + this.optionsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator(); + this.controlToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.pauseToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.pausePeriodToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.DelayDuration05Menu = new System.Windows.Forms.ToolStripMenuItem(); + this.DelayDuration15Menu = new System.Windows.Forms.ToolStripMenuItem(); + this.DelayDuration30Menu = new System.Windows.Forms.ToolStripMenuItem(); + this.DelayDuration60Menu = new System.Windows.Forms.ToolStripMenuItem(); + this.stopToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.throttleOptionsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator(); + this.quitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.TrayIcon = new System.Windows.Forms.NotifyIcon(this.components); + this.TrayMenu.SuspendLayout(); + this.SuspendLayout(); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.ImeMode = System.Windows.Forms.ImeMode.NoControl; + this.label1.Location = new System.Drawing.Point(8, 8); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(123, 13); + this.label1.TabIndex = 1; + this.label1.Text = "Duplicati dummy window"; + // + // TrayMenu + // + this.TrayMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.statusToolStripMenuItem, + this.wizardToolStripMenuItem, + this.toolStripSeparator1, + this.optionsToolStripMenuItem, + this.toolStripSeparator2, + this.controlToolStripMenuItem, + this.toolStripSeparator3, + this.quitToolStripMenuItem}); + this.TrayMenu.Name = "TrayMenu"; + this.TrayMenu.Size = new System.Drawing.Size(153, 154); + // + // statusToolStripMenuItem + // + this.statusToolStripMenuItem.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Bold); + this.statusToolStripMenuItem.Image = global::Duplicati.GUI.TrayIcon.Properties.Resources.StatusMenuIcon; + this.statusToolStripMenuItem.Name = "statusToolStripMenuItem"; + this.statusToolStripMenuItem.Size = new System.Drawing.Size(152, 22); + this.statusToolStripMenuItem.Text = "Status"; + this.statusToolStripMenuItem.Click += new System.EventHandler(this.statusToolStripMenuItem_Click); + // + // wizardToolStripMenuItem + // + this.wizardToolStripMenuItem.Image = global::Duplicati.GUI.TrayIcon.Properties.Resources.WizardMenuIcon; + this.wizardToolStripMenuItem.Name = "wizardToolStripMenuItem"; + this.wizardToolStripMenuItem.Size = new System.Drawing.Size(152, 22); + this.wizardToolStripMenuItem.Text = "Wizard..."; + // + // toolStripSeparator1 + // + this.toolStripSeparator1.Name = "toolStripSeparator1"; + this.toolStripSeparator1.Size = new System.Drawing.Size(149, 6); + // + // optionsToolStripMenuItem + // + this.optionsToolStripMenuItem.Image = global::Duplicati.GUI.TrayIcon.Properties.Resources.SettingsMenuIcon; + this.optionsToolStripMenuItem.Name = "optionsToolStripMenuItem"; + this.optionsToolStripMenuItem.Size = new System.Drawing.Size(152, 22); + this.optionsToolStripMenuItem.Text = "Options..."; + // + // toolStripSeparator2 + // + this.toolStripSeparator2.Name = "toolStripSeparator2"; + this.toolStripSeparator2.Size = new System.Drawing.Size(149, 6); + // + // controlToolStripMenuItem + // + this.controlToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.pauseToolStripMenuItem, + this.pausePeriodToolStripMenuItem, + this.stopToolStripMenuItem, + this.throttleOptionsToolStripMenuItem}); + this.controlToolStripMenuItem.Name = "controlToolStripMenuItem"; + this.controlToolStripMenuItem.Size = new System.Drawing.Size(152, 22); + this.controlToolStripMenuItem.Text = "Control"; + // + // pauseToolStripMenuItem + // + this.pauseToolStripMenuItem.Image = global::Duplicati.GUI.TrayIcon.Properties.Resources.Pause; + this.pauseToolStripMenuItem.Name = "pauseToolStripMenuItem"; + this.pauseToolStripMenuItem.Size = new System.Drawing.Size(168, 22); + this.pauseToolStripMenuItem.Text = "Pause"; + this.pauseToolStripMenuItem.Click += new System.EventHandler(this.pauseToolStripMenuItem_Click); + // + // pausePeriodToolStripMenuItem + // + this.pausePeriodToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.DelayDuration05Menu, + this.DelayDuration15Menu, + this.DelayDuration30Menu, + this.DelayDuration60Menu}); + this.pausePeriodToolStripMenuItem.Name = "pausePeriodToolStripMenuItem"; + this.pausePeriodToolStripMenuItem.Size = new System.Drawing.Size(168, 22); + this.pausePeriodToolStripMenuItem.Text = "Pause period"; + // + // DelayDuration05Menu + // + this.DelayDuration05Menu.Image = global::Duplicati.GUI.TrayIcon.Properties.Resources.Clock05; + this.DelayDuration05Menu.Name = "DelayDuration05Menu"; + this.DelayDuration05Menu.Size = new System.Drawing.Size(152, 22); + this.DelayDuration05Menu.Tag = "5m"; + this.DelayDuration05Menu.Text = "5 minutes"; + this.DelayDuration05Menu.Click += new System.EventHandler(this.DelayDuration05Menu_Click); + // + // DelayDuration15Menu + // + this.DelayDuration15Menu.Image = global::Duplicati.GUI.TrayIcon.Properties.Resources.Clock15; + this.DelayDuration15Menu.Name = "DelayDuration15Menu"; + this.DelayDuration15Menu.Size = new System.Drawing.Size(152, 22); + this.DelayDuration15Menu.Tag = "15m"; + this.DelayDuration15Menu.Text = "15 minutes"; + this.DelayDuration15Menu.Click += new System.EventHandler(this.DelayDuration15Menu_Click); + // + // DelayDuration30Menu + // + this.DelayDuration30Menu.Image = global::Duplicati.GUI.TrayIcon.Properties.Resources.Clock30; + this.DelayDuration30Menu.Name = "DelayDuration30Menu"; + this.DelayDuration30Menu.Size = new System.Drawing.Size(152, 22); + this.DelayDuration30Menu.Tag = "30m"; + this.DelayDuration30Menu.Text = "30 minutes"; + this.DelayDuration30Menu.Click += new System.EventHandler(this.DelayDuration30Menu_Click); + // + // DelayDuration60Menu + // + this.DelayDuration60Menu.Image = global::Duplicati.GUI.TrayIcon.Properties.Resources.Clock60; + this.DelayDuration60Menu.Name = "DelayDuration60Menu"; + this.DelayDuration60Menu.Size = new System.Drawing.Size(152, 22); + this.DelayDuration60Menu.Tag = "1h"; + this.DelayDuration60Menu.Text = "1 hour"; + this.DelayDuration60Menu.Click += new System.EventHandler(this.DelayDuration60Menu_Click); + // + // stopToolStripMenuItem + // + this.stopToolStripMenuItem.Enabled = false; + this.stopToolStripMenuItem.Image = global::Duplicati.GUI.TrayIcon.Properties.Resources.Stop; + this.stopToolStripMenuItem.Name = "stopToolStripMenuItem"; + this.stopToolStripMenuItem.Size = new System.Drawing.Size(168, 22); + this.stopToolStripMenuItem.Text = "Stop"; + this.stopToolStripMenuItem.Click += new System.EventHandler(this.stopToolStripMenuItem_Click); + // + // throttleOptionsToolStripMenuItem + // + this.throttleOptionsToolStripMenuItem.Image = global::Duplicati.GUI.TrayIcon.Properties.Resources.Throttle; + this.throttleOptionsToolStripMenuItem.Name = "throttleOptionsToolStripMenuItem"; + this.throttleOptionsToolStripMenuItem.Size = new System.Drawing.Size(168, 22); + this.throttleOptionsToolStripMenuItem.Text = "Throttle options..."; + // + // toolStripSeparator3 + // + this.toolStripSeparator3.Name = "toolStripSeparator3"; + this.toolStripSeparator3.Size = new System.Drawing.Size(149, 6); + // + // quitToolStripMenuItem + // + this.quitToolStripMenuItem.Image = global::Duplicati.GUI.TrayIcon.Properties.Resources.CloseMenuIcon; + this.quitToolStripMenuItem.Name = "quitToolStripMenuItem"; + this.quitToolStripMenuItem.Size = new System.Drawing.Size(152, 22); + this.quitToolStripMenuItem.Text = "Quit"; + // + // TrayIcon + // + this.TrayIcon.ContextMenuStrip = this.TrayMenu; + this.TrayIcon.Icon = ((System.Drawing.Icon)(resources.GetObject("TrayIcon.Icon"))); + // + // WindowsMainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(142, 29); + this.Controls.Add(this.label1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; + this.Name = "WindowsMainForm"; + this.StartPosition = System.Windows.Forms.FormStartPosition.Manual; + this.Text = "Duplicati Control Window"; + this.Load += new System.EventHandler(this.MainForm_Load); + this.TrayMenu.ResumeLayout(false); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label label1; + private System.Windows.Forms.ContextMenuStrip TrayMenu; + private System.Windows.Forms.ToolStripMenuItem statusToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem wizardToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator1; + private System.Windows.Forms.ToolStripMenuItem optionsToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator2; + private System.Windows.Forms.ToolStripMenuItem controlToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem pauseToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem pausePeriodToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem DelayDuration05Menu; + private System.Windows.Forms.ToolStripMenuItem DelayDuration15Menu; + private System.Windows.Forms.ToolStripMenuItem DelayDuration30Menu; + private System.Windows.Forms.ToolStripMenuItem DelayDuration60Menu; + private System.Windows.Forms.ToolStripMenuItem stopToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem throttleOptionsToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator3; + private System.Windows.Forms.ToolStripMenuItem quitToolStripMenuItem; + private System.Windows.Forms.NotifyIcon TrayIcon; + } +} + diff --git a/Duplicati/GUI/Duplicati.GUI.TrayIcon/WindowsMainForm.cs b/Duplicati/GUI/Duplicati.GUI.TrayIcon/WindowsMainForm.cs new file mode 100644 index 000000000..0b5cb4657 --- /dev/null +++ b/Duplicati/GUI/Duplicati.GUI.TrayIcon/WindowsMainForm.cs @@ -0,0 +1,113 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Windows.Forms; + +namespace Duplicati.GUI.TrayIcon +{ + public partial class WindowsMainForm : Form + { + private bool m_stateIsPaused = false; + private bool m_hasError = false; + private bool m_hasWarning = false; + + public WindowsMainForm() + { + InitializeComponent(); + } + + private void MainForm_Load(object sender, EventArgs e) + { + BeginInvoke((Action)(() => { this.Visible = false; })); + + TrayIcon.Visible = true; + + Program.Connection.StatusUpdated += new HttpServerConnection.StatusUpdate(Connection_StatusUpdated); + Connection_StatusUpdated(Program.Connection.Status); + } + + void Connection_StatusUpdated(Server.Serialization.ISerializableStatus status) + { + if (this.InvokeRequired) + this.Invoke(new HttpServerConnection.StatusUpdate(Connection_StatusUpdated), status); + else + { + if (status.ActiveScheduleId < 0) + { + if (status.ProgramState == Server.Serialization.LiveControlState.Running) + { + if (m_hasError) + TrayIcon.Icon = Properties.Resources.TrayNormalError; + else if (m_hasWarning) + TrayIcon.Icon = Properties.Resources.TrayNormalWarning; + else + TrayIcon.Icon = Properties.Resources.TrayNormal; + } + else + TrayIcon.Icon = Properties.Resources.TrayNormalPause; + } + else + { + TrayIcon.Icon = + status.ProgramState == Server.Serialization.LiveControlState.Running ? + Properties.Resources.TrayWorking : Properties.Resources.TrayWorkingPause; + } + + if (status.ProgramState == Server.Serialization.LiveControlState.Running) + { + pauseToolStripMenuItem.Image = Properties.Resources.Pause; + pauseToolStripMenuItem.Text = Strings.WindowsMainForm.PauseMenuText; + m_stateIsPaused = false; + } + else + { + pauseToolStripMenuItem.Image = Properties.Resources.Play; + pauseToolStripMenuItem.Text = Strings.WindowsMainForm.ResumeMenuText; + m_stateIsPaused = true; + } + } + } + + private void statusToolStripMenuItem_Click(object sender, EventArgs e) + { + + } + + private void pauseToolStripMenuItem_Click(object sender, EventArgs e) + { + if (m_stateIsPaused) + Program.Connection.Resume(); + else + Program.Connection.Pause(); + } + + private void stopToolStripMenuItem_Click(object sender, EventArgs e) + { + Program.Connection.StopBackup(); + } + + private void DelayDuration05Menu_Click(object sender, EventArgs e) + { + Program.Connection.Pause("5m"); + } + + private void DelayDuration15Menu_Click(object sender, EventArgs e) + { + Program.Connection.Pause("15m"); + } + + private void DelayDuration30Menu_Click(object sender, EventArgs e) + { + Program.Connection.Pause("30m"); + } + + private void DelayDuration60Menu_Click(object sender, EventArgs e) + { + Program.Connection.Pause("1h"); + } + } +} diff --git a/Duplicati/GUI/Duplicati.GUI.TrayIcon/WindowsMainForm.resx b/Duplicati/GUI/Duplicati.GUI.TrayIcon/WindowsMainForm.resx new file mode 100644 index 000000000..df3b7134c --- /dev/null +++ b/Duplicati/GUI/Duplicati.GUI.TrayIcon/WindowsMainForm.resx @@ -0,0 +1,630 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 221, 17 + + + 327, 17 + + + + + AAABAAwAMDAQAAEABABoBgAAxgAAACAgEAABAAQA6AIAAC4HAAAYGBAAAQAEAOgBAAAWCgAAEBAQAAEA + BAAoAQAA/gsAADAwAAABAAgAqA4AACYNAAAgIAAAAQAIAKgIAADOGwAAGBgAAAEACADIBgAAdiQAABAQ + AAABAAgAaAUAAD4rAAAwMAAAAQAgAKglAACmMAAAICAAAAEAIACoEAAATlYAABgYAAABACAAiAkAAPZm + AAAQEAAAAQAgAGgEAAB+cAAAKAAAADAAAABgAAAAAQAEAAAAAACABAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAIAAAIAAAACAgACAAAAAgACAAICAAACAgIAAwMDAAAAA/wAA/wAAAP//AP8AAAD/AP8A//8AAP// + /wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB4d3d3d3d3 + d3d3d3d3d3d3d3cAAAAAAIeIiPj4+Pj4+Pj4+Pj4+Pj4+Ph4AAAACHh3JyNiNiNiNiNiNiNiNiNiNniH + cAAACIcnInI2I2I2I2I2I2I2I2I2MiN/cAAAh4JyemJjanJ6cnpyenJ6cnpyY2poiAAAiHIqNjOmMjYj + ajY2JycjajYnpycnhwAAiCcnImJyemOoeHh4eHh4eHh4dyMniAAAh3KnJ6cqNjY4////////////h6an + hwAAiCciejJyY6Jn/4+PiPiI+I+P9ycj9wAAiCJ6JyajYnJ4+P+P+Pj4j4iPh6cmiAAAiHo2NqNjp6Ko + /4+Pj4+PiPiP9yJ69wAAiCYno2NiYnJ3//j4iIiIiIj492OniAAAiCOmJjpjo2p4+PiIiIiIiIiPh6Yy + 9wAAiHJzeHd4d3d3//j/j/j4+Ij49yemiAAAiCpqiP/4///4//+P+Pj4j4+Ph6Yz+AAAiHI3j4j4+IiI + +PiIiPiIiIiP9yNqiAAA96emf/j4+Pj3//j4+Ij4+IiPh6aniAAAiHI6j4+PiPiI+P+P/4//j/iP92On + iAAA9yp2iPj4j4iI/4iIj4j4+Pj496cm+AAAiHp6j4+IiIiI//j4j4j//4iPh6ajiAAA+CcjiPiIiIiI + +P//+Pj4+Pj/9yen+AAAiCp6j////4+I/4iIj4j4+PiPh6ei9wAAiHpjiIiIiIiI//iIj4iIiIj/96Y2 + +AAA+Cenj/+IiPiIj4//////+Pj492p6iAAAiKeniPj/j4iI//+Pj4+Pj4+Ph6en+AAAiHp6j/+IiPj4 + +P///////4iIiHp6iAAA+Cd3j4+I+PiI/4+Pj4+Pj4iIhqh3+AAAiKeoj/j/j4+I////////+I+Id3p6 + iAAAiHeniP+I+PiI/4+Pj4+Pj4iIp6in9wAAiKeKj/j4iPj4////////+IiGiod6+AAAiDqHj/+P+P+I + +Pj4+Pj4/4eoqKiniAAAiGioj4/4/4/4iIiIiIiIeH53d3qK9wAAiKeKj/j/j/j///iPiH6neoqKioh6 + 9wAAiHqIj/+P+P+Pj4iIiIeKiKiHeKin9wAAh6h3j4/4/4//+Pj4iKiod4qKioiKiAAA93d3j///j/j4 + /4j4joeHd4eHiKin9wAAiKh4j4+P////j/iId3eoeoqKh4eKiAAAiDioj///j4+P+PiOuKiIeIiIqKh6 + 9wAA92eIiIiIiIiIiIh4qIiod6ioiId3iAAAiHqKh4eHiHiHjod4iKiIeIiHd3eohwAAD3eoioeKh4qH + h3h3eIioioeHh6eHgAAACIh3p6p6emp6qqqqqqenp6qqp3h4cAAAAIiHh4eHh4h4eIiIh4eHeHh4h4eI + AAAAAACIiIiIiIiIiIiIiIiIiIiIiIgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAD///////8AAP///////wAA/AAAAAA/AADwAAAAAA8AAOAAAAAABwAA4AAAAAAH + AADAAAAAAAMAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAMAA + AAAAAwAAwAAAAAADAADAAAAAAAMAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAMAAAAAAAwAAwAAAAAAD + AADAAAAAAAMAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAMAA + AAAAAwAAwAAAAAADAADAAAAAAAMAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAMAAAAAAAwAAwAAAAAAD + AADAAAAAAAMAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAMAAAAAAAwAAwAAAAAADAADgAAAAAAcAAOAA + AAAABwAA8AAAAAAPAAD8AAAAAD8AAP///////wAA////////AAAoAAAAIAAAAEAAAAABAAQAAAAAAAAC + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAgAAAAICAAIAAAACAAIAAgIAAAICAgADAwMAAAAD/AAD/ + AAAA//8A/wAAAP8A/wD//wAA////AAAAAAAAAAAAAAAAAAAAAAAAAId3d3d3d3d3d3d3eAAAAAeIiHiI + eIh4iHiIeIhwAACHciJyInIiciJyInInhwAIgicnononpypypyejYniACHcqcnI2d3d3d3d3d3oocAhy + ciKnInj///////hyeHAIenJ6cnp4+Pj4iIj/aihwCHJ6cmOmP/+Pj/j4j3NogAh6NiOmMn+IiIiIiI9q + OHAIgmeIiIh///+PiI+PcmiACHOn+PiPiPiI+IiIj2OocAiCd/j4+I//j4j/+P96eIAIemf4+IiPj4j4 + +PiPY6hwCIKo+IiIiPj4+P+I/2pogAh3p//4+I/4+PiP+PhzqHAIinf4iIiPj4j4iIj/aniACHp3/4/4 + j//////4+HeocAiHqPiIj4j4+Pj4+Ih6eIAIenj//4+P/////4j3eniACIeo+Ij4j4+Pj4+IioeocAh6 + iI/4/4//////iH6oqIAIh6j/j4+IiIiHeOeod4hwCHqI//////iIjqioiop4cAh4ePj4+Pj4+HiKh3h4 + qIAIeoj/////+Ih6iHioqIhwCHio+I+I+IiOiKh4h4eocAiKiIiIiOiId3iHeoeHqIAAh3qKinqKioqK + ioiop4gAAAiHd3eHd3d3d3d3d4hwAAAAiIiIiIiIiIiIiIiIAAAAAAAAAAAAAAAAAAAAAAAA//////AA + AA/gAAAHwAAAA4AAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAA + AAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAcAAAAPgAAAH8AAAD/// + //8oAAAAGAAAADAAAAABAAQAAAAAACABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAgAAAAICAAIAA + AACAAIAAgIAAAICAgADAwMAAAAD/AAD/AAAA//8A/wAAAP8A/wD//wAA////AAAAAAAAAAAAAAAAAACI + iIiIiIiIiIh4AAh3IiIiIiIiIid4gAhycnNnNnNnNjIngAgiNiY2iIiIiPgigAh6Y6On////j4hjgAgj + anYn/4iI+IimgAhqdzd3+Pj4iPgjgAg2j4+I/4+IiIhqgAgjj4+I+Pj/+PgngAh6j4iI+I+I+PimgAin + j4+I//j/iPgjgAh6j4iI+I+I+Pim8Ainj4+I////+Ih6gAh3j4+I/4+PiIengAinj4j4////+IqK8Ah3 + j//4iIiIiGh3gAioj4+P+PiKioqKgAh4j///+IjoeHiogAioj/j4+IioqKiKgAh4iIiIiHiIiIeHgAiK + enp6eoqnp6iogACIiIiIiIiIiIiIAAAAAAAAAAAAAAAAAP///wDAAAMAgAABAIAAAQCAAAEAgAABAIAA + AQCAAAEAgAABAIAAAQCAAAEAgAABAIAAAQCAAAEAgAABAIAAAQCAAAEAgAABAIAAAQCAAAEAgAABAIAA + AQDAAAMA////ACgAAAAQAAAAIAAAAAEABAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAACA + AAAAgIAAgAAAAIAAgACAgAAAgICAAMDAwAAAAP8AAP8AAAD//wD/AAAA/wD/AP//AAD///8AAAAAAAAA + AAAId3d3d3d3gAcioqenp6JwB6cnj4+P93AHInKI+IiGcAd4iI+Pj/KACn+Pj4+I9jAHeIiPj/j3oAev + +P+Pj4eAB4j4j//4ioAHf4+P+PiGgAeI//iId6igCo/4+Iioh4AIiIiIh4d4oAh6h3qKioeAAAAAAAAA + AAD//wAAgAEAAIABAACAAQAAgAEAAIABAACAAQAAgAEAAIABAACAAQAAgAEAAIABAACAAQAAgAEAAIAB + AAD//wAAKAAAADAAAABgAAAAAQAIAAAAAAAACQAAAAAAAAAAAAAAAQAAAAEAAAAAAAAvkS8AL5YvAC+a + LwAvnS8ANYk1ADWMNQA/hj8AN484ADiPOAAwkTAAMJUwADaRNgA2lTYAMJgwADCeMAA3kzgAOJQ4ADiZ + OAA5nTkAMKMwADigNwAwqzAAOqE6ADumOwA8ojwAPaY8ADyrPAAxsDEAPbQ9AECLQABdi10AQK9BAEK0 + QgBDu0QATb5NAFukXABZvlkAYY1hAGGQYgBrkGkAdJJyAHWUcwB2lnQAd5h0AHicdgB8n3oAYaphAH6i + fAB7sXkARMREAEjASABUwlQAW8ZbAF/KXwBjxWMAY8xjAGrMagBr0WsAbNpsAHPUcwB22HYAe9V7AHzZ + fACAk30AgaJ/AIDXfwCLi4sAi4uMAI2NjgCFkYEAg5eDAIaShQCIlIQAiZWIAI+PkACRkZIAlJaQAJSU + lQCWmZMAl5qUAJiblQCZnJYAl5eYAJiYmQCbnpgAnJ6YAJqanACdnZ0AhKSFAI+jjwCGsIQAi7OJAJC1 + jwCYoZkAnaCaAJq6mACjp58An5+gAKGhogCjpKAApaaiAKOjpACkpKYAqqamAKOooAClqaEApqikAKio + pACnp6gAp66oAKioqQCrrKgAqqqsAKysrgCyrq0AqrSoALOwrwCurrAAsLCyALWxsQC2tbIAs7O0ALa2 + tgC8tbIAtby1ALq5tQC5uLkAvbq6AL2+ugC+vLwAwreyAMK4swDBubYAxbq2AMG8uQDGvbkAwb+/AMW/ + vADIv7wAgt2CAIrdigCSwpEAmcSXAJ7AnQCF4IUAi+KLAJPkkwClwaIAqcOnAK/HrQCzzrEAvsy8AMPA + vgDIwb4AwM2+AMHBwADFwsEAxcXCAMPDxADGxcYAy8PAAMrEwQDMxcIAyMbFAM3HxADCzcAAzcjGAMnJ + yADNysgAy8zJAM3OywDNzc4A2s3HAN3MxgDSzcoA2M7JAN7OyADP0M0A1dDOAN7QygDa0s0A3tHNAM/P + 0ADR0dEA1tLQANPT1ADV1dUA29XSAN7Y1QDX19gA2dnZANvb3ADc3N0A4dHKAODTzQDk08wA4tTPAOXV + zgDr1s4A7NfOAOzYzwDh1tIA5tfQAOjX0ADm2NIA4drWAOXa1QDo2dMA7drSAO3c0wDp2tQA7tvUAOnc + 1gDu3dUA4tzZAOXd2gDh390A5d/cAOne2QDt39gA8N/XAOXg3QDr4d0A8OHaAPDi3ADx5N4A4+LhAOrk + 4ADs5eEA6ubkAOzn5ADu6OUA6urpAOvs6wDv7+0A8ubgAPLo4gDx6eYA9OrmAPTs5wDw6+gA8u3qAPXu + 6gDz7uwA9O/tAPbw7QD48u8A8vLxAPn08QD5+PcA+fn4AAAAAAAAAAAAAAAAAP///wAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABUU1NERERERERERERERERERERERERERERERERE + RERERERERFMAAAAAAAAAAAAAZ2dUiauruLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLjAuHJEVAAA + AAAAAAByZ2duHwcFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUHJ324S1QAAAAAAACeZ0cFCgoK + AQoBAQEKAQEKAQEKAQEKAQEKAQEKAQoBAQoBAQoKCgVauFMAAAAAAH9tVAUKCgoKCgoKCgoKCgoKCgoK + CgoKCgoKCgoKCgoKCgoKCgoKCgoJfXpTAAAAALhnHwELAQEKAQoBAQEKAQEKCgkSCQkJEgkJCRIJCQkS + CQkJEgkKCgoBJ8BTAAAAALhUHgEKAQEKAQoBAQEKAQESSmFfX19fX19fVVVVVVVVUVVRUVEoAQoBHsBV + AAAAAKtUCRICAhIBAhIBAhIBAhISYfv7+/v7+/v7+/v7+/r6+vr7++kpChICCr5TAAAAALdUEQECAgIC + AgICAgICAgESYfvw8Ozs7Ozd3d3d3cnd3cnd3ekpAgICCbhUAAAAALhUCQ8PAQICAgICAgICAgIVavvw + 7Ozs3d3d3d3HycnHx8fH7OkpAgICCcBUAAAAALhnEQIPAgIPAgIPAgIPAg8Vavvw8PDs7Ozs3d3d3cfJ + x8fH3ekpAhUCEr5nAAAAALhnChICDwIUAhQCDw8PAg8Vavvw8N3OzsXFtraxsbGurq7H7OksAg8CEr5n + AAAAALhnEg8PDxQUFQ8PDw8PDw8Xavv38KShoaGIiIiGhoaGg4PH7OkpDw8PEr9nAAAAALhnEg8PFUBH + R0dHR0dGRkZHaPv28PDn593n3dvb3c7dxczd7OksDw8PE79nAAAAALhyEhQUF2fp6enp6enp6enncvv2 + 9vDw6e3w8N3n293O3d3M7OksFBQPE8BuAAAAALhyEhQVF2Hw59vb293O3c7Fc/v28KSkpaHavaSkiIiI + hobd8OksFBQUE8ByAAAAAMByFw8WF2rp3dvdxc7HxcWxc/v29trazs7wvbbn3efd2ojb8OksFBUPF8By + AAAAALhyFxYWGmr43d7a293FzsfFc/v29vD38/P3vbbw8PDw7Yjd8OksFhYWF8ByAAAAAMByFxYVGmrr + 593Oxb22xa6uc/v28LOvr6fnvb329vDw8Ijp8OktFBQWF8B2AAAAAL92FxYWGmrr6dqIf4Z8fHx8c/v2 + 9raztq/tvb3w9vfw8KHt8OktFhYWF8B6AAAAAL92GhwWHXDr593Avb22tranc/v39vb28Pbwvb3w9vf3 + 8J7w9+ktFhYWGsF2AAAAAMB2GhwWHWfr5+fd593j3d7devv38L29vb3pva/n3ePn3Z7w9ukuHBYcGsF6 + AAAAAMB2GhwcHXDp6d2eiYl/3q+Ic/v28K+ppKTd2qukqaSkpKTw+ekuHBwcGsF6AAAAAMB2HSIdIXL2 + 596vr6+n3amkevv29vDw8/D28PDw8PDw8PDw8OkuIiIiHcB6AAAAAL92HSMjJXr26fDn6fDp6a+zfvv3 + 9vf39/P58Pn58/fw59ra4+MuIyMjIMB2AAAAAL9yITQ0NXz48Oe2s7Oz3bi9ifv59/f39/n5+ff5+fnw + r56IqKtBNDQ0IcB2AAAAAL5yHTQlN3746eevr6+p6ba4ofv59/f39/f39/f38/nnc6ief2gxNDQ0IcB2 + AAAAALh2ITU1OH/48Onw6fDp8L29nvv59/f59/f59/f5+fPngOnZiVs1NTU1IcByAAAAAMByHTg1OYH4 + 8Ona2trO6b24qfv5+fn5+fn5+fn3+fnnf9mJXDg2NTg1IsByAAAAALhyHTg4OZ748Omvr6un3cCvnvv7 + +fv5+/n7+fn5+fnwiaBdOTg4ODg4IsBuAAAAALhnIjk6PIn48PDp6fDp6fDnpPj4+Pj4+Pj4+Pj4+Pjp + e2A5OTo6Ojo6IsBnAAAAALhnIjo6PKT49unw8PDw8Onwr6urpKSknqSedpSUlJSUjzw6Ojo6Ojo6IsBn + AAAAALhnIjw8PqT66fbw8Pjw+PD48PDw6b2vqbezXTw8PD08PDw8PDw8PDw8M71jAAAAALhhIj09Qqv4 + 9vD48Pjw8Pjw+PD424CeiYl6jj09PT09PT09PT09PT09M75jAAAAALdUIj1CQqv49vbw+PD4+PD48Pjw + 457p2aiQPUI9jD2MPYw9jD2MPYw9I7hjAAAAALdUM4yMkqv4+Pjw+Pj48Pjw+PD446jZt5RCjIyMQoxC + QoyMjEKMjIyMI75UAAAAALhUMoyMkrP4+Pj4+Pj3+Pj4+Pj456i3lY2MkYySjJKMkpKMkoySjIyMMrhU + AAAAAMBUIZKSk7L4+Pn4+Pj4+Pj3+Pn46YmWjZKSkpKSkpKSkpKSkpKSkpKRI7hjAAAAAMBULzuSk5um + pqampqSmpJukm6Sbm5eTjZKSk5KSkpKSkpKSkpKSkpI7L6RUAAAAAH9/SjKSk5OTk5OTk5OTk5OTkpOS + k5OTk5OTk5OTk5OTkpOSk5KTk5IylGNjAAAAAADjUykyPJOTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OT + k5OTk5OTOzJZbW0AAAAAAAB6uFNKJCIyMzMzMzIyMzIyMzI0MjIjMjMzMjMyMzIzMjMyNDIzL15fbm0A + AAAAAAAAesB6U0tMTExNTFFMTUxRTExMTExMTExMTExMTExMTUxNSkxTU2OfcgAAAAAAAAAAAAB6uMCr + pKCgpJ+goKCkn6CboKCfoKCgoKCgoKCgoKCgoKC3t30AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAD///////8AAP///////wAA/AAAAAA/AADwAAAAAA8AAOAAAAAABwAA4AAAAAAH + AADAAAAAAAMAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAMAA + AAAAAwAAwAAAAAADAADAAAAAAAMAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAMAAAAAAAwAAwAAAAAAD + AADAAAAAAAMAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAMAA + AAAAAwAAwAAAAAADAADAAAAAAAMAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAMAAAAAAAwAAwAAAAAAD + AADAAAAAAAMAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAMAAAAAAAwAAwAAAAAADAADgAAAAAAcAAOAA + AAAABwAA8AAAAAAPAAD8AAAAAD8AAP///////wAA////////AAAoAAAAIAAAAEAAAAABAAgAAAAAAAAE + AAAAAAAAAAAAAAABAAAAAQAAAAAAADCPMAAwkTAAMJYwADCaMAAwnTAAMaIxADGlMQAxqjEAMa0xADKw + MgA1sjUARItEAEWMRQBGlkUATJJLAFWaVABWnlUAXZNcAF6VXABemF0AYJteAGCeXgBGu0YAS79LAEy9 + TABVu1YAYaJfAHmXdwBzm3EAc5p0AHSadAB9kH4Ae5R8AH2XfgB6mHgAfJp6AH6cewB+nXwAYqVgAG+q + bQB0r3IAfaJ+AFHCUQBVx1UAVshWAFrHWgBfw18AWstaAFzMXABnx2YAYcthAGHPYQBoz2gAb8tuAGXS + ZQBo02gAa9ZrAG/TbwBu124AbNpsAHbXdgBy2nIAeNJ4AH3bfQB94H0AhoaGAI2NjQCBlIIAhJKEAIeU + hwCAmoEAgp2DAISYhQCQkJEAk5OUAJWVlgCXl5gAmZmaAJubnACenp8AgaWCAIWghgCDp4QAhqaEAIao + hQCIqoYAiayHAIejiACJpooAiamJAIuqjACMq40Ai6yMAIysjQCZopoAmqiaAJe3lQCetp4AnrybAKOn + nwCgsp4An7egAKGhogClpaYApa2iAKavpACmpqgAqamqAKqqrACtra4AprKmAKiwpQCjvKQApL6kAKm4 + pwCsuakAqr6rALixrgCvr7AAr7uwALGxsQC1t7MAs7O0ALW1tQC7trQAsr+yALy4twC5ubkAvrq5ALu7 + vAC+vb0Awru3AMa6tQDDvLkAxL+9AMi9uQCOzo0AhN6EAJPDkgCSx5EAlMiSAJXRlACd1J0Ant6eAKDf + nwCK4YoAkeSRAJrgmgCiwKAApsKlAKPIowCmyqYAp8OoAKnGqQCpyqoArsqtALLNsQC6w7oAt9G1ALrU + uQDGwL4AysG9AM3BvAC/v8AAwcHBAMXCwgDDw8QAxcXGAMjCwADNxMEAz8fEAMjIxgDHx8gAycnJAM3K + yQDNzMsAzMzMANDFwQDRyMUA1MvHANHNywDUzcoA0s7NANXPzADW0M4A2NHOANXU1ADY09AA2tTRANzW + 0wDa1dQA3djVANrZ2QDf29gA3d3dAODSzQDl1M0A7NfOAOzYzwDi1tEA5tfQAOfZ0wDg2dYA5NrVAOrZ + 0gDs2dEA6dvVAO7b1ADu3dYA4drYAOLd2gDl3tsA6t7YAO/f2ADl4N0A6uDbAO7h2wDp4t0A7uPdAO/k + 3wDw4doA8ePcAPHk3gDj4uEA5OPiAOTk4wDl5eQA6OLgAOrk4ADt5eEA6OfmAOzn5ADu6OQA6urpAO3q + 6QDt7OoA7u7sAPDm4QDx6eUA9OnkAPXs5wDw6+gA8u3qAPXu6QDy7uwA8vDuAPbw7QD48u8A8/HwAPXz + 8QD09PIA+PPwAPj08gAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHlK + QkJCQkJCQkJCQkJCQkJCQkJCQkJDbQAAAAAAAABQbW9iYmJiYmJiYmJiYmJiYmJiYmJiZnilSgAAAAAA + bWANAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ2eUAAAAK5tDQECAgICAgICAgICAgICAgICAgICAgICAg2l + eQAApEYBAQICAgICAgIOJSUlJSUlJSUlJRwlHA8CAn5NAACkHAIEAgQCBAIEAhDg/f39+Pj29vb29vbs + EgIEcUoAAKQcAgQEBAQCBAQEEODw7u7W1tbGxsbGxvYSBAKWUAAApEcEBAQEBAQEBAQQ4Pju7u7W1tbO + xsbG6RIEBHFQAAClRwQEBAQEBgQEBhHg+MSysrKIiIiIiMbsFAQGllAAAKVYBgYdb29qb2pqZOD48PDm + 3Nzczs7OzuwUBgSZZwAArVgGBlTs5tzc1Nyr4PjCvLjmuLS0qqrW7BUGBplnAAClWwYGVezWzMzJybLg + +Obm1Pa08ObctNzsFQYGm2sAAK5bCAZV7NzMyMm6iOD31MK+6br29PC07vYWCAiZbQAArlsICFfs1KmH + hIR24P3cwszpxPb097rw7BsICJttAACuWwgIV+zm5tzc1rTg9+bUwva45vDmuPD2GwgIm20AAK5bCwtV + 7NyppKm6fef4wsLE5r6+usS6+OwnCwubbQAArlsXGGHs6dTm5r6l5vj49vb3+Pb29tTm4CgYGJttAACu + WxgrY/jmvK68wq7s+Pf39/f39/fCh32eKSsYm20AAK1bKy6W7Ozg5uDCuOz99/399/39977CwmYvLiub + bQAApVssM5b46cLCwsK47P399/399/33wrxzMjMzLJtnAAClVy43mf3swtTg8Lzg/f39/f39/f3CczY1 + NTUum2cAAKVVNDqb/fb29vb25sK8vK6upYuNjYs/Ojo6OjeYZwAApVE3PZ347Pbw9vb29vaqpap5PT09 + PT0/PT0/N5hQAACkKjlAn/329vbw9vbw9q7srYlAQEBAQEBAQEA7mEoAAKQqO4qg/fb2+Pj29vj2uK6O + ioqKioqKioqKij2YTQAApUY5kqDg4Obg4ODg4OCuj5KSkpKSkpKSkpKSPJZQAACuahqSlJGRkZGRkZGR + kZSTk5OTk5OTk5OTk5IreXkAAACtRho9QUFBQUFBQUFBQUFBQUFBQUFBQUE7K2BnAAAAAAClZxwdHh4e + HR4dHh0eHR0dHR0dHR0dHUZndwAAAAAAAACupYB5gHmAeYB5gHmAeYB5gHmAeYB7gK0AAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////8AAAD+AAAAfAAAADgAAAAYAAAAGAAAABgAAAAYAA + AAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAA + AAGAAAABgAAAAYAAAAGAAAABwAAAA+AAAAfwAAAP/////ygAAAAYAAAAMAAAAAEACAAAAAAAQAIAAAAA + AAAAAAAAAAEAAAABAAAAAAAAL5EvAC+WLwAvmi8AMowyADWLNQAwkTAAMZQxADSSNAAwmjAAMZ4xADSZ + NAA1nzUAMKEwADClMAA1ojUANqY2ADCpMAAwrTAANqk2ADetNgA7rzsAObM5ADyxPABWklYAW5ZaAFuY + WQBcmFoAX5pfAEi4SABNvE0AZ5tlAG6ibABmtmcAabppAG2/bQBRwFEAVsBWAFbFVgBYxlgAXsZeAF3J + XQBizGIAZcxlAGvRawBs0WwAbdVtAHDRbwB11nUAedZ5AH/bfwB+3H4AhKGBAIK0gACRvY8Al6iVAJuh + nACcpJ0AoaGiAKenqACpqaoArq6uAKu7qQCvvq4AsL+uAK+vsACwsLAAsbaxALW1tgC+t7QAvrm3ALe3 + uAC4uLkAvLy9AIPJggCC24IAid+JAJfBlQCH4IcAjeONAJDjkACjyaIArM6rALDArgCl2KQAqdmoALHC + sACyxLEAysC7AM3DvwC/v8AAwcHCAMPDxADFxMUAycLAAMrFwgDPx8MAycbGAM3HxQDIycYAx8fIAMnJ + yADOy8oAy8zIAM3MygDPz88A1cfBANHKxgDVycQA18zHANjLxgDVzswA2c7JAMnXxwDN1ssAy9rKANrQ + ywDa0c0Az8/QANbS0ADV1NIA1tbVANrV0QDc1dEA2tbUANnZ1wDe2NUA3NrZANvc2gDe3NsA3t7dAOXS + ygDl08wA5dXOAOfY0gDi2tYA6NnTAO3Z0QDp3NYA7t3WAOHb2ADi3NoA5N3ZAOXf3ADq39oA4OHfAOfg + 3QDr4NsA6OHeAPDg2QDw4twA4uLhAOnj4ADq5OEA7OXiAO/p5QDv6ugA8ebhAPHq5gDy7eoA9u7qAPPv + 7AD17+wA9vHuAPjy7gD08vEA+PTyAPn29AD6+PYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABJOkE9PT09PT09PT09PT09 + PUI7QgAAAGQ4GQUFBQUFBQUFBQUFBQUFBQUcREkAAEIZAQEBAQEBAQcHBwcHBwcHBwcBHD0AAEcFBwcB + AQEBH2dnZ2dnYWddYTcBB0kAAEILCQEDAwMDIKSdlpWLi4mJiz8LB0kAAEkHCwMDCwMDIKadk4uGhYWF + iz8DB0kAAEkLDRwaHBoZNKaTenVwbmpqi1MNC1oAAEkND2eYmJiYYaaZfo6GdXBullMNDV0AAF0PEGeT + hoaFWKaemZ56np11nVYND10AAF0NFWeTZm5YRaaOb4Z6pKB6nlYSDWcAAF0VEmeZmH6GXaaemZt6np56 + oFYSFWQAAF0VF2eZYWF1RaaZjpiOjn5+pFYXF10AAF0dJXmejo6OZ6ampKCmoKB6eT4kHV0AAF0eKHmb + jn+OZ6ampKampqBdYTUnHl0AAEkkK36cenqOZ6impqampqBkNisrJF0AAEkkL3+cnJygf5F/f39yc3JN + LCwsJF0AAEkpMZGkoJymoKB6ZWFKLzAvMS8wKkkAAEIrS5GcppygnKR5f1FLMzMzMzMzK0gAAEkrTJil + pqWmpaV5UkxOTk5OTk5OK0gAAEghTFVVVVVVVVVUUFBQUFBQUFBMIzwAAHY4IiwuLi4uLiwsLC4sLi4u + LiwiOFsAAAByR0E9PDw8PDxBPTw9PTw9PT1DZQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AMAA + AwCAAAEAgAABAIAAAQCAAAEAgAABAIAAAQCAAAEAgAABAIAAAQCAAAEAgAABAIAAAQCAAAEAgAABAIAA + AQCAAAEAgAABAIAAAQCAAAEAgAABAMAAAwD///8AKAAAABAAAAAgAAAAAQAIAAAAAAAAAQAAAAAAAAAA + AAAAAQAAAAEAAAAAAAAwkjAAMJYwADeSNgAwmzAAR5VGAEeZRgBInUcASZVIAFWUUwBWllUAWJtZAEii + RwBJp0gAVqBVAFSvUwBcp1sAW6FcAF2mXQBcq1sAXqtfAGiWaQBynnIAZ6NnAGmqagBqrmsAZLFlAGe0 + ZgBgv2AAbLJsAGy2bABuuW4AeaZ6AHupewByu3MAdb11AHqzegB5tHoAeL14AGTNZAB0wXUAe8F6AHnG + eQB8xnwActVyAH7RfQCcvpsAp6moAKusqwCrr6wAt7q3AIbBhwCByoEAhsmFAIXOhgCF0IQAgN2AAIXZ + hACK0IoAncGcAJHQkQCS35IAnNecAJvemwChw58AjeKNAL3AuwC52rkAx8e/AMnGxgDIycIAyszFAM7O + ygDZycMA28zGANbOygDE08MA1NHPAN3QygDY0s8A39TPANbS0ADZ09AA2tTRANrW1QDe2NYA3dvaAN/d + 2wDj1c4A4NbRAOPZ1QDl2dQA4NvYAOLc2QDk3dkA4d7cAOjf2wDC4sEA5eDeAOjh3gDt4dwA8ePdAPHk + 3wDt5eEA6+bkAO3o5QDy5+IA8ermAPTq5QDx7OkA9e7qAPPw7gD08O0A+PLvAPXy8AD29PEA+PPwAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAAAAAAAAADAWFxcXFxcXFxcXFyAvAAAVAQEBAQgKCgoKCgoB + IQAACgECAQIubmxqZmZqCBgAAAsCBAIEO2pZTkpKZAYYAAARDkdHREhsXGBOTmQHHQAAERNnW1hZZ1xi + bFtnDR0AABMTZ1lITW5cXG5cbw0fAAAaG21NWU1uZGdqXG0PKAAAHSttVFZWb3Nzb01CHCsAAB81bVxi + VnNzc3NIKyc1AAAiPHNubmpNR0A3LSwsNQAAIj5zbW9vX0w5OTg4ODoAACU+YWFhYUM9QUFBQUEzAAAy + JSYmJiYmJiYrIiYlMAAAAAAAAAAAAAAAAAAAAAAA//8AAIABAACAAQAAgAEAAIABAACAAQAAgAEAAIAB + AACAAQAAgAEAAIABAACAAQAAgAEAAIABAACAAQAA//8AACgAAAAwAAAAYAAAAAEAIAAAAAAAgCUAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB9fX4GeHh5Onp6 + emmAgIF8gYGCf4GBgn+BgYJ/gYGCf4GBgn+BgYJ/gYGCf4GBgn+BgYJ/gYGCf4GBgn+BgYJ/gYGCf4GB + gn+BgYJ/gYGCf4GBgn+BgYJ/gYGCf4GBgn+BgYJ/gYGCf4GBgn+BgYJ/gYGCf4GBgn+BgYJ/gYGCf39/ + gHx4eHlpdnZ3Onp6ewYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhISFBnl5 + enSOjo7klpaX/pKSk/6Ojo7/i4uM/ouLi/+Li4v+i4uM/ouLjP6Li4v/i4uL/ouLi/6Li4v/i4uL/ouL + i/6Li4v/i4uL/ouLi/6Li4z/i4uL/ouLi/6Li4z/i4uM/ouLi/6Li4v/i4uL/ouLjP+Li4z+i4uM/ouL + i/+Li4z+i4uL/oyMjP+Ojo/+jY2O/oWFhuR1dXZ0enp7BgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AACHh4gVjIyNxqSkpf+ZmZr/wMDB/87Ozv/Pz8//0NDQ/9HR0f/R0dH/0dHR/9HR0f/R0dH/0dHR/9HR + 0f/R0dH/0dHR/9HR0f/R0dH/0dHR/9HR0f/R0dH/0dHR/9HR0f/R0dH/0dHR/9HR0f/R0dH/0dHR/9HR + 0f/R0dH/0dHR/9HR0f/R0dH/0dHR/9HR0v/Y2Nn/1tbW/62trf+Pj4//fn5/xnh4eRYAAAAAAAAAAAAA + AAAAAAAAAAAAAJOTkwaUlJXGpqan/qSkpf6nrqj/X4tf/j+GP/42iDb/NYk1/jWJNf81iTX+NYk1/jWJ + Nf41iTX/NYk1/jWJNf41iTX/NYk1/jWJNf41iTX/NYk1/jWJNf41iTX/NYk1/jWJNf41iTX/NYk1/jWJ + Nf41iTX/NYk1/jWJNf81iTX+NYk1/jWJNf81iTX+NYk1/jaINv8/hj/+YY1h/rW8tf/U1NT+jIyM/oCA + gMZ9fX4GAAAAAAAAAAAAAAAAAAAAAImJinTFxcX/n5+g/oOXg/41izX/L5Av/i+QL/4wkDD/L5Av/jCQ + MP8vkC/+L5Av/i+QL/4wkDD/L5Av/i+QL/4wkDD/L5Av/i+QL/4wkDD/L5Av/i+QL/4wkDD/L5Av/i+Q + L/4wkDD/L5Av/i+QL/4wkDD/L5Av/jCQMP8vkC/+L5Av/jCQMP8vkC/+L5Av/jCQMP8vkC/+L5Av/jWM + Nf+Po4/+1NTV/pKSk/96ent0AAAAAAAAAAAAAAAAmpqbB7CwsOSnp6j/maCa/zWNNf8wkTD/MJEw/zCR + MP8wkTD/MJEw/zCRMP8wkTD/MJEw/zCRMP8wkTD/MJEw/zCRMP8wkTD/MJEw/zCRMP8wkTD/MJEw/zCR + MP8wkTD/MJEw/zCRMP8wkTD/MJEw/zCRMP8wkTD/MJEw/zCRMP8wkTD/MJEw/zCRMP8wkTD/MJEw/zCR + MP8wkTD/MJEw/zCRMP81jTX/tby1/7Ozs/+Li4zkg4OEBwAAAAAAAAAAl5eYO9PT1P6fn5//XItc/i+S + L/4wkjD/L5Iv/i+SL/4wkjD/L5Iv/jCSMP8vki/+L5Iv/i+SL/4wkjD/L5Iv/i+SL/4wkjD/N5Q3/jmU + Of45lTn/OZQ5/jmUOf45lDn/OZQ5/jmUOf45lDn/OZQ5/jmUOf45lDn/OZQ5/jmUOf85lDn+OZQ5/jmU + Of85lDn+OZQ5/jmUOf80kzT+L5Iv/jCSMP8vki/+YZBi/tra2v+VlZb+gICBOwAAAAAAAAAAnJydatPT + 0/6cnJ3/QItA/i+TL/4wkzD/L5Mv/i+TL/4wkzD/L5Mv/jCTMP8vky/+L5Mv/i+TL/4wkzD/L5Mv/i+T + L/42ljb/i5eI/p6hm/6eoZv/naCa/p2fmf6cn5n/nJ6Y/puemP6bnZf/mp2X/pmclv6ZnJb/mZuV/pib + lf+Ym5X+l5qU/pealP+XmZP+lpmT/pSWkP9rkGn+L5Mv/jCTMP8vky/+QItB/tvb2/+ZmZn+g4OEagAA + AAAAAAAAq6urfc3Nzv+ZmZr/N484/zCVMP8wlTD/MJUw/zCVMP8wlTD/MJUw/zCVMP8wlTD/MJUw/zCV + MP8wlTD/MJUw/zCVMP85mDj/o6ef//n6+f/6+vj/+fn4//n5+P/5+fj/+fn3//n59//5+fj/+fn3//n4 + 9//5+Pf/+fj3//n49//5+Pf/+fn3//n49//5+Pf/+fn3/+nq6f90knL/MJUw/zCVMP8wlTD/OI84/9XV + 1v+YmJn/jIyNfQAAAAAAAAAAr6+wf87Ozv6bm5z/N5E3/i+WL/4wljD/L5Yv/i+WL/4wljD/L5Yv/jCW + MP8vli/+L5Yv/i+WL/4wljD/L5Yv/i+WL/45mjj/o6ig/vn5+P706+b/8+ji/vLm4P7y5d//8ePd/vDi + 2/7w4Nr/79/Y/u/e1/7u3dX/7tzU/u3c0//t29P+7tvT/u3b0//t29P+8eXf/urq6f90knL+L5Yv/jCW + MP8vli/+N5E3/tXV1v+ampv+j4+QfwAAAAAAAAAAsbGyf8/Pz/+dnZ7/N5M4/zCYMP8wmDD/MJgw/zCY + MP8wmDD/MJgw/zCYMP8wmDD/MJgw/zCYMP8wmDD/MJgw/zCYMP85mzj/pKmh//n5+P/06+b/8+fi//Lm + 4P/y5N7/8eLb//Dg2f/w39f/7t3V/+7b1P/t2tL/7dnR/+zYz//s187/7NfO/+zXzv/s187/8OLc/+rq + 6f91k3L/MJgw/zCYMP8wmDD/N5M4/9bW1/+dnZ7/kZGSfwAAAAAAAAAAs7Ozf9DQ0f6fn6D/OJQ4/i+Z + L/4wmTD/L5kv/i+ZL/4wmTD/L5kv/jCZMP8vmS/+L5kv/i+ZL/4wmTD/L5kv/i+ZL/45nDj/pamh/vn5 + +P717en/9Orl/vPp4/7z5+H/8uXf/vHj3f7x4tv/8ODZ/u/e1/7u3NX/7tvT/u3Z0f/s2ND+7NfP/uzX + zv/r1s3+8OLc/urq6f91lHP+L5kv/jCZMP8vmS/+OJQ4/tfX1/+fn6D+lJSVfwAAAAAAAAAAtLS1f9HR + 0v6hoaL/OJY4/i+bL/4wmzD/L5sv/i+bL/4wmzD/L5sv/jCbMP8vmy/+L5sv/i+bL/4wmzD/L5sv/i+b + L/45njj/paqi/vn6+f727+v/9ezn/ufe2v7l29f/5NrV/uLX0/7i1tH/4dTP/uDTzf7f0cz/39DK/t7O + yP/dzcf+3czG/t/Nxv/s187+8OPd/urq6v91lHP+L5sv/jCbMP8vmy/+OJY4/tjY2P+hoaP+lpaXfwAA + AAAAAAAAtra2f9LS0/6jo6T/OJg4/i+dL/4wnTD/L50v/jGdMf4xnjH/MZ4x/jGeMf8xnjH+MZ4x/jGe + Mf4xnjH/MZ4x/jGeMf46oDr/pqqi/vn6+P738O3/8erm/s3Gw/7MxMH/y8PA/sjAvf7Hv7v/xr26/sa8 + uf7Fu7f/xbq2/sO5tf/CuLP+wrey/sO3sv/r18/+8ePd/urq6v92lXP+L50v/jCdMP8vnS/+OJg4/tnZ + 2f+kpKX+mJiZfwAAAAAAAAAAt7e4f9PT1P+lpaf/OZo5/zCfMP8wnzD/OKA3/4CTff+IlIX/iJSE/4eT + hP+Gk4P/hpOD/4WSgv+EkYH/hJGB/4SQgP+GkYL/qqem//n6+f/38e3/9u/r//Dp5f/u5+P/7ubh/+3k + 3//s497/6+Hc/+vf2v/q3tj/6dzW/+ja1P/o2dP/59fR/+jX0P/t29P/8eXf/+rr6v92lnT/MJ8w/zCf + MP8wnzD/OZo5/9nZ2v+mpqf/mpqbfwAAAAAAAAAAuLi5f9TU1f6np6j/Opw6/jCgMP4xoDH/PKI8/qOk + oP7r7Ov/6+vq/uvr6v/r6+r+6+vq/uvr6v7r6+r/6uvq/urr6v7n5+b/sa6u/vn6+P738e3/9u/r/vLr + 6P7x6ub/8enl/vDo5P716+f/8+nk/u7k3/7u4t3/7ODb/uzf2f/r3df+6tvV/uvb1P/u3dX+8ubg/urr + 6v93l3T+MKAw/jGgMf8woDD+Opw6/tra2/+oqKn+nJydfwAAAAAAAAAAubm6f9XV1v6pqar/Op06/jCi + MP4xojH/PaM8/qSmov7v7+3/6uLd/urg2//p3tr+6N3Y/ujc1v7n29X/5trU/ubZ0v7j1c//sq2s/vn6 + +P738e3/8uvn/s/Jx/7Nx8X/zcfE/sjCv/7o4d3/39jU/szFwv7Lw8D/x7+8/se+uv/Gvbn+xby4/sa8 + uP/u3tf+8uji/urr6v93mHT+MKIw/jGiMf8wojD+Op06/tvb2/+qqqv+np6ffwAAAAAAAAAAurq7f9bW + 1/+rq6z/Op86/zGkMf8xpDH/PaU8/6Wmov/v7+3/6uDb/+nd1//o29b/59nU/+fY0v/m19D/5dXO/+TT + zP/h0Mn/sq6t//n6+f/38e3/9e/r/+Xe2//j3Nn/49zZ/+Ha1//z7Oj/3dfT/9jSzv/u5uL/7eTg/+3j + 3v/s4tz/6t7Z/8W8uP/u4Nr/8+nl/+rr6v93mXX/MaQx/zGkMf8xpDH/Op86/9vb3P+srK3/n5+hfwAA + AAAAAAAAu7u8f9fX2P6srK7/OqE7/jCmMP4xpjH/Pac8/qano/7v7+3/6+Ld/urf2v/p3tj+6dzX/uja + 1f7n2dP/5tfR/uXWz/7i08v/sq6t/vn6+f738e3/9u/r/vbv6/738Oz/9u/r/vbv6/738Oz/3dfU/tvV + 0f727ur/9e3p/vXs5//06uX+8ufi/sa+uv/v493+9Ovn/urr6v94mnX+MKYw/jGmMf8wpjD+OqE7/tzc + 3P+tra/+oaGifwAAAAAAAAAAvLy9f9jY2P6tra//O6M7/jCoMP4xqDH/Pak8/qaopP7v7+7/7OTg/uvi + 3f/i2dT+4NfS/t/V0P7e087/3tHN/t3Qy/7azcf/s6+u/vr6+f738e3/9O3p/tXPzf7Tzcr/0szJ/s/I + xv7t5uL/3tfV/tvV0v738Oz/9+/r/vbu6v/27ej+8+nl/si/vP/x5uH+9e3p/uvr6v94m3b+MKgw/jGo + Mf8wqDD+O6M7/tzc3f+vr7D+oqKjfwAAAAAAAAAAvb2+f9jY2f+urrD/O6U7/zGqMf8xqjH/Pas8/6eo + pP/v7+7/7ebi/+Xd2f/Cvbr/wry5/8C6t/++uLT/vbaz/721sf+8tLD/sa2s//n6+f/38e3/9O3p/9rT + 0f/X0c7/1tDO/9PNyv/v6OT/3dfU/9vV0v/38Oz/9/Ds//fv6//27+v/9Ozn/8jBvv/y6OP/9u/r/+vr + 6v95nHb/Maox/zGqMf8xqjH/O6U7/93d3f+wsLH/o6OlfwAAAAAAAAAAvb2+f9jY2f6vr7H/O6c7/jCs + MP4xrDH/Pa08/qiopP7v7+7/7ebi/uzk4P/f2dX+3tfT/t3W0v7c1ND/29PO/tvRzP7Yzsn/s7Cv/vn6 + +f738e3/9u/r/vbv6/738Oz/9u/r/vbv6/738Oz/3dfU/tvV0v738Oz/9u/r/vfw7P/38Oz+9O3p/sjC + v//z6ub+9/Ht/uvr6v95nXb+MKww/jGsMf8wrDD+O6c7/t3d3f+wsLL+pKSlfwAAAAAAAAAAvr6+f9nZ + 2f6wsLH/O6g7/jCuMP4xrjH/Pa49/qippf7v7+7/7ebi/u3m4v/s5eH+6+Tg/uvj3/7q4t7/6+Ld/urg + 2/7m29b/tbGw/vn6+f738e3/9e7q/uDa1/7e2NX/3tfV/tzV0v7x6ub/3dfU/tfRz/7r5eH/6uTg/urk + 4P/r5OD+6eLf/sjCv//z7Oj+9/Lv/uvr6v96nnf+MK4w/jGuMf8wrjD+O6g7/t3d3f+xsbP+pKSmfwAA + AAAAAAAAvr6+f9nZ2f+wsLH/O6o8/zGwMf8xsDH/PbA9/6mppf/v7+7/7ebi/+fg3P/Gwb//xcC+/8S/ + vf/AvLn/49vX/9TNyv/Dvbr/s6+v//n6+f/38e3/8+zo/9HLyf/Pycf/zsjG/8rEwf/q5OD/4tzZ/8/J + x//OyMb/y8XC/8rEwv/LxML/ysTB/83Gw//17ur/+PPw/+vr6v96n3j/MbAx/zGwMf8xsDH/O6o8/93d + 3f+xsbP/paWmfwAAAAAAAAAAvr6+f9nZ2f6vr7H/Pq0+/kG3Qf49tj3/RrVG/qusqP7v7+7/7ebi/urj + 3//Uzsv+083K/tLNyv7Qy8j/6OHd/s/Kxv7MxsP/tbGx/vn6+f738e3/9u/r/vXu6v717ur/9O7q/vTt + 6v738Oz/9u/r/vTu6v707er/9O3p/vTt6f/07en+8uvn/vHr5//z7Oj+9PDt/urq6f9+onz+P7c//kK4 + Qv9GuUb+P60//t3d3f+xsbL+pKSmfwAAAAAAAAAAvb2+f9jY2f6vr7D/P68//k6+Tv5Ovk7/Wb5Z/ra2 + sv7x8fD/7+nm/u/p5f/v6OX+7+jl/u7o5P7u6OT/7ujk/tPOy/7Uz8z/u7e3/vr6+f738u7/9/Dt/vfw + 7f738O3/9/Dt/vfw7f738e3/9/Dt/vfx7f738e3/9/Ht/vfx7f/07uv+7Obj/ubg3f/l39z+5+Ph/uLi + 4f9+n3z+Tr5O/k6+Tv9Ovk7+QK9B/t3d3f+wsLL+o6OlfwAAAAAAAAAAvb2+f9jY2f+urq//QLFA/1LB + Uv9SwVL/XcFd/7i4tf/y8vH/8Orn/+3n5P/Y09H/19LQ/9bRz//U0M3/6+Xi/9fT0f/Z1NL/wr+///v7 + +v/48/D/+PLv//jy7//48u//+PLv//jy7//48u//+PLv//jy7//48u//+PLv//jy7//x7On/0s3L/8bB + v//FwL7/yMXE/8rJyP+Bon//UsFS/1LBUv9SwVL/QbFB/9zc3f+vr7D/o6OkfwAAAAAAAAAAvLy9f9fX + 2P6tra7/QLJA/lfEV/5XxFf/YcRh/rq7t/7y8vH/8Ovn/uvm4//Szsz+0c3L/tHMy/7Oy8j/6eTh/tjU + 0f7Z1dP/xMHA/vv7+v749PD/+PLv/vjy7/748+//+PLv/vjy7/748+//+PLv/vjy7/748+//+PLv/vjy + 7//s5uP+s6+v/sjGx//FxMT+v729/qqmpv97sXn+V8RX/lfEV/9XxFf+QrNC/tzc3f+urq/+oaGjfwAA + AAAAAAAAu7u8f9bW1/6rq63/QLRB/lvHW/5bx1v/Zcdl/ry9uf7y8vH/8evo/vDr6P/w6uf+8Orn/vDq + 5/7w6uf/8Orn/tnV0/7a1tT/xsPC/vv7+v759PH/+PLv/vjy7/758/D/+PLv/vjy7/758/D/+PLv/vjy + 7/758/D/+PLv/vjy7//s5+T+vbq6/urq6v/g39/+vry8/oawhP9cx1z+W8db/lvHW/9bx1v+QrRC/tvb + 3P+srK7+oKChfwAAAAAAAAAAurq7f9bW1v+qqqv/QbVB/1/KX/9fyl//acpp/76/u//y8/H/8ezp/+/q + 5//j39z/497b/+Ld2//h3dr/7+nm/9rW1P/a1tT/x8XE//v7+v/59PH/+fPw//nz8P/58/D/+fPw//nz + 8P/58/D/+fPw//nz8P/58/D/+fPw//jz7//t6OX/vru7/+Hh4f/BwL//i7OJ/2HKYf9fyl//X8pf/1/K + X/9fyl//Q7ZD/9vb2/+qqqz/np6gfwAAAAAAAAAAubm6f9XV1f6oqKn/QbdB/mTNZP5kzWT/bc1t/sDB + vv7z8/L/8ezp/uzn5P/Szs3+0s7N/tHOzP7Oy8j/6eTh/t3Z1/7Rzsz/x8XE/vv7+v769/X/+vf0/vr3 + 9P769/T/+vf0/vr39P769/T/+vf0/vr39P769/T/+vf0/vr39P/w7ev+vbu7/sXDw/+RtY/+Zsxm/mTN + ZP9kzWT+ZM1k/mTNZP9kzWT+Q7hE/tra2/+oqKr+nZ2efwAAAAAAAAAAt7e4f9TU1P+mpqf/QbhC/2nQ + af9p0Gn/ctBy/8LDwP/z8/L/8u3q//Hs6f/u6eb/7ejm/+3o5f/t6OX/8ezp//Dr6P/r5uT/ycbG//Hx + 8P/y8vH/8fHx//Hx8f/x8fH/8fHx//Hx8P/x8vH/8fHw//Hx8P/x8fD/8fHw//Hx8P/q6un/t7Sz/5q6 + mP9qz2r/adBp/2nQaf9p0Gn/adBp/2nQaf9p0Gn/RLlF/9ra2v+np6j/m5ucfwAAAAAAAAAAtra3f9LS + 0/6kpKX/QrpC/m3Tbf5t023/dtJ2/sTGwv7z9PP/8u3q/vLt6v/x7er+8u3q/vLt6v7y7er/8e3q/vHt + 6v7w7On/0s7N/s3Kyf7Oysn/zMnH/snGxf7HxMP/x8PC/sfExP7FwsL/rLWp/qbCo/6mw6T/psOk/qXB + o/+jwKH+mcSX/nHScf9t023+bdNt/m3Tbf9t023+bdNt/m3Tbf9t023+RbtF/tnZ2f+kpKb+mZmafwAA + AAAAAAAAtbW1f9HR0v6ioqP/Q7tD/nPVc/5z1XP/e9V7/sfIxf709PT/8+7r/vPu6//z7uv+8+7r/vPu + 6/7z7uv/8+7r/vPu6/7z7uv/8+7r/vPu6/7z7ev/7ejm/tnV0/7RzMr/0MvK/tTR0P7R0ND/kLWP/nPV + c/5z1XP/c9Vz/nPVc/9z1XP+c9Vz/nPVc/9z1XP+c9Vz/nPVc/9z1XP+c9Vz/nPVc/9z1XP+RrxG/tjY + 2P+ioqP+l5eYfwAAAAAAAAAAs7O0f9DQ0f+goKH/Q7xD/3fYd/932Hf/gNd//8nKxv/09fT/8+7s//Pu + 7P/z7uv/8+7s//Pu7P/z7uz/8+7r//Pu6//z7uz/8+7r//Pu6//z7uv/5eHf/7u5uf/GxMT/xMLC/8G/ + v/+1srL/ksKR/3fYd/932Hf/d9h3/3fYd/932Hf/d9h3/3fYd/932Hf/d9h3/3fYd/932Hf/d9h3/3fY + d/932Hf/R71H/9fX2P+goKH/lJSWfwAAAAAAAAAAsrKyf8/P0P6dnZ7/Q75D/nzafP582nz/hNqE/svM + yf709fT/8+/s/vPv7P/z7uz+8+/s/vPv7P7z7+z/8+7s/vPu7P7z7+z/8+7s/vPu7P7z7uz/5eHf/sfG + xv7o6Oj/4eHh/sjHxv6ewJ3/fdl9/nzafP582nz/fNp8/nzafP982nz+fNp8/nzafP982nz+fNp8/nza + fP982nz+fNp8/nzafP982nz+SL9I/tbW1/+dnZ7+kpKTfwAAAAAAAAAAsLCxf87Oz/6bm5z/RL9E/oDd + gP6B3YH/iNyI/s3Oy/719fT/9PDt/vTv7f/z7+z+9O/t/vTv7f707+3/8+/s/vPv7P707+3/8+/s/vPv + 7P7z7+3/5+Lg/snHx/7i4uL/y8rK/qTCov6C3IL/gN2A/oDdgP6B3YH/gN2A/oHdgf+A3YD+gN2A/oHd + gf+A3YD+gN2A/oHdgf+A3YD+gN2A/oHdgf+A3YD+ScFJ/tXV1f+bm5z+kJCRfwAAAAAAAAAArKytfdHR + 0f+ZmZr/RL9E/4TfhP+F34X/jN6M/8/Qzf/19vX/9fLv//Xx7//18e//9fHv//Xx7//18e//9fHv//Xx + 7//18e//9fHv//Xx7//08e//6ebl/8jGxv/Ozc3/qcOn/4fdh/+F34X/hd+F/4Xfhf+F34X/hd+F/4Xf + hf+F34X/hd+F/4Xfhf+F34X/hd+F/4Xfhf+F34X/hd+F/4Xfhf+F34X/SMBI/9PT1P+ampz/jY2OfQAA + AAAAAAAAnp6fatvb2/6YmJn/RbVG/oXghf6J4Yn/keCQ/tDRzv7z9PP/8/Pz/vP08//z8/P+8/Tz/vPz + 8/7z8/P/8/Pz/vPz8/7z8/P/8/Pz/vPz8/7z8/P/6urq/sLAwP6vx63/i9+L/onhif6J4Yn/ieGJ/onh + if6J4Yn/ieGJ/onhif+J4Yn+ieGJ/onhif+J4Yn+ieGJ/onhif+J4Yn+ieGJ/onhif+F4IX+R7ZH/tLS + 0v+cnJ3+hYWGagAAAAAAAAAAm5ubO9vb2/6cnJz/XKVc/nDbcP6O447/kuKS/r7PvP7Cz8D/ws/A/sLP + wP/Cz8D+ws/A/sLOv/7Bzr//wc6//sHNv/7Bzb//wM2+/sDNvv6/zL3/vcq7/rPOsf6R4pH/juOO/o7j + jv6O447/juOO/o7jjv6O447/juOO/o7jjv+O447+juOO/o7jjv+O447+juOO/o7jjv+O447+juOO/o7j + jv9s2mz+Yaph/sbGxv+enp/+hISFOwAAAAAAAAAAoKCgB7GxsuS3t7f/iJSJ/0XGRf+K44r/kuSS/5Lk + kv+T5JP/k+ST/5Pkk/+T5JP/k+ST/5Pkk/+T5JP/k+ST/5Pkk/+T5JP/k+ST/5Pkk/+T5JP/k+ST/5Lk + kv+S5JL/kuSS/5Lkkv+S5JL/kuSS/5Lkkv+S5JL/kuSS/5Lkkv+S5JL/kuSS/5Lkkv+S5JL/kuSS/5Lk + kv+S5JL/kuSS/4Xhhf9AxUD/qLSo/6Cgof+UlJXkioqKBwAAAAAAAAAAAAAAAI+PkHTg4OD/kpKS/naV + dv5Fx0b/dd51/pHkkf6V5pX/luaW/pbmlv+W5pb+luaW/pbmlv6W5pb/luaW/pbmlv6W5pb/luaW/pbm + lv6W5pb/luaW/pbmlv6W5pb/luaW/pbmlv6W5pb/luaW/pbmlv6W5pb/luaW/pbmlv+W5pb+luaW/pbm + lv+W5pb+luaW/pXmlf+P5I/+cN1w/kDGQP+EpIX+pqan/qenqP9/f4B0AAAAAAAAAAAAAAAAAAAAAKCg + oAaenp/G1tbX/pCQkf6GkYf/WqNb/kS2Rf5Fw0X/RcRF/kXERf9FxEX+RcRF/kXERf5FxEX/RcRF/kXE + Rf5FxEX/RcRF/kXERf5FxEX/RcRF/kXERf5FxEX/RcRF/kXERf5FxEX/RcRF/kXERf5FxEX/RcRF/kXE + Rf9FxEX+RcRF/kXERf9FxEX+RcRF/kXDRf9EtkT+XKRd/pijmf+enp/+p6eo/o+Pj8aKiosGAAAAAAAA + AAAAAAAAAAAAAAAAAACampoVnZ2dxd/f3/+zs7T/lJSV/4+PkP+Ojo//jo6P/46Oj/+Ojo//jo6P/46O + j/+Ojo//jo6P/46Oj/+Ojo//jo6P/46Oj/+Ojo//jo6P/46Oj/+Ojo//jo6P/46Oj/+Ojo//jo6P/46O + j/+Ojo//jo6P/46Oj/+Ojo//jo6P/46Oj/+Ojo//jo6P/4+PkP+UlJX/mJiZ/6Ojo//Dw8T/k5OUxYmJ + ihUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAn5+fBoyMjHSurq7k19fY/tjY2P7MzMz/x8fH/sbG + x//Gxsf+xsbH/sbGx/7Gxsf/xsbH/sbGx/7Gxsf/xsbH/sbGx/7Gxsf/xsbH/sbGx/7Gxsf/xsbH/sbG + x/7Gxsf/xsbH/sbGx/7Gxsf/xsbH/sbGx//Gxsf+xsbH/sbGx//Gxsf+xsbH/sjIyP/Pz9D+0NDQ/qys + rOOHh4d0lZWVBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgoKAGl5eXOpaW + l2ihoaJ8pKSkf6SkpH+kpKR/pKSkf6SkpH+kpKR/pKSkf6SkpH+kpKR/pKSkf6SkpH+kpKR/pKSkf6Sk + pH+kpKR/pKSkf6SkpH+kpKR/pKSkf6SkpH+kpKR/pKSkf6SkpH+kpKR/pKSkf6SkpH+kpKR/pKSkf6Gh + oXyVlZZolpaWOp6engYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///////8AAPwA + AAAAPwAA8AAAAAAPAADgAAAAAAcAAMAAAAAAAwAAwAAAAAADAACAAAAAAAEAAIAAAAAAAQAAgAAAAAAB + AACAAAAAAAEAAIAAAAAAAQAAgAAAAAABAACAAAAAAAEAAIAAAAAAAQAAgAAAAAABAACAAAAAAAEAAIAA + AAAAAQAAgAAAAAABAACAAAAAAAEAAIAAAAAAAQAAgAAAAAABAACAAAAAAAEAAIAAAAAAAQAAgAAAAAAB + AACAAAAAAAEAAIAAAAAAAQAAgAAAAAABAACAAAAAAAEAAIAAAAAAAQAAgAAAAAABAACAAAAAAAEAAIAA + AAAAAQAAgAAAAAABAACAAAAAAAEAAIAAAAAAAQAAgAAAAAABAACAAAAAAAEAAIAAAAAAAQAAgAAAAAAB + AACAAAAAAAEAAIAAAAAAAQAAgAAAAAABAADAAAAAAAMAAMAAAAAAAwAA4AAAAAAHAADwAAAAAA8AAPwA + AAAAPwAA////////AAAoAAAAIAAAAEAAAAABACAAAAAAAIAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAB9fX02ioqKqoaGh+mHh4f9hoaH/4aGh/+Ghof/hoaH/4aGh/+Ghof/hoaH/4aG + h/+Ghof/hoaH/4aGh/+Ghof/hoaH/4aGh/+Ghof/hoaH/4aGh/+Ghof/hoaG/YODg+mCgoOqd3d4NgAA + AAAAAAAAAAAAAAAAAAAAAAAAjIyNap2dnvytra7/prKm/561nv+ftp//n7ef/5+3n/+ft5//n7ef/5+3 + n/+ft5//n7ef/5+3n/+ft5//n7ef/5+3n/+ft5//n7ef/5+3n/+ft5//n7ef/5+3n/+ft6D/r7uw/8HB + wf+VlZX8e3t8agAAAAAAAAAAAAAAAI+Pjzavr6/8maKa/0SLRP8wjzD/MI8w/zCPMP8wjzD/MI8w/zCP + MP8wjzD/MI8w/zCPMP8wjzD/MI8w/zCPMP8wjzD/MI8w/zCPMP8wjzD/MI8w/zCPMP8wjzD/MI8w/zCP + MP8wjzD/RYxG/7rDuv+Xl5j8fHx9NgAAAAAAAAAAr6+vq6enqP9EjET/MJEw/zCRMP8wkTD/MJEw/zCR + MP8wkTD/MJEw/zCRMP8wkTD/MJEw/zCRMP8wkTD/MJEw/zCRMP8wkTD/MJEw/zCRMP8wkTD/MJEw/zCR + MP8wkTD/MJEw/zCRMP8wkTD/Ro5G/8XFxf+JiYqrAAAAAAAAAAC5ubnph5SH/zCTMP8wkzD/MJMw/zCT + MP8wkzD/MJMw/zCTMP8wkzD/MJMw/0aWRf99m3v/f559/3+dfP9+nHz/fpx7/32be/98mnr/fJp6/3ya + ef97mXn/e5l5/3qYeP95l3f/TJJL/zCTMP8wkzD/sr+y/42NjukAAAAAAAAAALu7vP57lHz/MJUw/zCV + MP8wlTD/MJUw/zCVMP8wlTD/MJUw/zCVMP8wlTD/VZlU/+Pi4f/49fP/9/Tx//fz8P/38u//9/Lv//bx + 7v/28O3/9fDt//bw7f/28O3/9vDt/+7u7P9dk1z/MJUw/zCVMP+jvKT/k5OU/gAAAAAAAAAAvb2+/32X + fv8wlzD/MJcw/zCXMP8wlzD/MJcw/zCXMP8wlzD/MJcw/zCXMP9Wm1T/4+Ph//Tp5P/y5d//8ePc//Dg + 2f/v3tb/7tvT/+3Z0f/s2M//7NfO/+zXzv/s187/7evp/16UXP8wlzD/MJcw/6S+pP+Xl5j/AAAAAAAA + AAC/v8D/gJqB/zCaMP8wmjD/MJow/zCaMP8wmjD/MJow/zCaMP8wmjD/MJow/1adVf/k4+L/9e3o//Tp + 5P/y5+H/8eTe//Di2//v39j/7t3V/+3a0v/s2ND/7NfO/+zXzv/t6+n/XpZc/zCaMP8wmjD/pb+l/5qa + m/8AAAAAAAAAAMHBwv+CnYP/MJww/zCcMP8wnTD/MZ0x/zGdMf8xnTH/MZ0x/zGdMf8xnTH/V59W/+Tj + 4//38Oz/29TQ/8/HxP/NxMH/y8K+/8rAvP/Jvrr/yLy4/8a7tv/HurX/7NjQ/+7r6v9emF3/MJww/zCc + MP+mwab/np6f/wAAAAAAAAAAw8PE/4Wghv8wnzD/MJ8w/3Obcf+osKX/p6+l/6avpP+mrqP/pa6j/6Wt + ov+jp5//5OTj//fw7f/07On/8enl//Dn4//v5eD/7uPd/+3g2//r3tj/6tvV/+rZ0v/u29T/7uzq/1+Z + Xf8wnzD/MJ8w/6fDqP+hoaL/AAAAAAAAAADFxcb/h6OI/zGiMf8xojH/hqWE/+7s6v/s5eL/6+Tg/+rj + 3//q4t3/6eDc/9HKxv/k5OP/9/Dt/+Hb2P/X0c//1M7L/+7m4v/Xz8z/1MvH/9HIxP/RxsL/0MXA/+7e + 1//u7Ov/YJte/zGiMf8xojH/qMSp/6Skpf8AAAAAAAAAAMfHx/+Jpor/MaQx/zGkMf+Gp4T/7ero/+ne + 2f/o29b/59nT/+bX0P/l1M3/zsG8/+Xk4//38O3/7ujk/+nj3//o4t7/8uvn/9XPy//x6OT/8Obh/+/k + 3//SyMT/7+Lb/+7t6/9gnV7/MaQx/zGkMf+pxqn/pqao/wAAAAAAAAAAyMjJ/4qoi/8xpzH/Macx/4eo + hf/u6+n/6+Ld/+Ta1f/j19P/4dXQ/+DSzf/Mwbz/5eXk//fw7f/n4N3/39jV/93W0//v6OX/19DO//fv + 6//27un/9ezn/9XMyP/x5uD/7+7s/2CfX/8xpzH/Macx/6rHqv+oqKr/AAAAAAAAAADJycr/i6qM/zGq + Mf8xqjH/iKqG/+7s6v/o4d3/x8K//8bAvf/DvLn/wru3/7ixrv/l5eT/9/Dt/+ni3//i29j/4NnW//Dp + 5f/X0M7/9/Ds//fv6//27+v/1s7L//Pq5f/v7u3/YaFf/zGqMf8xqjH/qsmr/6qqq/8AAAAAAAAAAMrK + yv+Mq43/Ma0x/zGtMf+Iq4b/7uzq/+3m4v/s5eH/6+Pf/+ri3f/q4Nv/0snG/+Xl5P/38O3/7OXi/+bg + 3f/l3tv/8erm/9XPzP/v6OT/7ujk/+/o5P/Uzcr/9O3o/+/v7f9ho1//Ma0x/zGtMf+ryqv/q6ut/wAA + AAAAAAAAysrK/4ysjf8ysTL/MbAx/4msh//u7Or/6eLe/8XAvv/Ev73/yMPA/9vU0P+7trT/5uXk//fw + 7f/j3dr/29XS/9jSz//w6eX/3NbT/9nT0P/Y0c7/2NHO/9jSz//27+v/8O/t/2KlYP8zsTP/NbI1/6vL + q/+rq63/AAAAAAAAAADJycr/jKyN/0a7Rv9MvUz/l7eV//Du7P/u6OT/6+Xh/+vk4f/r5eH/29XS/8jC + wP/n5uX/9/Ht//fw7P/38Oz/9/Ds//fw7f/38Oz/9/Dt//fw7f/z7en/6uTh/+nj4P/n5uX/b6pt/029 + Tf9Hu0f/q8ur/6qqrP8AAAAAAAAAAMjIyf+LrIz/S79L/1PCU/+evJv/8e/u/+3n5P/Uz83/087N/9bS + z//g2tj/z8vJ/+rq6f/48/D/+PLv//jy7//48u//+PLv//jy7//48u//+PLv/+Pe2/++urn/vLi3/7+8 + vP90r3L/U8JT/0y/TP+qy6v/qamq/wAAAAAAAAAAx8fI/4mriv9Qw1D/Wsda/6LAoP/x8O7/8Orn/+ji + 4P/n4t//6eTh/+Hc2f/Rzcv/6+vq//nz8P/48/D/+PPw//jz8P/58/D/+PPw//jz8P/48u//2NPR/93d + 3f/a2tr/oLKe/1/DX/9ax1r/UcNR/6nLqv+np6j/AAAAAAAAAADFxcb/iKqI/1XHVf9hy2H/psOk//Lw + 7//v6eb/3dnW/9zY1v/f29j/4t3b/8/Lyv/s7Ov/+fTx//nz8P/58/D/+fPw//nz8P/58/D/+fPw//nz + 8P/a1tT/1dTU/6m4p/9nx2b/Ycth/2HLYf9WyFb/qcup/6Skpv8AAAAAAAAAAMTExf+FqYb/Wsta/2jP + aP+qx6j/8/Hw//Dr6P/l4N7/5ODd/+bi3//t6OX/2NTS/+jn5v/19PP/9PTz//T08//09PP/9PTz//T0 + 8//09PL/9PTy/9vZ2f+suan/b8tu/2jPaP9oz2j/aM9o/1zMXP+oy6j/oqKj/wAAAAAAAAAAwsLC/4On + hP9gz2D/b9Nv/67Krf/z8vD/8u3q//Lt6v/y7ev/8u3q//Lt6v/s5+X/2tbU/9rV1P/Tz87/zcnI/87L + yv/DwcH/k8OS/5XJk/+UyJL/kseR/3jReP9v02//b9Nv/2/Tb/9v02//Ys9i/6fKp/+enp//AAAAAAAA + AADAwMD/gaWC/2XSZf9213b/ss2x//Tz8f/z7uv/8+7r//Pu6//z7uv/8+7r//Pu6//z7uv/8u3q/8zJ + yP/Gw8P/xMLC/7W3s/9403j/dtd2/3bXdv9213b/dtd2/3bXdv9213b/dtd2/3bXdv9o02j/psqm/5ub + nP8AAAAAAAAAAL6+vv9+o3//a9Zr/33bff+30bX/9PPy//Pv7P/z7+z/8+/s//Pv7P/z7+z/8+/s//Pv + 7P/y7uv/zszL/+Xl5f/Iycb/js6N/33bff99233/fdt9/33bff99233/fdt9/33bff99233/fdt9/27X + bv+lyqX/l5eY/wAAAAAAAAAAvb29/nyhff9v2W//hN6E/7rUuf/19PP/9PHu//Tx7v/08e7/9PHu//Tx + 7v/08e7/9PHu//Pw7v/Qzs3/zc3L/5XRlP+E3oT/hN6E/4TehP+E3oT/hN6E/4TehP+E3oT/hN6E/4Te + hP+E3oT/ctpy/6PIo/+UlJX+AAAAAAAAAAC+vr/phJiF/2nZaf+K4Yr/u9S6/+bl5f/m5eX/5uXl/+bl + 5f/l5eX/5eXk/+Xl5P/l5OT/5eTk/8jIx/+d1J3/iuGK/4rhiv+K4Yr/iuGK/4rhiv+K4Yr/iuGK/4rh + iv+K4Yr/iuGK/4rhiv9o2Wj/qr6r/5GRkekAAAAAAAAAALOzs6unp6f/VrtX/43jjf+a4Zr/oN+f/6Df + n/+g35//n9+f/5/fn/+f35//n9+e/5/fnv+e3p7/m+Ca/5Hkkf+R5JH/keSR/5Hkkf+R5JH/keSR/5Hk + kf+R5JH/keSR/5Hkkf+R5JH/i+OL/1W9Vf+ysrL/kpKSqwAAAAAAAAAAlpaXNsbGx/yEkoT/V7tX/2/d + b/994H3/feB9/33gff994H3/feB9/33gff994H3/feB9/33gff994H3/feB9/33gff994H3/feB9/33g + ff994H3/feB9/33gff994H3/feB9/27dbv9UvFX/mqia/5+foPyFhYU2AAAAAAAAAAAAAAAAnJydacXF + xvyjo6P/fZB+/3SadP9zmnT/c5p0/3OadP9zmnT/c5p0/3OadP9zmnT/c5p0/3OadP9zmnT/c5p0/3Oa + dP9zmnT/c5p0/3OadP9zmnT/c5p0/3OadP90mnT/gZSC/6Ojo/+tra78jY2OaQAAAAAAAAAAAAAAAAAA + AAAAAAAAlZWVNq+vr6q5ubnotbW1/bOztP+zs7T/s7O0/7OztP+zs7T/s7O0/7OztP+zs7T/s7O0/7Oz + tP+zs7T/s7O0/7OztP+zs7T/s7O0/7OztP+zs7T/s7O0/7OztP2zs7PorKysqpCQkTYAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAP/////gAAAHwAAAA4AAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAA + AAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAA + AAGAAAABwAAAA+AAAAf/////KAAAABgAAAAwAAAAAQAgAAAAAABgCQAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAGNjYxBsbGw5cHBxP3FxcT9xcXE/cXFxP3FxcT9xcXE/cXFxP3FxcT9xcXE/cXFxP3Fx + cT9xcXE/cXFxP3BwcT9ra2w5Y2NjEAAAAAAAAAAAAAAAAAAAAABubm8Fi4uMj5+foPivr7D/rq6u/q6u + rv+urq7/rq6u/q6urv+urq7/rq6u/66urv6urq7/rq6u/q6urv+urq7/rq6u/q6urv+xsbH/paWm+H9/ + gI9ra2wFAAAAAAAAAACdnZ6Qm6Cc/luVW/41izX+Mowy/jKMMv4yjDL+Mowy/jKMMv4yjDL+Mowy/jKM + Mv4yjDL+Mowy/jKMMv4yjDL+Mowy/jKMMv41izX+X5lf/rG2sf6CgoOQAAAAAHh4eBCysrP4VpJW/jCR + MP8wkTD/L5Ev/jCRMP8wkTD/L5Ev/jGSMf80kzT/NJM0/zSTNP40kzT/NJI0/jSTNP80kjT/NJI0/jSS + NP8zkjP/L5Ev/l+bX/+rq6z4dnZ3EImJiTm1tbb/NpA2/jCUMP8wlDD/L5Qv/jCUMP8wlDD/L5Qv/meb + Zf/Mzcr/y8zJ/8vMyP7Ky8f/ycrH/snKxv/Iysb/yMnF/sjJxf+XqJX/L5Qv/jaRNv+4uLn/g4OEOZWV + lj+1tbb+M5Qz/i+XL/4vly/+L5cv/i+XL/4vly/+L5cv/m6hbP738u/+8+fh/vHj3f7w4Nn+793W/u3b + 0/7t2dH+7dnQ/u/e1/6vvq7+L5cv/jOUM/65ubn+jY2OP5iYmT+4uLn/NJg0/jCaMP8wmjD/L5ov/jCa + MP8wmjD/L5ov/m+jbf/49PH/8efi/+vg2/7q3Nf/6NnT/ubWz//l08z/5dLK/u7d1f+wv67/L5ov/jSY + NP+8vL3/kZGTP5ubnD+8vLz/NJs0/jKeMv9bmVn/XJlb/lyYWv9bmFn/W5dZ/oShgf/49fP/6eLe/9zV + 0f7a0c3/2c7K/tfMx//VycT/1cfB/u/e1/+wwK7/MJ4w/jSbNP+/v8D/lpaXP56enz++vr/+NZ81/jai + Nv7Iycb+6ubj/urk4v7p4+D+6OLe/svGxP749fP+6uTg/t/Y1f7l3dr+49vW/tvRzf7Zzsn+2MvG/vDi + 3P6xwa/+MKEw/jWfNf7CwsP+mpqbP6CgoT/BwcL/NaM1/jemNv/Ky8j/6t/a/ujc1v/n2NL/5dXO/srA + u//49fP/8uvn/+3m4v7w6eb/29XS/vLq5f/x5+L/2tDL/vHm4f+xwrD/MKUw/jWjNv/ExMX/nZ2eP6Ki + oz/Dw8T/NqY2/jepNv/LzMn/6uLe/tHKxv/Px8P/zcO//r63tP/49fP/5t/c/9XOzP7f2db/3NbT/vfv + 6//27ur/3dXR/vPr5v+yw7D/MKkw/jamNv/Gxsf/n5+hP6Ojoz/ExMX/Nqo2/jetNv/LzMn/7Obi/uXe + 2v/k3Nj/49nV/snCwP/49fP/8erm/+rk4P7v6OT/29XS/vHq5v/x6ub/29XR/vXu6/+yxLD/MK0w/jaq + Nv/Hx8j/oaGiP6OjpD/ExMX+O687/jyzPP7Mzcr+6uTg/s3Hxf7KxcL+29XR/r65t/749fP+7OXi/uLb + 2P7o4d7+5+Dd/uDa1/7f2dX+3tjV/vXv7P6zxbL+ObM5/jywPP7Hx8j+oaGiP6Kioz/Dw8T/SLhI/lbA + Vv/U1NL/7+nm/uPd2v/i3Nn/4dvY/svGxf/59vT/9/Hu//fx7v748e7/9/Hu/vfx7v/17+z/2tXT/tbS + 0P+ru6n/UMBQ/km4Sf/Gxsf/oKChP6CgoT/BwcL+TbxN/l7GXv7W19X+7+rm/uHc2v7g29j+497b/s/M + yv769/X++PLv/vjy7/748+/++PLv/vjy7/7y7On+yMbH/snHx/6CtID+WcZZ/k29Tv7ExMX+nZ2fP56e + nz+/v8D/UcFR/mbMZv/Z2df/7+rn/trW1P/Z1dL/5N/d/s7Lyv/6+Pb/+fXy//n18v759fL/+fXy/vn1 + 8v/08O3/yMfG/pG9j/9izGL/Ysxi/lLBUv/CwsP/mpqcP5ycnT+8vL3/VsVW/nDRb//b3Nr/8u3q/u/r + 6P/v6uj/8ezp/t7a2P/f3t3/3tzb/9za2v7c2tr/zdbL/svayv/J18f/l8GV/mzRbP9r0Wv/a9Fr/ljG + WP+/v8D/l5eYP5mZmj+5ubr+XMlc/nnWef7e393+8+7r/vPu6/7z7uv+8+7r/vPu6/7z7uv+2tbU/srH + x/7HxcT+g8mC/nXWdf511nX+ddZ1/nXWdf511nX+ddZ1/l7JXv68vL3+kpKTP5aWlj+1tbb/Yc1h/oLb + gv/g4d//8+/s/vPv7P/z7+z/8+/s/vPv7P/z7+z/19TT/97d3f6jyaL/f9t//n7cfv9+3H7/ftx+/n7c + fv9+3H7/ftx+/mPOY/+5ubr/jo6PP4uLizm3t7j/Zc1l/ovfi//i4uH/9PLx/vTy8f/08vH/9PLx/vTy + 8f/08vH/19bV/6zOq/6I34j/h+CH/ofgh/+H4If/h+CH/ofgh/+H4If/h+CH/mbNZv+3t7j/hYWGOXx8 + fBC4uLj4ZrZn/o/jj/6p2qj+qtqp/qraqf6q2an+qtmp/qrZqf6p2Kj+pdik/pDjkP6Q45D+kOOQ/pDj + kP6Q45D+kOOQ/pDjkP6Q45D+jOOM/m2/bf6mpqf4e3t8EAAAAACrq6yQm6Oc/me2Z/9s0Wz/bdVt/m3V + bf9t1W3/bdVt/m3Vbf9t1W3/bdVt/23Vbf5t1W3/bdVt/m3Vbf9t1W3/bdVt/m3Vbf9r0Wv/abpp/pyk + nf+QkJGQAAAAAAAAAACAgIAFqqqqj7OztPiwsLH/qqqr/qqqq/+qqqv/qqqr/qqqq/+qqqv/qqqr/6qq + q/6qqqv/qqqr/qqqq/+qqqv/qqqr/qqqq/+vr6//rq6u+J2dnY99fX4FAAAAAAAAAAAAAAAAAAAAAIKC + gxCRkZI5m5ucP5ycnD+cnJw/nJycP5ycnD+cnJw/nJycP5ycnD+cnJw/nJycP5ycnD+cnJw/nJycP5ub + nD+SkpI5hISEEAAAAAAAAAAAAAAAAOAABwCAAAEAgAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAQCAAAEA4AAHACgA + AAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAS0tMDXR0dGR5eXp/eXl6f3l5 + en95eXp/eXl6f3l5en95eXp/eXl6f3l5en95eXl/cXFyZExMTA0AAAAAU1NUDZyendhynnL/Z6Nn/2ej + Z/9no2f/Z6Nn/2ejZ/9no2f/Z6Nn/2ejZ/9no2f/Z6Nn/3mmev+YmpnYU1NTDZWVlWVolmn/MJIw/zCS + MP8wkjD/MJIw/0mVSP9Xl1b/V5dW/1aWVf9WlVT/VZVU/1WUU/83kjb/e6l7/4KCg2Wmpqd/VpZW/zCW + MP8wljD/MJYw/zCWMP+cvpv/9e7q//Tq5f/y5+L/8eTf//Hj3f/v6OT/R5VG/2mqav+QkJF/rKysf1ib + Wf8wmzD/MJsw/zCbMP8wmzD/ncGc/+/m4v/g1tH/3dDL/9vMxv/ZycP/7eHc/0eZRv9qrmv/l5eZf6+v + sH9boVz/VqBV/8rMxf/IycL/x8e//8/Oy//x6ub/49zY/+jf2//f1M//3dDK/+7k4P9InUf/bLJs/56e + n3+zs7N/XaZd/1ynW//s5eL/5dnU/+PVzv/Z09D/8erm/+Pd2f/j3dn/8+vn/+PZ1f/v6OX/SKJH/222 + bf+jo6R/tLS1f16rX/9cq1v/7Ojl/9nSz//Wzsr/1dHP//Hq5v/j3dn/493Z//Ps6P/k3dn/8e3q/0mn + SP9tum7/pqanf7W1tX9ksWX/Z7Rm/+3p5v/Y0s//2tTR/9TRz//y7Oj/6OLe/+7o5P/o4d7/493a/+3q + 5/9Ur1P/dMF1/6amqH+zs7R/bLZs/3vBev/w7Or/3tjW/+Db2P/d29r/+PPw//jy7//48u//+PLv/9bS + 0P+9wLv/YL9g/3zGfP+jo6V/sLCxf2+5b/+GyYX/8e7r/+Hc2v/l4N7/393b//f08v/29PH/9vTx//bz + 8f/Nz8r/ecZ5/2TNZP+ByoH/np6gf6ysrX9yu3P/kdCR//Pw7v/y7ev/8u3r/+vm5P/a1tX/ycbG/6HD + n/+F0IT/ftF9/3LVcv9y1XL/hc6G/5iYmX+oqKh/db11/5zXnP/08vD/9PDt//Tw7f/08O3/4d7c/8TT + w/+F2YT/gN2A/4DdgP+A3YD/gN2A/4rQiv+RkZJ/mZmZZXq1e/+b3pv/w+LC/8Piwv/C4sL/wuLB/7na + uf+S35L/juOO/47jjv+O447/juOO/4zijP+GwYf/h4eIZVtbXA2rrqvYerN6/3i9eP94vXj/eL14/3i9 + eP94vXj/eL14/3i9eP94vXj/eL14/3i9eP95tHr/naGe2FxcXA0AAAAAXl5eDZycnWSpqap/qqqqf6qq + qn+qqqp/qqqqf6qqqn+qqqp/qqqqf6qqqn+pqal/m5ubZGBgYA0AAAAAgAEAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAEAAA== + + + \ No newline at end of file diff --git a/Duplicati/GUI/Duplicati.GUI.TrayIcon/app.config b/Duplicati/GUI/Duplicati.GUI.TrayIcon/app.config new file mode 100644 index 000000000..02451de7f --- /dev/null +++ b/Duplicati/GUI/Duplicati.GUI.TrayIcon/app.config @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Duplicati/GUI/app.config b/Duplicati/GUI/app.config index a7d04fa82..34c68c314 100644 --- a/Duplicati/GUI/app.config +++ b/Duplicati/GUI/app.config @@ -1,3 +1,7 @@ - + + + + + diff --git a/Duplicati/License/Duplicati.License.csproj b/Duplicati/License/Duplicati.License.csproj index 715cfa78a..154b6f289 100644 --- a/Duplicati/License/Duplicati.License.csproj +++ b/Duplicati/License/Duplicati.License.csproj @@ -137,8 +137,22 @@ PreserveNewest - - + + PreserveNewest + licenses\SSH.NET\Homepage.txt + + + PreserveNewest + licenses\SSH.NET\License.txt + + + PreserveNewest + licenses\Json.NET\Homepage.txt + + + PreserveNewest + licenses\Json.NET\License.txt + diff --git a/Duplicati/Server/Duplicati.Server.Serialization/Duplicati.Server.Serialization.csproj b/Duplicati/Server/Duplicati.Server.Serialization/Duplicati.Server.Serialization.csproj index 9077652ca..8bc81c354 100644 --- a/Duplicati/Server/Duplicati.Server.Serialization/Duplicati.Server.Serialization.csproj +++ b/Duplicati/Server/Duplicati.Server.Serialization/Duplicati.Server.Serialization.csproj @@ -1,4 +1,4 @@ - + Debug @@ -61,6 +61,12 @@ 4 + + ..\..\..\thirdparty\LightDataModel\LightDatamodel.dll + + + ..\..\..\thirdparty\Json.NET\Newtonsoft.Json.dll + @@ -70,14 +76,15 @@ - - - - - + + + + + + - + diff --git a/Duplicati/Server/Duplicati.Server.Serialization/Enums.cs b/Duplicati/Server/Duplicati.Server.Serialization/Enums.cs index 4eef8b80c..7ce12deba 100755 --- a/Duplicati/Server/Duplicati.Server.Serialization/Enums.cs +++ b/Duplicati/Server/Duplicati.Server.Serialization/Enums.cs @@ -5,11 +5,72 @@ using System.Text; namespace Duplicati.Server.Serialization { - public enum ServiceState + public enum RunnerState { + Started, + Suspended, Running, - Paused, - Suspended + Stopped, } + public enum RunnerResult + { + OK, + Partial, + Warning, + Error + } + + public enum CloseReason + { + None, + ApplicationExitCall, + TaskManagerClosing, + WindowsShutDown, + UserClosing + } + + public enum LiveControlState + { + Running, + Paused + } + + + public enum DuplicatiOperation + { + Backup, + Restore, + List, + Remove + } + + public enum DuplicatiOperationMode + { + Backup, + BackupFull, + BackupIncremental, + Restore, + RestoreControlfiles, + List, + GetBackupSets, + ListCurrentFiles, + ListSourceFolders, + ListActualSignatureFiles, + DeleteAllButNFull, + DeleteAllButN, + DeleteOlderThan, + CleanUp, + CreateFolder, + FindLastFileVersion, + Verify + } + + public static class EnumConverter + { + public static T Convert(Enum o) + { + return (T)Enum.Parse(typeof(T), o.ToString(), false); + } + } } diff --git a/Duplicati/Server/Duplicati.Server.Serialization/IProgressEventData.cs b/Duplicati/Server/Duplicati.Server.Serialization/IProgressEventData.cs new file mode 100644 index 000000000..721b490b5 --- /dev/null +++ b/Duplicati/Server/Duplicati.Server.Serialization/IProgressEventData.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Duplicati.Server.Serialization +{ + public interface IProgressEventData + { + DuplicatiOperation Operation { get; } + DuplicatiOperationMode Mode { get; } + string Message { get; } + string SubMessage { get; } + int Progress { get; } + int SubProgress { get; } + } +} diff --git a/Duplicati/Server/Duplicati.Server.Serialization/ISerializableStatus.cs b/Duplicati/Server/Duplicati.Server.Serialization/ISerializableStatus.cs new file mode 100644 index 000000000..9d1fb72aa --- /dev/null +++ b/Duplicati/Server/Duplicati.Server.Serialization/ISerializableStatus.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; + +namespace Duplicati.Server.Serialization +{ + public interface ISerializableStatus + { + RunnerState ActiveBackupState { get; } + long ActiveScheduleId { get; } + LiveControlState ProgramState { get; } + IProgressEventData RunningBackupStatus { get; } + System.Collections.Generic.IList SchedulerQueueIds { get; } + } +} diff --git a/Duplicati/Server/Duplicati.Server.Serialization/Implementations/ProgressEventData.cs b/Duplicati/Server/Duplicati.Server.Serialization/Implementations/ProgressEventData.cs new file mode 100644 index 000000000..4a68de8a7 --- /dev/null +++ b/Duplicati/Server/Duplicati.Server.Serialization/Implementations/ProgressEventData.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Duplicati.Server.Serialization.Implementations +{ + internal class ProgressEventData : IProgressEventData + { + public DuplicatiOperation Operation { get; set; } + + public DuplicatiOperationMode Mode { get; set; } + + public string Message { get; set; } + + public string SubMessage { get; set; } + + public int Progress { get; set; } + + public int SubProgress { get; set; } + } +} diff --git a/Duplicati/Server/Duplicati.Server.Serialization/Implementations/SerializableStatus.cs b/Duplicati/Server/Duplicati.Server.Serialization/Implementations/SerializableStatus.cs new file mode 100644 index 000000000..3f3b5451b --- /dev/null +++ b/Duplicati/Server/Duplicati.Server.Serialization/Implementations/SerializableStatus.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Duplicati.Server.Serialization.Implementations +{ + internal class SerializableStatus : ISerializableStatus + { + public RunnerState ActiveBackupState { get; set; } + public long ActiveScheduleId { get; set; } + public LiveControlState ProgramState { get; set; } + public IProgressEventData RunningBackupStatus { get; set; } + public IList SchedulerQueueIds { get; set; } + } +} diff --git a/Duplicati/Server/Duplicati.Server.Serialization/InterfaceResolver.cs b/Duplicati/Server/Duplicati.Server.Serialization/InterfaceResolver.cs new file mode 100644 index 000000000..9f27847e6 --- /dev/null +++ b/Duplicati/Server/Duplicati.Server.Serialization/InterfaceResolver.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Newtonsoft.Json.Converters; + +namespace Duplicati.Server.Serialization +{ + public class SerializableStatusCreator : CustomCreationConverter + { + public override ISerializableStatus Create(Type objectType) + { + return new Implementations.SerializableStatus(); + } + } + + public class ProgressEventDataCreator : CustomCreationConverter + { + public override IProgressEventData Create(Type objectType) + { + return new Implementations.ProgressEventData(); + } + } +} diff --git a/Duplicati/Server/Duplicati.Server.Serialization/JsonSerializer.cs b/Duplicati/Server/Duplicati.Server.Serialization/JsonSerializer.cs new file mode 100644 index 000000000..46dbf4c86 --- /dev/null +++ b/Duplicati/Server/Duplicati.Server.Serialization/JsonSerializer.cs @@ -0,0 +1,180 @@ +// Copyright (C) 2011, Kenneth Skovhede +// http://www.hexad.dk, opensource@hexad.dk +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +using System; +using System.Linq; +using Newtonsoft.Json.Serialization; +using System.Reflection; +using Newtonsoft.Json; +using System.Globalization; +using System.Collections.Generic; + +namespace Duplicati.Server.Serialization +{ + internal class JsonSerializer : DefaultContractResolver + { + private Dictionary m_ignoreList = GetIgnoreList(); + + private static Dictionary GetIgnoreList() + { + Dictionary lst = new Dictionary(); + lst.Add("Datamodel.ApplicationSettings!RawOptions", null); + + return lst; + } + + private static string MemberInfoAsKey(MemberInfo mi) { return mi.DeclaringType.FullName + "!" + mi.Name; } + + protected override List GetSerializableMembers(Type objectType) + { + return base.GetSerializableMembers(objectType).Where(x => !m_ignoreList.ContainsKey(MemberInfoAsKey(x))).ToList(); + } + + protected override JsonObjectContract CreateObjectContract (Type objectType) + { + if (typeof(System.Data.LightDatamodel.IDataFetcher).IsAssignableFrom(objectType)) + { + //If this type was ever serialized, it would expose the entire internal object cache, and we do NOT want that :) + throw new Exception("Internal error, a non-serializable type was hit"); + } + else if (typeof(System.Data.LightDatamodel.IDataClass).IsAssignableFrom(objectType)) + { + JsonObjectContract joc = new JsonObjectContract(objectType); + + foreach(var pi in objectType.GetProperties( BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance )) + { + var customs = pi.GetCustomAttributes(false); + bool isRef = customs.Select(x => x.GetType()).Contains(typeof(System.Data.LightDatamodel.DataClassAttributes.Affects)); + bool isParent = typeof(System.Data.LightDatamodel.IDataFetcher).IsAssignableFrom(pi.PropertyType); + isRef |= typeof(System.Data.LightDatamodel.IDataClass).IsAssignableFrom(pi.PropertyType); + + joc.Properties.Add(new JsonProperty() { + PropertyName = pi.Name, + PropertyType = pi.PropertyType, + Ignored = isRef || isParent || m_ignoreList.ContainsKey(MemberInfoAsKey(pi)), + UnderlyingName = pi.Name, + Readable = pi.CanRead, + Writable = pi.CanWrite, + ValueProvider = CreateMemberValueProvider(pi) + }); + } + + return joc; + } + else + return base.CreateObjectContract (objectType); + } + + protected override IValueProvider CreateMemberValueProvider(MemberInfo member) + { + if (member.MemberType == System.Reflection.MemberTypes.Property && ((PropertyInfo)member).PropertyType.IsEnum) + return new EnumValueProvider(member); + else if (member.MemberType == System.Reflection.MemberTypes.Field && ((FieldInfo)member).FieldType.IsEnum) + return new EnumValueProvider(member); + else + return base.CreateMemberValueProvider(member); + } + + /// + /// Get and set values for a Enum using reflection. + /// + private class EnumValueProvider : IValueProvider + { + private Type m_enumType; + + private MemberInfo m_member; + + /// + /// Initializes a new instance of the class. + /// + /// The property info. + public EnumValueProvider(MemberInfo mi) + { + if (mi == null) + throw new ArgumentNullException("mi"); + if (mi.MemberType == MemberTypes.Property) + m_enumType = ((PropertyInfo)mi).PropertyType; + else if (mi.MemberType == MemberTypes.Field) + m_enumType = ((FieldInfo)mi).FieldType; + else + throw new ArgumentException(string.Format("MemberInfo '{0}' must be of type FieldInfo or PropertyInfo", CultureInfo.InvariantCulture, m_member.Name, "member")); + + m_member = mi; + } + + /// + /// Sets the value. + /// + /// The target to set the value on. + /// The value to set on the target. + public void SetValue(object target, object value) + { + try + { + if (target == null) + throw new ArgumentNullException("target"); + + object parsedValue = value is string ? Enum.Parse(m_enumType, value as String, true) : value; + + switch (m_member.MemberType) + { + case MemberTypes.Field: + ((FieldInfo)m_member).SetValue(target, parsedValue); + break; + case MemberTypes.Property: + ((PropertyInfo)m_member).SetValue(target, parsedValue, null); + break; + default: + throw new ArgumentException(string.Format("MemberInfo '{0}' must be of type FieldInfo or PropertyInfo", CultureInfo.InvariantCulture, m_member.Name, "member")); + } + } + catch (Exception ex) + { + throw new JsonSerializationException(string.Format("Error setting value to '{0}' on '{1}'.", CultureInfo.InvariantCulture, m_member.Name, (target == null ? "null" : target.GetType().FullName)), ex); + } + } + + /// + /// Gets the value. + /// + /// The target to get the value from. + /// The value. + public object GetValue(object target) + { + try + { + if (target == null) + throw new ArgumentNullException("target"); + + switch (m_member.MemberType) + { + case MemberTypes.Field: + return ((FieldInfo)m_member).GetValue(target).ToString(); + case MemberTypes.Property: + return ((PropertyInfo)m_member).GetValue(target, null).ToString(); + default: + throw new ArgumentException(string.Format("MemberInfo '{0}' must be of type FieldInfo or PropertyInfo", CultureInfo.InvariantCulture, m_member.Name, "member")); + } + } + catch (Exception ex) + { + throw new JsonSerializationException(string.Format("Error getting value to '{0}' on '{1}'.", CultureInfo.InvariantCulture, m_member.Name, (target == null ? "null" : target.GetType().FullName)), ex); + } + } + } + } +} + diff --git a/Duplicati/Server/Duplicati.Server.Serialization/Serializer.cs b/Duplicati/Server/Duplicati.Server.Serialization/Serializer.cs new file mode 100644 index 000000000..9bdbfaa06 --- /dev/null +++ b/Duplicati/Server/Duplicati.Server.Serialization/Serializer.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Newtonsoft.Json; + +namespace Duplicati.Server.Serialization +{ + public class Serializer + { + private JsonSerializerSettings m_jsonSettings; + private Formatting m_jsonFormatting = Formatting.Indented; + + public Serializer() + { + m_jsonSettings = new JsonSerializerSettings(); + m_jsonSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; + m_jsonSettings.ContractResolver = new JsonSerializer(); + m_jsonSettings.Converters = new JsonConverter[]{ + new SerializableStatusCreator(), + new ProgressEventDataCreator() + }.ToList(); + } + + public void SerializeJson(System.IO.StreamWriter sw, object o) + { + Newtonsoft.Json.JsonSerializer jsonSerializer = Newtonsoft.Json.JsonSerializer.Create(m_jsonSettings); + using (var jsonWriter = new JsonTextWriter(sw)) + { + jsonWriter.Formatting = m_jsonFormatting; + jsonSerializer.Serialize(jsonWriter, o); + jsonWriter.Flush(); + } + } + + public T Deserialize(System.IO.StreamReader sr) + { + Newtonsoft.Json.JsonSerializer jsonSerializer = Newtonsoft.Json.JsonSerializer.Create(m_jsonSettings); + using (var jsonReader = new JsonTextReader(sr)) + { + jsonReader.Culture = System.Globalization.CultureInfo.InvariantCulture; + return jsonSerializer.Deserialize(jsonReader); + } + } + } +} diff --git a/Duplicati/Server/Duplicati.Server.csproj b/Duplicati/Server/Duplicati.Server.csproj index 510ed3d99..4a3c23c44 100644 --- a/Duplicati/Server/Duplicati.Server.csproj +++ b/Duplicati/Server/Duplicati.Server.csproj @@ -1,4 +1,4 @@ - + Debug @@ -54,6 +54,12 @@ true 4 + + true + + + Duplicati.snk + ..\..\thirdparty\HttpServer\HttpServer.dll @@ -64,9 +70,6 @@ ..\..\thirdparty\LightDataModel\LightDatamodel.dll - - ..\..\thirdparty\LitJSON\LitJson.dll - @@ -83,7 +86,6 @@ - @@ -122,9 +124,11 @@ + + @@ -174,10 +178,6 @@ {CCD76347-7DC7-4B42-B7E1-E500E624CAC3} Duplicati.Library.Backend.SkyDrive - - {33FD1D24-C28F-4C71-933F-98F1586EA76C} - Duplicati.Server.Serialization - {1BFAE226-8364-4086-825C-BB83F6F3EE4C} Duplicati.Library.Backend.CloudFiles @@ -242,6 +242,10 @@ {4D012CB1-4B92-47F4-89B7-BF80A73A2E99} Duplicati.License + + {33FD1D24-C28F-4C71-933F-98F1586EA76C} + Duplicati.Server.Serialization + diff --git a/Duplicati/Server/Duplicati.snk b/Duplicati/Server/Duplicati.snk new file mode 100644 index 000000000..e0c1e2dd8 Binary files /dev/null and b/Duplicati/Server/Duplicati.snk differ diff --git a/Duplicati/Server/DuplicatiRunner.cs b/Duplicati/Server/DuplicatiRunner.cs index 383bb8cf4..b637fb349 100644 --- a/Duplicati/Server/DuplicatiRunner.cs +++ b/Duplicati/Server/DuplicatiRunner.cs @@ -21,7 +21,8 @@ using System; using System.Collections.Generic; using System.Text; using Duplicati.Datamodel; -using Duplicati.Library.Main; +//using Duplicati.Library.Main; +using Duplicati.Server.Serialization; namespace Duplicati.Server { @@ -30,31 +31,16 @@ namespace Duplicati.Server /// public class DuplicatiRunner : Duplicati.Library.Main.LiveControl.ILiveControl { - public enum RunnerState + public class ProgressEventData : IProgressEventData { - Started, - Suspended, - Running, - Stopped, + public DuplicatiOperation Operation { get; set; } + public DuplicatiOperationMode Mode { get; set; } + public string Message { get; set; } + public string SubMessage { get; set; } + public int Progress { get; set; } + public int SubProgress { get; set; } } - public enum RunnerResult - { - OK, - Partial, - Warning, - Error - } - - public enum CloseReason - { - None, - ApplicationExitCall, - TaskManagerClosing, - WindowsShutDown, - UserClosing - } - public delegate void ResultEventDelegate(RunnerResult result, string parsedMessage, string message); public event ResultEventDelegate ResultEvent; @@ -64,18 +50,25 @@ namespace Duplicati.Server private const int PERCENT_PR_EXTRA_OPERATION = 2; private int m_extraOperations = 0; - private DuplicatiOperation m_lastPGOperation; - private DuplicatiOperationMode m_lastPGMode; - private int m_lastPGProgress; - private int m_lastPGSubprogress; - private string m_lastPGmessage; - private string m_lastPGSubmessage; + private ProgressEventData m_lastEvent = new ProgressEventData(); private object m_lock = new object(); private CloseReason m_stopReason = CloseReason.None; private Library.Main.LiveControl.ILiveControl m_currentBackupControlInterface; private bool m_isAborted = false; + private RunnerState m_currentRunnerState = RunnerState.Suspended; + + public DuplicatiRunner() + { + ProgressEvent += new ProgressEventDelegate(DuplicatiRunner_ProgressEvent); + } + + void DuplicatiRunner_ProgressEvent(DuplicatiOperation operation, RunnerState state, string message, string submessage, int progress, int subprogress) + { + m_currentRunnerState = state; + } + public void ExecuteTask(IDuplicityTask task) { Dictionary options = new Dictionary(); @@ -92,7 +85,7 @@ namespace Duplicati.Server try { //TODO: Its a bit dirty to set the options after creating the instance - using (Interface i = new Interface(destination, options)) + using (Duplicati.Library.Main.Interface i = new Duplicati.Library.Main.Interface(destination, options)) { lock (m_lock) { @@ -101,8 +94,8 @@ namespace Duplicati.Server } SetupControlInterface(); - - i.OperationProgress += new OperationProgressEvent(Duplicati_OperationProgress); + + i.OperationProgress += new Duplicati.Library.Main.OperationProgressEvent(Duplicati_OperationProgress); switch (task.TaskType) { @@ -184,10 +177,10 @@ namespace Duplicati.Server case DuplicityTaskType.ListBackups: List res = new List(); - foreach (ManifestEntry be in i.GetBackupSets()) + foreach (Duplicati.Library.Main.ManifestEntry be in i.GetBackupSets()) { res.Add(be.Time.ToString()); - foreach (ManifestEntry bei in be.Incrementals) + foreach (Duplicati.Library.Main.ManifestEntry bei in be.Incrementals) res.Add(bei.Time.ToString()); } @@ -309,10 +302,10 @@ namespace Duplicati.Server { if (task.Schedule.Task.KeepFull > 0) { - m_lastPGProgress = 100; - m_lastPGmessage = Strings.DuplicatiRunner.CleaningUpMessage; - m_lastPGSubmessage = ""; - m_lastPGSubprogress = -1; + m_lastEvent.Progress = 100; + m_lastEvent.Message = Strings.DuplicatiRunner.CleaningUpMessage; + m_lastEvent.SubMessage = ""; + m_lastEvent.SubProgress = -1; ReinvokeLastProgressEvent(); m_extraOperations--; @@ -324,10 +317,10 @@ namespace Duplicati.Server if (!string.IsNullOrEmpty(task.Schedule.Task.KeepTime)) { - m_lastPGProgress = 100; - m_lastPGmessage = Strings.DuplicatiRunner.CleaningUpMessage; - m_lastPGSubmessage = ""; - m_lastPGSubprogress = -1; + m_lastEvent.Progress = 100; + m_lastEvent.Message = Strings.DuplicatiRunner.CleaningUpMessage; + m_lastEvent.SubMessage = ""; + m_lastEvent.SubProgress = -1; ReinvokeLastProgressEvent(); m_extraOperations--; @@ -377,18 +370,23 @@ namespace Duplicati.Server task.Schedule.ScheduledRunCompleted(); //Register as completed if not aborted } - void Duplicati_OperationProgress(Interface caller, DuplicatiOperation operation, DuplicatiOperationMode specificmode, int progress, int subprogress, string message, string submessage) + void Duplicati_OperationProgress(Duplicati.Library.Main.Interface caller, Duplicati.Library.Main.DuplicatiOperation operation, Duplicati.Library.Main.DuplicatiOperationMode specificmode, int progress, int subprogress, string message, string submessage) { - m_lastPGOperation = operation; - m_lastPGMode = specificmode; - m_lastPGProgress = progress; - m_lastPGSubprogress = subprogress; - m_lastPGmessage = message; - m_lastPGSubmessage = submessage; + Duplicati_OperationProgress(caller, EnumConverter.Convert(operation), EnumConverter.Convert(specificmode), progress, subprogress, message, submessage); + } + + void Duplicati_OperationProgress(Duplicati.Library.Main.Interface caller, DuplicatiOperation operation, DuplicatiOperationMode specificmode, int progress, int subprogress, string message, string submessage) + { + m_lastEvent.Operation = operation; + m_lastEvent.Mode = specificmode; + m_lastEvent.Progress = progress; + m_lastEvent.SubProgress = subprogress; + m_lastEvent.Message = message; + m_lastEvent.SubMessage = submessage; //If there are extra operations, reserve some space for it by reducing the displayed progress if (m_extraOperations > 0 && progress > 0) - progress = (int)((m_lastPGProgress / 100.0) * (100 - (m_extraOperations * PERCENT_PR_EXTRA_OPERATION))); + progress = (int)((m_lastEvent.Progress / 100.0) * (100 - (m_extraOperations * PERCENT_PR_EXTRA_OPERATION))); if (ProgressEvent != null) try { ProgressEvent(operation, RunnerState.Running, message, submessage, progress, subprogress); } @@ -397,10 +395,9 @@ namespace Duplicati.Server public void ReinvokeLastProgressEvent() { - Duplicati_OperationProgress(null, m_lastPGOperation, m_lastPGMode, m_lastPGProgress, m_lastPGSubprogress, m_lastPGmessage, m_lastPGSubmessage ); + Duplicati_OperationProgress(null, m_lastEvent.Operation, m_lastEvent.Mode, m_lastEvent.Progress, m_lastEvent.SubProgress, m_lastEvent.Message, m_lastEvent.SubMessage ); } - private void PerformBackup(Schedule schedule, bool forceFull, string fullAfter) { if (forceFull) @@ -425,7 +422,7 @@ namespace Duplicati.Server return task.Backups; } - public List ListBackupEntries(Schedule schedule) + public List ListBackupEntries(Schedule schedule) { ListBackupEntriesTask task = new ListBackupEntriesTask(schedule); ExecuteTask(task); @@ -527,6 +524,9 @@ namespace Duplicati.Server m_currentBackupControlInterface.Resume(); } + public RunnerState CurrentState { get { return m_currentRunnerState; } } + public ProgressEventData LastEvent { get { return m_lastEvent; } } + public void Stop() { Stop(CloseReason.None); diff --git a/Duplicati/Server/LiveControls.cs b/Duplicati/Server/LiveControls.cs index d43ad2f5a..62636ca59 100644 --- a/Duplicati/Server/LiveControls.cs +++ b/Duplicati/Server/LiveControls.cs @@ -240,5 +240,21 @@ namespace Duplicati.Server } } } + + /// + /// Suspends the backups for a given period + /// + /// The duration to wait + public void Pause(TimeSpan timeout) + { + lock (m_lock) + { + if (m_state == LiveControlState.Running) + { + Pause(); + m_waitTimer.Change((long)timeout.TotalMilliseconds, System.Threading.Timeout.Infinite); + } + } + } } } diff --git a/Duplicati/Server/Program.cs b/Duplicati/Server/Program.cs index 59d29a83f..4689b49d8 100644 --- a/Duplicati/Server/Program.cs +++ b/Duplicati/Server/Program.cs @@ -83,17 +83,12 @@ namespace Duplicati.Server /// public static WebServer WebServer; - /// - /// The queue for handling events - /// - public static EventQueue Events; - /// /// The main entry point for the application. /// Commandline arguments /// [STAThread] - static void Main(string[] args) + public static void Main(string[] args) { //If we are on Windows, append the bundled "win-tools" programs to the search path //We add it last, to allow the user to override with other versions @@ -262,28 +257,25 @@ namespace Duplicati.Server ApplicationExitEvent = new System.Threading.ManualResetEvent(false); - Events = new EventQueue(); - LiveControl = new LiveControls(new Duplicati.Datamodel.ApplicationSettings(DataConnection)); LiveControl.StateChanged += new EventHandler(LiveControl_StateChanged); LiveControl.ThreadPriorityChanged += new EventHandler(LiveControl_ThreadPriorityChanged); LiveControl.ThrottleSpeedChanged += new EventHandler(LiveControl_ThrottleSpeedChanged); - Runner = new DuplicatiRunner(); WorkThread = new Duplicati.Library.Utility.WorkerThread(new Duplicati.Library.Utility.WorkerThread.ProcessItemDelegate(Runner.ExecuteTask), LiveControl.State == LiveControls.LiveControlState.Paused); Scheduler = new Scheduler(DataConnection, WorkThread, MainLock); - WorkThread.StartingWork += new EventHandler(Events.WorkThread_StartingWork); + /*WorkThread.StartingWork += new EventHandler(Events.WorkThread_StartingWork); WorkThread.CompletedWork += new EventHandler(Events.WorkThread_CompletedWork); WorkThread.WorkQueueChanged += new EventHandler(Events.WorkThread_WorkQueueChanged); Scheduler.NewSchedule += new EventHandler(Events.Scheduler_NewSchedule); Runner.ProgressEvent += new DuplicatiRunner.ProgressEventDelegate(Events.Runner_DuplicatiProgress); DataConnection.AfterDataConnection += new System.Data.LightDatamodel.DataConnectionEventHandler(Events.DataConnection_AfterDataConnection); - + LiveControl.StateChanged += new EventHandler(Events.LiveControl_StateChanged); LiveControl.ThreadPriorityChanged += new EventHandler(Events.LiveControl_ThreadPriorityChanged); - LiveControl.ThrottleSpeedChanged += new EventHandler(Events.LiveControl_ThrottleSpeedChanged); + LiveControl.ThrottleSpeedChanged += new EventHandler(Events.LiveControl_ThrottleSpeedChanged);*/ Program.WebServer = new Server.WebServer(8080); diff --git a/Duplicati/Server/SerializableStatus.cs b/Duplicati/Server/SerializableStatus.cs new file mode 100644 index 000000000..020a6011f --- /dev/null +++ b/Duplicati/Server/SerializableStatus.cs @@ -0,0 +1,66 @@ +#region "Disclaimer / License" +// Copyright (C) 2011, Kenneth Skovhede + +// http://www.hexad.dk, opensource@hexad.dk +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#endregion +using System; +using System.Linq; +using System.Collections.Generic; +using Duplicati.Server.Serialization; + +namespace Duplicati.Server +{ + /// + /// This class collects all reportable status properties into a single class that can be exported as JSON + /// + public class SerializableStatus : ISerializableStatus + { + public LiveControlState ProgramState + { + get { return EnumConverter.Convert(Program.LiveControl.State); } + } + + public RunnerState ActiveBackupState + { + get { return Program.Runner.CurrentState; } + } + + public long ActiveScheduleId + { + get + { + IDuplicityTask t = Program.WorkThread.CurrentTask; + if (t == null || t.Schedule == null) + return -1; + else + return t.Schedule.ID; + + } + } + + public IList SchedulerQueueIds + { + get { return Program.Scheduler.Schedule.Select(x => x.ID).ToList(); } + } + + public IProgressEventData RunningBackupStatus + { + get { return Program.Runner.LastEvent; } + } + } +} + diff --git a/Duplicati/Server/WebServer.cs b/Duplicati/Server/WebServer.cs index 825242fa8..bdc1ffa6e 100644 --- a/Duplicati/Server/WebServer.cs +++ b/Duplicati/Server/WebServer.cs @@ -4,13 +4,18 @@ using System.Linq; using System.Text; using HttpServer.MVC; using HttpServer.HttpModules; +using System.IO; +using Duplicati.Server.Serialization; namespace Duplicati.Server { public class WebServer { + /// + /// The single webserver instance + /// private HttpServer.HttpServer m_server; - + public WebServer(int port) { m_server = new HttpServer.HttpServer(); @@ -27,115 +32,258 @@ namespace Duplicati.Server private class BodyWriter : System.IO.StreamWriter, IDisposable { private HttpServer.IHttpResponse m_resp; + + // We override the format provider so all JSON output uses US format + public override IFormatProvider FormatProvider + { + get { return System.Globalization.CultureInfo.InvariantCulture; } + } + public BodyWriter(HttpServer.IHttpResponse resp) - : base(resp.Body, resp.Encoding) + : base(resp.Body, resp.Encoding) { m_resp = resp; } - protected override void Dispose(bool disposing) + protected override void Dispose (bool disposing) { - base.Flush(); - m_resp.ContentLength = base.BaseStream.Length; - m_resp.Send(); - + if (!m_resp.HeadersSent) + { + base.Flush(); + m_resp.ContentLength = base.BaseStream.Length; + m_resp.Send(); + } base.Dispose(disposing); } } private class DynamicHandler : HttpModule { - private delegate void ProcessSub(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session); - + private delegate void ProcessSub(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session, BodyWriter writer); + private Server.Serialization.Serializer m_serializer; private readonly Dictionary SUPPORTED_METHODS; public DynamicHandler() { + m_serializer = new Serializer(); SUPPORTED_METHODS = new Dictionary(System.StringComparer.InvariantCultureIgnoreCase); - + + //Make a list of all supported actions + SUPPORTED_METHODS.Add("supported-actions", ListSupportedActions); SUPPORTED_METHODS.Add("list-schedules", ListSchedules); SUPPORTED_METHODS.Add("get-current-state", GetCurrentState); + SUPPORTED_METHODS.Add("list-application-settings", ListApplicationSettings); + SUPPORTED_METHODS.Add("list-installed-backends", GetInstalledBackends); + SUPPORTED_METHODS.Add("list-installed-encryption-modules", ListInstalledEncryptionModules); + SUPPORTED_METHODS.Add("list-installed-compression-modules", ListInstalledCompressionModules); + SUPPORTED_METHODS.Add("list-installed-generic-modules", ListInstalledGenericModules); + SUPPORTED_METHODS.Add("list-options", ListCoreOptions); + SUPPORTED_METHODS.Add("list-recent-completed", ListRecentCompleted); + SUPPORTED_METHODS.Add("get-recent-log-details", GetLogBlob); + SUPPORTED_METHODS.Add("send-command", SendCommand); } - - public override bool Process(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session) + public override bool Process (HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session) { + //We use the fake entry point /control.cgi to listen for requests + //This ensures that the rest of the webserver can just serve plain files if (!request.Uri.AbsolutePath.Equals("/control.cgi", StringComparison.InvariantCultureIgnoreCase)) return false; HttpServer.HttpInput input = request.Method.ToUpper() == "POST" ? request.Form : request.QueryString; string action = input["action"].Value ?? ""; - + + //Lookup the actual handler method ProcessSub method; SUPPORTED_METHODS.TryGetValue(action, out method); - if (method == null) - { + if (method == null) { response.Status = System.Net.HttpStatusCode.NotImplemented; response.Reason = "Unsupported action: " + (action == null ? "" : ""); response.Send(); - } - else - { + } else { //Default setup response.Status = System.Net.HttpStatusCode.OK; response.Reason = "OK"; - //response.ContentType = "text/json"; +#if DEBUG response.ContentType = "text/plain"; - - method(request, response, session); +#else + response.ContentType = "text/json"; +#endif + using (BodyWriter bw = new BodyWriter(response)) + { + try + { + method(request, response, session, bw); + } + catch (Exception ex) + { + if (!response.HeadersSent) + { + response.Status = System.Net.HttpStatusCode.InternalServerError; + response.Reason = ex.Message; + response.ContentType = "text/plain"; + bw.WriteLine("Internal error"); +#if DEBUG + bw.Write("Stacktrace: " + ex.ToString()); +#endif + bw.Flush(); + } + } + } } return true; } - private void ListSchedules(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session) + private void ReportError(HttpServer.IHttpResponse response, BodyWriter bw, string message) { - using (var b = new BodyWriter(response)) + response.Status = System.Net.HttpStatusCode.InternalServerError; + response.Reason = message; + + OutputObject(bw, new { Error = message }); + } + + private void OutputObject (BodyWriter b, object o) + { + m_serializer.SerializeJson(b, o); + } + + private void ListSupportedActions(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session, BodyWriter bw) + { + OutputObject(bw, new { Version = 1, Methods = SUPPORTED_METHODS.Keys }); + } + + private void ListSchedules (HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session, BodyWriter bw) + { + OutputObject(bw, Program.DataConnection.GetObjects()); + } + + private void GetCurrentState (HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session, BodyWriter bw) + { + OutputObject(bw, new SerializableStatus()); + } + + private void GetInstalledBackends(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session, BodyWriter bw) + { + OutputObject(bw, Duplicati.Library.DynamicLoader.BackendLoader.Backends); + } + + private void ListInstalledEncryptionModules(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session, BodyWriter bw) + { + OutputObject(bw, Duplicati.Library.DynamicLoader.EncryptionLoader.Modules); + } + + private void ListInstalledCompressionModules(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session, BodyWriter bw) + { + OutputObject(bw, Duplicati.Library.DynamicLoader.CompressionLoader.Modules); + } + + private void ListInstalledGenericModules(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session, BodyWriter bw) + { + OutputObject(bw, Duplicati.Library.DynamicLoader.GenericLoader.Modules); + } + + private void ListCoreOptions(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session, BodyWriter bw) + { + OutputObject(bw, new Duplicati.Library.Main.Options(new Dictionary()).SupportedCommands); + } + + private void ListRecentCompleted(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session, BodyWriter bw) + { + OutputObject(bw, Program.DataConnection.GetObjects("EndTime > ? AND SubAction LIKE ? ORDER BY EndTime DESC", Library.Utility.Timeparser.ParseTimeInterval(new Datamodel.ApplicationSettings(Program.DataConnection).RecentBackupDuration, DateTime.Now, true), "Primary")); + } + + private void GetLogBlob(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session, BodyWriter bw) + { + HttpServer.HttpInput input = request.Method.ToUpper() == "POST" ? request.Form : request.QueryString; + long id; + if (!long.TryParse(input["id"].Value, out id)) + ReportError(response, bw, "Invalid or missing log id"); + else { - LitJson.JsonWriter w = new LitJson.JsonWriter(b); - w.WriteArrayStart(); - - foreach (Datamodel.Schedule s in Program.DataConnection.GetObjects()) - { - w.WriteObjectStart(); - - w.WritePropertyName("name"); - w.Write(s.Name); - w.WritePropertyName("id"); - w.Write(s.ID); - - w.WriteObjectEnd(); - } - - w.WriteArrayEnd(); + Datamodel.LogBlob lb = Program.DataConnection.GetObject("LogId = ?", id); + OutputObject(bw, lb); } } - private void GetCurrentState(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session) + private void ListApplicationSettings(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session, BodyWriter bw) { - using (var b = new BodyWriter(response)) - { - LitJson.JsonWriter w = new LitJson.JsonWriter(b); - - w.WriteObjectStart(); - - w.WritePropertyName("eventid"); - w.Write(Program.Events.CurrentEventId); - - w.WritePropertyName("paused"); - w.Write(Program.LiveControl.State.ToString()); - - w.WritePropertyName("pause-timeout"); - w.Write(0); - - - - w.WriteObjectEnd(); - } + OutputObject(bw, new Datamodel.ApplicationSettings(Program.DataConnection)); } + private void SendCommand(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session, BodyWriter bw) + { + HttpServer.HttpInput input = request.Method.ToUpper() == "POST" ? request.Form : request.QueryString; + + string command = input["command"].Value ?? ""; + long id; + + switch (command.ToLowerInvariant()) + { + case "pause": + if (input.Contains("duration")) + { + TimeSpan ts; + try { ts = Library.Utility.Timeparser.ParseTimeSpan(input["duration"].Value); } + catch (Exception ex) + { + ReportError(response, bw, ex.Message); + return; + } + Program.LiveControl.Pause(ts); + } + else + { + Program.LiveControl.Pause(); + } + + break; + case "resume": + Program.LiveControl.Resume(); + break; + + case "stop": + if (!Program.Runner.IsStopRequested) + Program.Runner.Stop(CloseReason.UserClosing); + break; + + case "abort": + if (!Program.Runner.IsStopRequested) + { + Program.Runner.Stop(CloseReason.UserClosing); + Program.Runner.Stop(CloseReason.UserClosing); + } + break; + + case "run": + case "run-backup": + { + Datamodel.Schedule schedule = null; + if (long.TryParse(input["id"].Value, out id)) + schedule = Program.DataConnection.GetObjectById(id); + + if (schedule == null) + { + ReportError(response, bw, string.Format("No backup found for id: {0}", input["id"].Value)); + return; + } + + if (Library.Utility.Utility.ParseBoolOption(input["full"].ToDictionary(x => x.Name, x => x.Value), "full")) + Program.WorkThread.AddTask(new FullBackupTask(schedule)); + else + Program.WorkThread.AddTask(new IncrementalBackupTask(schedule)); + } + break; + + default: + ReportError(response, bw, string.Format("Unsupported command {0}", command)); + break; + } + + OutputObject(bw, new { Status = "OK" }); + } } } } diff --git a/Duplicati/Server/app.config b/Duplicati/Server/app.config index a7d04fa82..02451de7f 100644 --- a/Duplicati/Server/app.config +++ b/Duplicati/Server/app.config @@ -1,3 +1,7 @@ - + + + + +