using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; using System.Threading; using System.Xml; using Microsoft.SharePoint; using Microsoft.SharePoint.Administration; using Microsoft.SharePoint.Utilities; using Microsoft.SharePoint.WebPartPages; using SPSolutions.SharePoint.Alerts; using Taloyhtio.CondoUpdate.Common; namespace CondoUpdate.AddICSFieldToCalendars { public class UpdaterImpl : ICondoUpdater { private const string ICS_FIELD_NAME = "ICS"; private const string ALERT_TEMPLATE_BODY_PROPERTY_NAME = "NotificationMessage"; public event EventHandler OnNotify; public void Update(object args) { string url = args as string; if (string.IsNullOrEmpty(url)) { this.warn("Url is empty"); return; } try { this.updateImpl(url); } catch(Exception x) { this.error("Error occured during updating of Condo '{0}':\n{1}\n{2}", url, x.Message, x.StackTrace); } } private void updateImpl(string url) { using (var s = new SPSite(url)) { using (var w = s.OpenWeb()) { using (var site = new SPSite(s.ID, SPUrlZone.Extranet)) { using (var web = site.OpenWeb(w.ID)) { if (!web.Exists) { this.warn("Web site '{0}' doesn't exist. It will be ignored", url); return; } Thread.CurrentThread.CurrentCulture = Thread.CurrentThread.CurrentUICulture = new CultureInfo((int) web.Language); this.checkWeb(web); } } } } } private void checkWeb(SPWeb web) { var lists = new List(); foreach (SPList l in web.Lists) { if (l.BaseTemplate == SPListTemplateType.Events) { lists.Add(l); } } lists.ForEach(l => { this.ensureField(l); this.ensureICSLink(l); }); foreach (SPWeb subWeb in web.Webs) { this.checkWeb(subWeb); } } private void ensureField(SPList l) { try { if (l.Fields.Cast().Any(f => f.Title == ICS_FIELD_NAME || f.InternalName == ICS_FIELD_NAME)) { return; } string fldName = l.Fields.Add(ICS_FIELD_NAME, SPFieldType.Calculated, false); var fld = l.Fields[fldName] as SPFieldCalculated; fld.Formula = string.Format("=\"{0}/_vti_bin/owssvr.dll?CS=109&Cmd=Display&List={1}&CacheControl=1&ID=\"&{2}&\"&Using=event.ics\"", l.ParentWeb.Url, l.ID, SPUtility.GetLocalizedString("$Resources:ID", "core", l.ParentWeb.Language)); fld.OutputType = SPFieldType.Text; fld.Update(); } catch (Exception x) { this.error("Error occured when try to add field to list '{0}': {1}\n{2}", l.DefaultViewUrl, x.Message, x.StackTrace); } } private void ensureICSLink(SPList l) { try { //var alertTemplate = l.AlertTemplate; var alert = getFirstListAlert(l); if (alert == null) { //log("There are no alerts in the list"); return; } // get alert template from this list var alertTemplate = alert.AlertTemplate; if (alertTemplate == null) { error("Alert's alert template is null (list '{0}')", l.DefaultViewUrl); return; } if (!isCustom(alertTemplate)) { error("Alert template '{0}' is not custom (list '{1}')", alertTemplate.DisplayName, l.DefaultViewUrl); return; } if (alertTemplate.Properties == null || !alertTemplate.Properties.ContainsKey(ALERT_TEMPLATE_BODY_PROPERTY_NAME)) { error("Alert template '{0}' doesn't have {1} property (list '{2}')", alertTemplate.DisplayName, ALERT_TEMPLATE_BODY_PROPERTY_NAME, l.DefaultViewUrl); return; } string body = alertTemplate.Properties[ALERT_TEMPLATE_BODY_PROPERTY_NAME] as string; if (string.IsNullOrEmpty(body)) { error("{1} property is empty (list '{1}')", ALERT_TEMPLATE_BODY_PROPERTY_NAME, l.DefaultViewUrl); return; } if (body.Contains("Using=event.ics")) { return; } int idx = body.IndexOf("<p>Lisätietoja osoitteesta"); if (idx < 0) { return; } string sub1 = body.Substring(0, idx); string sub2 = body.Substring(idx); string ics = "<p><a href=\"{WebAbsolutePublicUrl}/_vti_bin/owssvr.dll?CS=109&Cmd=Display&List={ListId}&CacheControl=1&ID={ID}&Using=event.ics\">Lataa kalenterikutsu (.ics)</a></p>"; alertTemplate.Properties[ALERT_TEMPLATE_BODY_PROPERTY_NAME] = sub1 + ics + sub2; alertTemplate.Update(); } catch (Exception x) { this.error("Error occured when try to update alert template for list '{0}': {1}\n{2}", l.DefaultViewUrl, x.Message, x.StackTrace); } } private static SPAlert getFirstListAlert(SPList list) { var web = list.ParentWeb; var alerts = web.Alerts.Cast(); return alerts.FirstOrDefault(a => a.ListID == list.ID); } // This is copy of Alert template's AlertTemplateManager.IsCustom property implementation private static bool isCustom(SPAlertTemplate t) { return (((t.Properties["Custom"] != null) && (t.Properties["Custom"] is string)) && (((string)t.Properties["Custom"]) == SPAlertTemplateUtil.CustomAlertTemplateIdentifier)); } private void info(string msg, params object[] args) { this.notify(LogLevel.Info, msg, args); } private void warn(string msg, params object[] args) { this.notify(LogLevel.Warn, msg, args); } private void error(string msg, params object[] args) { this.notify(LogLevel.Error, msg, args); } private void notify(LogLevel level, string msg, params object[] args) { this.notify(level, string.Format(msg, args)); } private void notify(LogLevel level, string msg) { if (this.OnNotify != null) { this.OnNotify(this, new LogEventArgs { LogLevel = level, Message = msg }); } } } }