diff --git a/RatingManagerPlugin/Properties/AssemblyInfo.cs b/RatingManagerPlugin/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..e82b572
--- /dev/null
+++ b/RatingManagerPlugin/Properties/AssemblyInfo.cs
@@ -0,0 +1,18 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Rating Manager Plugin")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("fe885520-e570-4524-943c-effc5bae1843")]
diff --git a/RatingManagerPlugin/RatingManager.cs b/RatingManagerPlugin/RatingManager.cs
new file mode 100644
index 0000000..6915839
--- /dev/null
+++ b/RatingManagerPlugin/RatingManager.cs
@@ -0,0 +1,414 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using ScrewTurn.Wiki.PluginFramework;
+using System.Text.RegularExpressions;
+using System.Reflection;
+using System.IO;
+
+namespace ScrewTurn.Wiki.Plugins.RatingManagerPlugin {
+
+ ///
+ /// A plugin for assigning a rating to pages.
+ ///
+ public class RatingManager : IFormatterProviderV30 {
+
+ const string defaultDirectoryName = "/__RatingManagerPlugin/";
+ const string cssFileName = "RatingManagerPluginCss.css";
+ const string jsFileName = "RatingManagerPluginJs.js";
+ const string starImageFileName = "RatingManagerPluginStarImage.gif";
+ const string ratingFileName = "RatingManagerPluginRatingFile.dat";
+
+ private IHostV30 _host;
+ private bool _enableLogging = true;
+ private static readonly ComponentInformation Info = new ComponentInformation("Rating Manager Plugin", "Threeplicate Srl", "3.0.2.538", "http://www.screwturn.eu", "http://www.screwturn.eu/Version/PluginPack/RatingManager2.txt");
+
+ private bool foundRatings = false;
+
+ private static readonly Regex VotesRegex = new Regex(@"{rating(\|(.+?))?}",
+ RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public RatingManager() {
+
+ }
+
+ ///
+ /// Specifies whether or not to execute Phase 1.
+ ///
+ public bool PerformPhase1 {
+ get { return false; }
+ }
+
+ ///
+ /// Specifies whether or not to execute Phase 2.
+ ///
+ public bool PerformPhase2 {
+ get { return false; }
+ }
+
+ ///
+ /// Specifies whether or not to execute Phase 3.
+ ///
+ public bool PerformPhase3 {
+ get { return true; }
+ }
+
+ ///
+ /// Gets the execution priority of the provider (0 lowest, 100 highest).
+ ///
+ public int ExecutionPriority {
+ get { return 50; }
+ }
+
+ ///
+ /// Performs a Formatting phase.
+ ///
+ /// The raw content to Format.
+ /// The Context information.
+ /// The Phase.
+ /// The Formatted content.
+ public string Format(string raw, ContextInformation context, FormattingPhase phase) {
+ // {rating}
+ // _backendpage not found -> ignored
+
+ StringBuilder buffer = new StringBuilder(raw);
+ try {
+ if(context.Context == FormattingContext.PageContent && context.Page != null) {
+ if(context.HttpContext.Request["vote"] != null) {
+ AddRating(context.Page.FullName, int.Parse(context.HttpContext.Request["vote"]));
+ System.Web.HttpCookie cookie = new System.Web.HttpCookie("RatingManagerPlugin_" + context.Page.FullName, context.HttpContext.Request["vote"]);
+ cookie.Expires = DateTime.Now.AddYears(10);
+ context.HttpContext.Response.Cookies.Add(cookie);
+ return "";
+ }
+ }
+ if(context.Page != null) {
+ ComputeRating(context, buffer, context.Page.FullName);
+ }
+ else {
+ return raw;
+ }
+ }
+ catch(Exception ex) {
+ LogWarning(string.Format("Exception occurred: {0}", ex.StackTrace));
+ }
+ if(foundRatings) {
+ buffer.Append(@"");
+ buffer.Append(@"");
+ foundRatings = false;
+ }
+ return buffer.ToString();
+ }
+
+ ///
+ /// Gets the rating of the plugin from the backendpage and display it to the user.
+ ///
+ /// The context.
+ /// The page content.
+ /// Full name of the page.
+ private void ComputeRating(ContextInformation context, StringBuilder buffer, string fullPageName) {
+ KeyValuePair block = FindAndRemoveFirstOccurrence(buffer);
+ int numRatings = 0;
+ while(block.Key != -1) {
+ foundRatings = true;
+ numRatings++;
+
+ string result = null;
+
+ if(block.Value.Groups[2].Value != "") {
+ int average = (int)Math.Round((decimal)GetCurrentAverage(block.Value.Groups[2].Value), 0, MidpointRounding.AwayFromZero);
+
+ result += @"";
+
+ result += @"";
+ }
+ else if(context.HttpContext.Request.Cookies.Get("RatingManagerPlugin_" + fullPageName) != null) {
+ int average = (int)Math.Round((decimal)GetCurrentAverage(fullPageName), 0, MidpointRounding.AwayFromZero);
+
+ result += @"";
+
+ result += @"";
+ }
+ else {
+ int average = (int)Math.Round((decimal)GetCurrentAverage(fullPageName), 0, MidpointRounding.AwayFromZero);
+
+ result += @"
+ ";
+
+ result += @"";
+
+ }
+
+ result += @"";
+
+ buffer.Insert(block.Key, result);
+
+ block = FindAndRemoveFirstOccurrence(buffer);
+ }
+ }
+
+
+ private float GetCurrentAverage(string fullPageName) {
+ float average = 0;
+ try {
+ IFilesStorageProviderV30 filesStorageProvider = GetDefaultFilesStorageProvider();
+
+ MemoryStream stream = new MemoryStream();
+ string fileContent = "";
+
+ if(FileExists(filesStorageProvider, defaultDirectoryName, ratingFileName)) {
+ filesStorageProvider.RetrieveFile(defaultDirectoryName + ratingFileName, stream, true);
+ stream.Seek(0, SeekOrigin.Begin);
+ fileContent = Encoding.UTF8.GetString(stream.ToArray());
+ }
+
+ string[] plugins = fileContent.Split(new String[] { "||" }, StringSplitOptions.RemoveEmptyEntries);
+
+ // If the plugin is found return the posizion in the plugins array
+ // otherwise return -1
+ int pluginIndex = SearchPlugin(plugins, fullPageName);
+ if(pluginIndex != -1) {
+ string[] pluginDetails = plugins[pluginIndex].Split(new string[] { "|" }, StringSplitOptions.RemoveEmptyEntries);
+ average = (float)int.Parse(pluginDetails[2]) / (float)100;
+ }
+ }
+ catch(Exception ex) {
+ LogWarning(String.Format("Exception occurred {0}", ex.StackTrace));
+ }
+ return average;
+ }
+
+
+ private void AddRating(string fullPageName, int rate) {
+ IFilesStorageProviderV30 filesStorageProvider = GetDefaultFilesStorageProvider();
+
+ MemoryStream stream = new MemoryStream();
+
+ if(FileExists(filesStorageProvider, defaultDirectoryName, ratingFileName)) {
+ filesStorageProvider.RetrieveFile(defaultDirectoryName + ratingFileName, stream, true);
+ stream.Seek(0, SeekOrigin.Begin);
+ }
+ string fileContent = Encoding.UTF8.GetString(stream.ToArray());
+
+ string[] plugins = fileContent.Split(new String[] { "||" }, StringSplitOptions.RemoveEmptyEntries);
+
+ StringBuilder sb = new StringBuilder();
+
+ // If the plugin is found return the posizion in the plugins array
+ // otherwise return -1
+ int pluginIndex = SearchPlugin(plugins, fullPageName);
+ if(pluginIndex != -1) {
+ int numRates = int.Parse(plugins[pluginIndex].Split(new string[] { "|" }, StringSplitOptions.RemoveEmptyEntries)[1]);
+ int average = int.Parse(plugins[pluginIndex].Split(new string[] { "|" }, StringSplitOptions.RemoveEmptyEntries)[2]);
+ int newAverage = ((average * numRates) + (rate * 100)) / (numRates + 1);
+ numRates++;
+ plugins[pluginIndex] = fullPageName + "|" + numRates + "|" + newAverage;
+ foreach(string plugin in plugins) {
+ sb.Append(plugin + "||");
+ }
+ }
+ else {
+ foreach(string plugin in plugins) {
+ sb.Append(plugin + "||");
+ }
+ sb.Append(fullPageName + "|1|" + (rate * 100));
+ }
+
+ stream = new MemoryStream(Encoding.UTF8.GetBytes(sb.ToString()));
+
+ filesStorageProvider.StoreFile(defaultDirectoryName + ratingFileName, stream, true);
+
+ //statisticsPage.Provider.ModifyPage(statisticsPage, statisticsPageContent.Title, statisticsPageContent.User, DateTime.Now, statisticsPageContent.Comment, sb.ToString(), statisticsPageContent.Keywords, statisticsPageContent.Description, SaveMode.Normal);
+ }
+
+ ///
+ /// Searches the plugin.
+ ///
+ /// The plugins array.
+ /// The current plugin.
+ ///
+ /// The position of the plugin in the array, otherwise -1
+ ///
+ private int SearchPlugin(string[] plugins, string currentPlugin) {
+ for(int i = 0; i < plugins.Length; i++) {
+ if(plugins[i].Split(new string[] { "|" }, StringSplitOptions.RemoveEmptyEntries)[0] == currentPlugin)
+ return i;
+ }
+ return -1;
+ }
+
+ ///
+ /// Finds the and remove first occurrence.
+ ///
+ /// The buffer.
+ /// The index->content data.
+ private KeyValuePair FindAndRemoveFirstOccurrence(StringBuilder buffer) {
+ Match match = VotesRegex.Match(buffer.ToString());
+
+ if(match.Success) {
+ buffer.Remove(match.Index, match.Length);
+ return new KeyValuePair(match.Index, match);
+ }
+
+ return new KeyValuePair(-1, null);
+ }
+
+ ///
+ /// Logs the warning.
+ ///
+ /// The message.
+ private void LogWarning(string message) {
+ if(_enableLogging) {
+ _host.LogEntry(message, LogEntryType.Warning, null, this);
+ }
+ }
+
+ ///
+ /// Prepares the title of an item for display (always during phase 3).
+ ///
+ /// The input title.
+ /// The context information.
+ /// The prepared title (no markup allowed).
+ public string PrepareTitle(string title, ContextInformation context) {
+ return title;
+ }
+
+ ///
+ /// Initializes the Storage Provider.
+ ///
+ /// The Host of the Component.
+ /// The Configuration data, if any.
+ /// If or are null.
+ /// If is not valid or is incorrect.
+ public void Init(IHostV30 host, string config) {
+ _host = host;
+
+ if(config != null) {
+ string[] configEntries = config.Split(new string[] { "\n" }, StringSplitOptions.RemoveEmptyEntries);
+ for(int i = 0; i < configEntries.Length; i++) {
+ string[] configEntryDetails = configEntries[i].Split(new string[] { "=" }, 2, StringSplitOptions.None);
+ switch(configEntryDetails[0].ToLowerInvariant()) {
+ case "logoptions":
+ if(configEntryDetails[1] == "nolog") {
+ _enableLogging = false;
+ }
+ else {
+ LogWarning(@"Unknown value in ""logOptions"" configuration string: " + configEntries[i] + "Supported values are: nolog.");
+ }
+ break;
+ default:
+ LogWarning("Unknown value in configuration string: " + configEntries[i]);
+ break;
+ }
+ }
+ }
+
+ IFilesStorageProviderV30 filesStorageProvider = GetDefaultFilesStorageProvider();
+
+ if(!DirectoryExists(filesStorageProvider, defaultDirectoryName)) {
+ filesStorageProvider.CreateDirectory("/", defaultDirectoryName.Trim('/'));
+ }
+ if(!FileExists(filesStorageProvider, defaultDirectoryName, cssFileName)) {
+ filesStorageProvider.StoreFile(defaultDirectoryName + cssFileName, Assembly.GetExecutingAssembly().GetManifestResourceStream("ScrewTurn.Wiki.Plugins.RatingManagerPlugin.Resources.jquery.rating.css"), true);
+ }
+ if(!FileExists(filesStorageProvider, defaultDirectoryName, jsFileName)) {
+ filesStorageProvider.StoreFile(defaultDirectoryName + jsFileName, Assembly.GetExecutingAssembly().GetManifestResourceStream("ScrewTurn.Wiki.Plugins.RatingManagerPlugin.Resources.jquery.rating.pack.js"), true);
+ }
+ if(!FileExists(filesStorageProvider, defaultDirectoryName, starImageFileName)) {
+ filesStorageProvider.StoreFile(defaultDirectoryName + starImageFileName, Assembly.GetExecutingAssembly().GetManifestResourceStream("ScrewTurn.Wiki.Plugins.RatingManagerPlugin.Resources.star.gif"), true);
+ }
+ }
+
+
+ private IFilesStorageProviderV30 GetDefaultFilesStorageProvider() {
+ string defaultFilesStorageProviderName = _host.GetSettingValue(SettingName.DefaultFilesStorageProvider);
+ return _host.GetFilesStorageProviders(true).First(p => p.GetType().FullName == defaultFilesStorageProviderName);
+ }
+
+ private bool DirectoryExists(IFilesStorageProviderV30 filesStorageProvider, string directoryName) {
+ string[] directoryList = filesStorageProvider.ListDirectories("/");
+ foreach(string dir in directoryList) {
+ if(dir == directoryName) return true;
+ }
+ return false;
+ }
+
+ private bool FileExists(IFilesStorageProviderV30 filesStorageProvider, string directory, string fileName) {
+ string[] filesList = filesStorageProvider.ListFiles(directory);
+ foreach(string file in filesList) {
+ if(file == directory + fileName) return true;
+ }
+ return false;
+ }
+
+ ///
+ /// Method invoked on shutdown.
+ ///
+ /// This method might not be invoked in some cases.
+ public void Shutdown() {
+ // Nothing to do
+ }
+
+ ///
+ /// Gets the Information about the Provider.
+ ///
+ public ComponentInformation Information {
+ get { return Info; }
+ }
+
+ ///
+ /// Gets a brief summary of the configuration string format, in HTML. Returns null if no configuration is needed.
+ ///
+ public string ConfigHelpHtml {
+ get { return "Specify logooptions=nolog for disabling warning log messages for exceptions."; }
+ }
+ }
+}
diff --git a/RatingManagerPlugin/RatingManagerPlugin.csproj b/RatingManagerPlugin/RatingManagerPlugin.csproj
new file mode 100644
index 0000000..6ffe906
--- /dev/null
+++ b/RatingManagerPlugin/RatingManagerPlugin.csproj
@@ -0,0 +1,72 @@
+
+
+
+ Debug
+ AnyCPU
+ 9.0.30729
+ 2.0
+ {B65C793F-62C4-4B81-95C4-3E4805E80411}
+ Library
+ Properties
+ ScrewTurn.Wiki.Plugins.RatingManagerPlugin
+ RatingManagerPlugin
+ v3.5
+ 512
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+ true
+
+
+ none
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+ true
+
+
+
+
+ 3.5
+
+
+
+
+
+ AssemblyVersion.cs
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {531A83D6-76F9-4014-91C5-295818E2D948}
+ PluginFramework
+
+
+
+
+
\ No newline at end of file
diff --git a/RatingManagerPlugin/Resources/jquery.rating.css b/RatingManagerPlugin/Resources/jquery.rating.css
new file mode 100644
index 0000000..9120ba4
--- /dev/null
+++ b/RatingManagerPlugin/Resources/jquery.rating.css
@@ -0,0 +1,36 @@
+.ui-rating .ui-rating-star, .ui-rating .ui-rating-cancel, .static-rating{
+ width:16px;
+ height:16px;
+ font-size:2px;
+ float:left;
+ text-decoration:none;
+ vertical-align:middle;
+ background-image:url('GetFile.aspx?file=/__RatingManagerPlugin/RatingManagerPluginStarImage.gif');
+ background-repeat:no-repeat;
+}
+.ui-rating a {
+ cursor: pointer;
+}
+.ui-rating-full {
+ background-position:left top;
+}
+
+.ui-rating-half {
+ background-position:left -16px;
+}
+
+.ui-rating-empty {
+ background-position:left -32px;
+}
+
+.ui-rating-cancel-empty {
+ background-position:left -64px;
+}
+
+.ui-rating-cancel-full {
+ background-position:left -80px;
+}
+
+.ui-rating-hover {
+ background-position:left -48px;
+}
diff --git a/RatingManagerPlugin/Resources/jquery.rating.pack.js b/RatingManagerPlugin/Resources/jquery.rating.pack.js
new file mode 100644
index 0000000..41b4c08
--- /dev/null
+++ b/RatingManagerPlugin/Resources/jquery.rating.pack.js
@@ -0,0 +1,4 @@
+// Chris Richards 2009
+// rating control for jQuery. version 1.06
+// http://zensoftware.org/
+(function($){$.fn.rating=function(e){var f={showCancel:true,cancelValue:null,startValue:null,disabled:false};$.extend(f,e);var g={hoverOver:function(a){var b=$(a.target);if(b.hasClass("ui-rating-cancel")){b.addClass("ui-rating-cancel-full")}else{b.prevAll().andSelf().not(".ui-rating-cancel").addClass("ui-rating-hover")}},hoverOut:function(a){var b=$(a.target);if(b.hasClass("ui-rating-cancel")){b.addClass("ui-rating-cancel-empty").removeClass("ui-rating-cancel-full")}else{b.prevAll().andSelf().not(".ui-rating-cancel").removeClass("ui-rating-hover")}},click:function(a){var b=$(a.target);var c=f.cancelValue;if(b.hasClass("ui-rating-cancel")){g.empty(b)}else{b.closest(".ui-rating-star").prevAll().andSelf().not(".ui-rating-cancel").attr("className","ui-rating-star ui-rating-full");b.closest(".ui-rating-star").nextAll().not(".ui-rating-cancel").attr("className","ui-rating-star ui-rating-empty");b.siblings(".ui-rating-cancel").attr("className","ui-rating-cancel ui-rating-cancel-empty");c=b.attr("value")}if(!a.data.hasChanged){$(a.data.selectBox).val(c).trigger("change")}},change:function(a){var b=$(this).val();g.setValue(b,a.data.container,a.data.selectBox)},setValue:function(a,b,c){var d={"target":null,"data":{}};d.target=$(".ui-rating-star[value="+a+"]",b);d.data.selectBox=c;d.data.hasChanged=true;g.click(d)},empty:function(a){a.attr("className","ui-rating-cancel ui-rating-cancel-empty").nextAll().attr("className","ui-rating-star ui-rating-empty")}};var h={createContainer:function(a){var b=$("").attr({title:a.title,className:"ui-rating"}).insertAfter(a);return b},createStar:function(a,b){$("").attr({className:"ui-rating-star ui-rating-empty",title:$(a).text(),value:a.value}).appendTo(b)},createCancel:function(a,b){$("").attr({className:"ui-rating-cancel ui-rating-cancel-empty",title:"Cancel"}).appendTo(b)}};return this.each(function(){if($(this).attr("type")!=="select-one"){return}var a=this;$(a).css("display","none");var b=$(a).attr("id");if(""===b){b="ui-rating-"+$.data(a);$(a).attr("id",b)}var c=h.createContainer(a);if(true!==f.disabled&&$(a).attr("disabled")!==true){$(c).bind("mouseover",g.hoverOver).bind("mouseout",g.hoverOut).bind("click",{"selectBox":a},g.click)}if(f.showCancel){h.createCancel(this,c)}$("option",a).each(function(){h.createStar(this,c)});if(0!==$("#"+b+" option[selected]").size()){g.setValue($(a).val(),c,a)}else{var d=null!==f.startValue?f.startValue:f.cancelValue;g.setValue(d,c,a);$(a).val(d)}$(this).bind("change",{"selectBox":a,"container":c},g.change)})}})(jQuery);
diff --git a/RatingManagerPlugin/Resources/star.gif b/RatingManagerPlugin/Resources/star.gif
new file mode 100644
index 0000000..0e5b813
Binary files /dev/null and b/RatingManagerPlugin/Resources/star.gif differ
diff --git a/ScrewTurnWiki.sln b/ScrewTurnWiki.sln
index 35b42d3..29f6c40 100644
--- a/ScrewTurnWiki.sln
+++ b/ScrewTurnWiki.sln
@@ -65,6 +65,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RssFeedDisplayPlugin", "Rss
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnfuddleTicketsPlugin", "UnfuddleTicketsPlugin\UnfuddleTicketsPlugin.csproj", "{62EC7498-D82C-40FD-B153-5FC2F2FA6D72}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RatingManagerPlugin", "RatingManagerPlugin\RatingManagerPlugin.csproj", "{B65C793F-62C4-4B81-95C4-3E4805E80411}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -155,22 +157,27 @@ Global
{62EC7498-D82C-40FD-B153-5FC2F2FA6D72}.Debug|Any CPU.Build.0 = Debug|Any CPU
{62EC7498-D82C-40FD-B153-5FC2F2FA6D72}.Release|Any CPU.ActiveCfg = Release|Any CPU
{62EC7498-D82C-40FD-B153-5FC2F2FA6D72}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B65C793F-62C4-4B81-95C4-3E4805E80411}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B65C793F-62C4-4B81-95C4-3E4805E80411}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B65C793F-62C4-4B81-95C4-3E4805E80411}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B65C793F-62C4-4B81-95C4-3E4805E80411}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
- {88212C14-10A0-4D46-8203-D48534465181} = {F6E9DB23-D200-4CCE-B42D-7CD1D20FC92D}
- {617D5D30-97F9-48B2-903D-29D4524492E8} = {F6E9DB23-D200-4CCE-B42D-7CD1D20FC92D}
{67590C3A-1A7C-4608-90CA-1C1632D2F643} = {F6E9DB23-D200-4CCE-B42D-7CD1D20FC92D}
{ECB488D9-C8E9-41E0-BE27-27F41F76F8A0} = {F6E9DB23-D200-4CCE-B42D-7CD1D20FC92D}
{F75DFFE1-A8CF-4CC2-B15F-3EC7EAADDCFC} = {F6E9DB23-D200-4CCE-B42D-7CD1D20FC92D}
+ {88212C14-10A0-4D46-8203-D48534465181} = {F6E9DB23-D200-4CCE-B42D-7CD1D20FC92D}
{C7169CA4-9893-4361-96A8-09F87FCF5E8C} = {F6E9DB23-D200-4CCE-B42D-7CD1D20FC92D}
+ {617D5D30-97F9-48B2-903D-29D4524492E8} = {F6E9DB23-D200-4CCE-B42D-7CD1D20FC92D}
{C2F2722A-0B44-4E98-965C-CC1AD1DA511C} = {F6E9DB23-D200-4CCE-B42D-7CD1D20FC92D}
{DEA4E4AA-7452-4598-8277-A7F5D6DE4985} = {F6E9DB23-D200-4CCE-B42D-7CD1D20FC92D}
{B7EE7C86-5031-40EB-B06C-DF5B3564BE17} = {F6E9DB23-D200-4CCE-B42D-7CD1D20FC92D}
{94DDE3D4-0595-405C-9EA6-358B74EC6BC5} = {F6E9DB23-D200-4CCE-B42D-7CD1D20FC92D}
{83363183-7B84-43BF-885F-C728A721140B} = {F6E9DB23-D200-4CCE-B42D-7CD1D20FC92D}
{62EC7498-D82C-40FD-B153-5FC2F2FA6D72} = {F6E9DB23-D200-4CCE-B42D-7CD1D20FC92D}
+ {B65C793F-62C4-4B81-95C4-3E4805E80411} = {F6E9DB23-D200-4CCE-B42D-7CD1D20FC92D}
EndGlobalSection
EndGlobal