///
/// Copyright © 2003-2008 JetBrains s.r.o.
/// You may distribute under the terms of the GNU General Public License, as published by the Free Software Foundation, version 2 (see License.txt in the repository root folder).
///
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Reflection;
using System.Text;
using System.Windows.Forms;
using EMAPILib;
using JetBrains.Omea.Base;
using JetBrains.Omea.Diagnostics;
using JetBrains.Omea.GUIControls;
using JetBrains.Omea.OpenAPI;
using JetBrains.Omea.ResourceTools;
namespace JetBrains.Omea.OutlookPlugin
{
internal class MailBodyView : MessageDisplayPane
{
private const string _WaitMessage = "
" +
"Loading message body...";
private const string _NoPreviewTemplate = "No preview text available...";
private const string _Pattern1 = "%%1%%";
private const string _IniSection = "Outlook";
private const string _StylePath = "OutlookPlugin.Styles.AttachmentStyle.txt";
private const string _ScriptPath = "OutlookPlugin.Styles.ExpandScript.txt";
private const string _AttachIconFileName = "OutlookPlugin.Icons.attachment.png";
private const string _LargeImageIndicatorFileName = "OutlookPlugin.Icons.zoom.png";
// private const int _SmallFrameSize = 40;
// private const int _LargeFrameSize = 80;
private System.ComponentModel.Container _components = null;
///
/// A Web browser security context that is to be applied when displaying email
/// messages with the highest security, prohibiting downloading external images.
/// Embedded images are to be displayed by default.
///
private readonly WebSecurityContext _ctxRestrictedWoImages;
///
/// A Web browser security context that is to be applied when displaying email
/// messages with the nearly-highest security, showing all the external content,
/// but still prohibiting most actions that may compromise the security.
///
private readonly WebSecurityContext _ctxRestrictedWithImages;
private Panel _panel1;
private JetLinkLabel _linkShowPictures;
private Panel _panel2;
private JetLinkLabel _linkReceiveAttachedResources;
private bool _disposed;
private int _lastResourceId;
private IResource _resource;
private static string _font;
private static int _fontSize;
private static string _expandScript, _attachmentStyle;
private static string _largeImageIndicatorPath;
// This is a background of the frames for displaying the application-
// dependendent shell icons.
private static readonly Brush _backBrush = new SolidBrush(Color.FromArgb(0xEB, 0xEB, 0xEB));
///
/// Holds words that should be highlighted so that we could apply the highlighting when the mail body gets loaded at last.
///
private WordPtr[] _wordsToHighlight;
public MailBodyView()
{
// This call is required by the Windows.Forms Form Designer.
InitializeComponent();
_panel2.Visible = false;
_panel1.Visible = false;
// Initialize the contexts
// • Without images — work offline, show pictures that come from the file system of browser's cache only
_ctxRestrictedWoImages = WebSecurityContext.Restricted;
_ctxRestrictedWoImages.WorkOffline = true;
_ctxRestrictedWoImages.ShowPictures = Core.SettingStore.ReadBool( "General", "MailShowCachedPictures", false );
// • With images — work online, show pictures that come from the file system or are downloaded from the Internet
_ctxRestrictedWithImages = WebSecurityContext.Restricted;
_ctxRestrictedWithImages.WorkOffline = false;
_ctxRestrictedWithImages.ShowPictures = true;
ReadMailFontAttributes();
Core.UIManager.AddOptionsChangesListener( "MS Outlook", "Outlook General", ReadMailFontAttributesHandler );
Core.UIManager.AddOptionsChangesListener( "Omea", "General", ReadMailFontAttributesHandler );
}
private static void ReadMailFontAttributesHandler( object sender, EventArgs args )
{
ReadMailFontAttributes();
Core.ResourceBrowser.RedisplaySelectedResource();
}
private static void ReadMailFontAttributes()
{
// Initialize font from local settings or from the Core.UIManager.
_font = Core.UIManager.DefaultFontFace;
_fontSize = (int)Core.UIManager.DefaultFontSize;
bool overriden = Core.SettingStore.ReadBool( _IniSection, "MailFontOverride", false );
if( overriden )
{
_font = Core.SettingStore.ReadString( _IniSection, "MailFont", Core.UIManager.DefaultFontFace );
_fontSize = Core.SettingStore.ReadInt( _IniSection, "MailFontSize", (int)Core.UIManager.DefaultFontSize );
}
}
private void CheckDisposed()
{
if ( _disposed )
{
throw new ObjectDisposedException( "MailBodyView was disposed" );
}
}
protected override void Dispose( bool disposing )
{
if ( !_disposed )
{
if( disposing )
{
if(_components != null)
{
_components.Dispose();
}
}
base.Dispose( disposing );
}
_disposed = true;
}
#region Component Designer generated code
///
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
///
private void InitializeComponent()
{
this._linkReceiveAttachedResources = new JetLinkLabel();
this._linkShowPictures = new JetLinkLabel();
this._panel1 = new Panel();
this._panel2 = new Panel();
this.SuspendLayout();
//
// label1
//
this._linkReceiveAttachedResources.BackColor = SystemColors.Info;
this._linkReceiveAttachedResources.Dock = System.Windows.Forms.DockStyle.Top;
this._linkReceiveAttachedResources.Font = new System.Drawing.Font("Tahoma", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(204)));
this._linkReceiveAttachedResources.Location = new System.Drawing.Point(0, 24);
this._linkReceiveAttachedResources.Name = "_linkReceiveAttachedResources";
this._linkReceiveAttachedResources.Size = new System.Drawing.Size(560, 24);
this._linkReceiveAttachedResources.TabIndex = 3;
this._linkReceiveAttachedResources.TabStop = true;
this._linkReceiveAttachedResources.Text = "Click to receive attached resources";
this._linkReceiveAttachedResources.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
this._linkReceiveAttachedResources.Click += new System.EventHandler(this.OnReceiveResources);
//
// _panel1
//
this._panel1.BackColor = SystemColors.Info;
this._panel1.BorderStyle = BorderStyle.FixedSingle;
this._panel1.Dock = System.Windows.Forms.DockStyle.Top;
this._panel1.Font = new System.Drawing.Font("Tahoma", 8F, System.Drawing.FontStyle.Underline, System.Drawing.GraphicsUnit.Point, ((System.Byte)(204)));
this._panel1.Location = new System.Drawing.Point(0, 0);
this._panel1.Name = "_panel1";
this._panel1.Size = new System.Drawing.Size(560, 24);
//
// _panel2
//
this._panel2.BackColor = SystemColors.Info;
this._panel2.BorderStyle = BorderStyle.FixedSingle;
this._panel2.Dock = System.Windows.Forms.DockStyle.Top;
this._panel2.Font = new System.Drawing.Font("Tahoma", 8F, System.Drawing.FontStyle.Underline, System.Drawing.GraphicsUnit.Point, ((System.Byte)(204)));
this._panel2.Location = new System.Drawing.Point(0, 0);
this._panel2.Name = "_panel2";
this._panel2.Size = new System.Drawing.Size(560, 24);
//
// linkLabel1
//
this._linkShowPictures.BackColor = SystemColors.Info;
this._linkShowPictures.Dock = System.Windows.Forms.DockStyle.Top;
this._linkShowPictures.Font = new System.Drawing.Font("Tahoma", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(204)));
this._linkShowPictures.Location = new System.Drawing.Point(0, 0);
this._linkShowPictures.Name = "_linkShowPictures";
this._linkShowPictures.Size = new System.Drawing.Size(560, 24);
this._linkShowPictures.TabIndex = 4;
this._linkShowPictures.TabStop = true;
this._linkShowPictures.Text = "Click to show pictures";
this._linkShowPictures.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
this._linkShowPictures.Click += new System.EventHandler(this.OnShowPictures);
//
// MailBodyView
//
this.Controls.Add(this._panel1);
this.Controls.Add(this._panel2);
_panel1.Controls.Add(this._linkShowPictures);
_panel2.Controls.Add(this._linkReceiveAttachedResources);
this.Name = "MailBodyView";
this.Size = new System.Drawing.Size(560, 408);
this.ResumeLayout(false);
}
#endregion
#region Event Handlers
private void OnReceiveResources(object sender, EventArgs e)
{
IResourceList attachments = _resource.GetLinksOfType( null, PROP.InternalAttachment );
foreach ( IResource attachment in attachments.ValidResources )
{
if ( attachment.HasProp( PROP.ResourceTransfer ) )
{
UnpackResourcesAction action = new UnpackResourcesAction();
action.Unpack( attachment );
break;
}
}
}
private void OnShowPictures(object sender, EventArgs e)
{
new ResourceProxy( _resource ).SetProp( PROP.ShowPictures, true );
_panel1.Visible = false;
DisplayResource( _resource );
}
#endregion Event Handlers
#region DisplayResource
private static string Script
{
get
{
if( _expandScript == null )
{
Assembly theAssm = Assembly.GetExecutingAssembly();
Stream strm = theAssm.GetManifestResourceStream( _ScriptPath );
_expandScript = Utils.StreamToString( strm );
}
return _expandScript;
}
}
private static string Style
{
get
{
if( _attachmentStyle == null )
{
Assembly theAssm = Assembly.GetExecutingAssembly();
Stream strm = theAssm.GetManifestResourceStream( _StylePath );
_attachmentStyle = Utils.StreamToString( strm );
// Parameterize style with the actual location of an icon which
// indicates resizeable images.
_attachmentStyle = _attachmentStyle.Replace( _Pattern1, LargeImageIndicatorPath );
}
return _attachmentStyle;
}
}
private static string LargeImageIndicatorPath
{
get
{
if( _largeImageIndicatorPath == null )
{
_largeImageIndicatorPath = Path.Combine( Path.GetTempPath(), _LargeImageIndicatorFileName );
Assembly theAssm = Assembly.GetExecutingAssembly();
Image img = Utils.TryGetEmbeddedResourceImageFromAssembly( theAssm, _LargeImageIndicatorFileName);
img.Save( _largeImageIndicatorPath, ImageFormat.Png );
}
return _largeImageIndicatorPath;
}
}
public override void DisplayResource(IResource res, WordPtr[] wordsToHighlight)
{
base.DisplayResource( res, wordsToHighlight );
_lastResourceId = res.Id;
CheckDisposed();
ShowHtml( _WaitMessage, WebSecurityContext.Restricted, null);
_wordsToHighlight = wordsToHighlight; // When the item gets loaded, have a chance to apply
_resource = res;
if ( res.Type == STR.Email || res.Type == STR.EmailFile )
{
IResource folder = _resource.GetLinkProp( PROP.MAPIFolder );
if ( folder != null )
{
new ResourceProxy( folder ).SetPropAsync( PROP.SelectedInFolder, _resource );
}
ShowSubject( res.GetStringProp( Core.Props.Subject ), wordsToHighlight );
ShowMessageItem( res, MailMessage.Get( res ) );
ShowTransferredResourcesPane( res );
}
}
private void ShowMessageItem( IResource res, MailMessage messageItem )
{
#region Preconditions
CheckDisposed();
Guard.NullArgument( messageItem, "messageItem" );
#endregion Preconditions
int loadingResourceId = _lastResourceId;
// this performs an asynchronous operation for loading the body;
// during this operation, the form may be disposed or may switch
// to a different message (#6012)
BodyType messageBodyType = messageItem.BodyType;
if ( _disposed || _lastResourceId != loadingResourceId )
return;
bool hidePictures = _panel1.Visible = !res.HasProp( PROP.ShowPictures ) &&
!Settings.ShowEmbedPics && messageItem.HasPictures;
int attchmCount = res.GetLinksOfType( null, PROP.Attachment ).Count;
WebSecurityContext context = ( attchmCount > 0 ) ? WebSecurityContext.Trusted :
( hidePictures ? _ctxRestrictedWoImages : _ctxRestrictedWithImages );
if ( messageBodyType == BodyType.HTML )
{
string body = Core.MessageFormatter.GetFormattedHtmlBody( res, messageItem.Body, ref _wordsToHighlight );
body = InlineAttachments( res, body );
body = ReplaceContentID( res, body );
ShowHtml( body, context, _wordsToHighlight );
_wordsToHighlight = null;
// Control whether we allow downloading pictures or not
}
else
if ( messageBodyType == BodyType.RTF )
{
ShowRtf( messageItem.Body, _wordsToHighlight );
InsertOLEObjects( res );
}
else
{
if ( !res.HasProp( PROP.NoFormat ) )
{
IResource origMsg = res.GetLinkProp( "Reply" );
string origBody = (origMsg != null) ? MailMessage.Get( origMsg ).Body : null;
// Apply formatting to the plaintext item to present it in a fancy way. Also, remap the offsets if needed
string body = Core.MessageFormatter.GetFormattedBody( res, messageItem.Body, origBody,
ref _wordsToHighlight, _font, _fontSize );
body = InlineAttachments( res, body );
ShowHtml( body, WebSecurityContext.Trusted, _wordsToHighlight );
_wordsToHighlight = null;
}
else
{
string body = Core.MessageFormatter.GetFormattedBody( res, messageItem.Body, null, ref _wordsToHighlight );
ShowHtml( body, WebSecurityContext.Trusted, _wordsToHighlight );
}
}
}
private static string InlineAttachments( IResource res, string body )
{
IResourceList attachments = res.GetLinksOfType( null, PROP.Attachment );
if( attachments.Count == 0 )
return body;
string suffix = string.Empty;
bool corrected = false;
foreach( IResource attachment in attachments.ValidResources )
{
if (!corrected)
{
int index = body.LastIndexOf( "