source: trunk/Documentation/Developer/PluginHowTo/part2.tex @ 1156

Last change on this file since 1156 was 1145, checked in by Patrick Vacek, 12 years ago

PluginHowTo: further comprehensive revisions, i.e. grammar, formatting, labeling, clarity, etc.

File size: 61.9 KB
Line 
1\chapter{Plugin Implementation}
2\label{sec:PluginImplementation}
3In this chapter we provide step-by-step instructions for implementing your own CrypTool 2.0 plugin. The given instructions refer mostly to the usage of MS Visual C\# 2008 Express Edition, hence before starting you should have a copy of \textbf{Microsoft Visual Studio 2008} or \textbf{Microsoft Visual C\# 2008 Express Edition} installed on your computer. We will use the \textbf{Caesar cipher} (also known as the \textbf{shift cipher}) for our example implemenation.
4
5\section{Creating a new project}
6\label{sec:CreatingANewProject}
7
8To begin, open Visual Studio 2008 or C\# 2008 Express Edition, go to the menu bar and select ``File"~$\rightarrow$ ``New" $\rightarrow$ ``Project\ldots ". The following window will appear:
9
10\begin{figure}[h!]
11        \centering
12                \includegraphics[width=1.00\textwidth]{figures/vs_create_new_project.jpg}
13        \caption{Creating a new Visual Studio/C\# Express project.}
14        \label{fig:vs_create_new_project}
15\end{figure}
16
17If you are using Visual Studio 2008, select \textbf{``.NET-Framework 3.5"} as the target framework; the Express Edition will automatically choose the target framework. Then choose \textbf{``Class Library"} as the default template, as this will build the project as a DLL file. Give the project a unique and meaningful name (such as ``Caesar" in our case), and choose a location to save it to. (The Express Edition will ask for a save location later when you close your project or environment). Select the subdirectory ``CrypPlugins" from your SVN trunk as the location. Finally, confirm by pressing the ``OK" button. Note that creating a new project in this manner also creates a new solution into which the project is placed.
18
19\begin{figure}[h!]
20        \centering
21                \includegraphics[width=0.80\textwidth]{figures/save_solution_csharp_express.JPG}
22        \caption{The Microsoft C\# Express Edition Save Project dialog window.}
23        \label{fig:save_solution_csharp_express}
24\end{figure}
25
26At this point, your Visual Studio\slash C\# Express solution should look like this:
27
28\begin{figure}[h!]
29        \centering
30                \includegraphics[width=1.00\textwidth]{figures/solution_start_up.jpg}
31        \caption{A newly created solution and project.}
32        \label{fig:solution_start_up}
33\end{figure}
34\clearpage
35
36\section{Interface selection}
37\label{sec:InterfaceSelection}
38
39First we must add a reference to the CrypTool library, \textbf{\textit{CrypPluginBase.dll}}, where all the necessary CrypTool plugin interfaces are declared.
40
41\begin{figure}[h!]
42        \includegraphics{figures/add_reference.jpg}
43        \caption{Adding a new reference.}
44        \label{fig:add_reference}
45\end{figure}
46
47Right-click in the Solution Explorer on the ``Reference" item and choose ``Add Reference". A window like the following should appear:
48
49\begin{figure}[h!]
50        \centering
51                \includegraphics{figures/add_pluginbase_source.jpg}
52        \caption{Adding a reference to the PluginBase source code.}
53        \label{fig:add_pluginbase_source}
54\end{figure}
55\clearpage
56
57Select the project ``CrypPluginBase". If you do not have the ``CrypPluginBase" source code, it is also possible to add a reference the the binary DLL. In this case browse to the path where the library file \textit{CrypPluginBase.dll} is located, e.g.\ \textit{C:\textbackslash Documents and Settings\textbackslash $<$Username$>$\textbackslash My Documents\textbackslash Visual Studio 2008\textbackslash Projects\textbackslash CrypPluginBase\textbackslash bin\textbackslash Debug} and select the library by double clicking the file or pressing the ``OK" button. (You can also select the binary DLL located in the folder where \textit{CrypWin.exe} was placed when you downloaded CrypTool2.)
58
59\begin{figure}[h!]
60        \centering
61                \includegraphics{figures/browse_reference.jpg}
62        \caption{Browsing for a reference.}
63        \label{fig:browse_reference}
64\end{figure}
65
66Besides CrypPluginBase you will need to add three assembly references to provide the necessary ``Windows" namespaces for the \textbf{user control} functions ``Presentation" and ``QuickWatchPresentation". This can be done in the same manner as before with the ``CrypPluginBase" but by selecting the ``.NET" tab. Select the following .NET components:
67
68\begin{itemize}
69    \item PresentationCore
70    \item PresentationFramework
71    \item WindowsBase
72\end{itemize}
73\clearpage
74
75Afterwards your reference tree view should look like this:
76
77\begin{figure}[h!]
78                \includegraphics{figures/reference_tree.jpg}
79        \caption{A reference tree with the essential components.}
80        \label{fig:reference_tree}
81\end{figure}
82
83If your plugin will be based on other additional libraries, you can add them in the same way.
84
85\section{Modifing the project properties}
86\label{sec:ModifyTheProjectProperties}
87
88It is important to make two small changes to your plugin's assembly data to make sure that it will be imported correctly into CrypTool 2. Go to the Solution Explorer and open ``AssemblyInfo.cs", which can be found in the ``Properties" folder. Make the following two changes:
89
90\begin{itemize}
91        \item Change the attribute ``AssemblyVersion" to have the value ``2.0.*", and
92        \item Comment out the attribute ``AssemblyFileVersion".
93\end{itemize}
94
95This section of your assembly file should now look something like this:
96
97\begin{lstlisting}
98[assembly: AssemblyVersion("2.0.*")]
99//[assembly: AssemblyFileVersion("1.0.0.0")]
100\end{lstlisting}
101
102\section{Creating classes for the algorithm and its settings}
103\label{sec:CreatingClassesForTheAlgorithmAndItsSettings}
104
105In the next step we will create two classes. The first class will be the main driver; we will call ours ``Caesar" since that is the name of the cipher that it will implement. In our case, this class has to inherit from IEncryption because it will be an ecryption plugin. If it was instead a hash plugin, this class should inherit from IHash. The second class will be used to store setting information for the plugin, and thus we will name ours ``CaesarSettings". It has to inherit from ISettings.
106\clearpage
107
108\subsection{Creating a class for the algorithm}
109\label{sec:CreatingAClassForTheAlgorithm}
110
111When starting a new project, Visual Studio automatically creates a class which has the name ``Class1.cs".  Since this is a rather non-descriptive name, we will change it. In our example, it should be ``Caesar.cs". There are two ways to change the name:
112
113\begin{itemize}
114        \item Rename the existing class, or
115        \item Delete the existing class and create a new one.
116\end{itemize}
117%\clearpage
118
119Both options will achieve the same results. We will guide you through the second method. First, delete ``Class1.cs".
120
121\begin{figure}[h!]
122        \centering
123                \includegraphics{figures/new_class.jpg}
124        \caption{Deleting a class.}
125        \label{fig:new_class}
126\end{figure}
127\clearpage
128
129Then right-click on the project item (in our case, ``Caesar") and select ``Add $\rightarrow$ Class\ldots ":
130
131\begin{figure}[h]
132        \centering
133                \includegraphics{figures/add_new_class.jpg}
134        \caption{Adding a new class.}
135        \label{fig:add_new_class}
136\end{figure}
137\clearpage
138
139Finally, give your class a unique name. We will call our class ``Caesar.cs" and define it as public so that it will be available to other classes.
140
141\begin{figure}[h!]
142        \centering
143                \includegraphics[width=1.00\textwidth]{figures/name_new_class.jpg}
144        \caption{Naming the new class.}
145        \label{fig:name_new_class}
146\end{figure}
147
148\subsection{Creating a settings class}
149\label{sec:CreatingASettingsClass}
150
151Add a second public class in the same way. We will call the class ``CaesarSettings". The settings class stores the necessary information about controls, captions, descriptions and default parameters (e.g.\ for key settings, alphabets, key length and type of action) to build the \textbf{TaskPane} in the CrypTool application.
152\clearpage
153
154Below is an example of what a completed TaskPane for the existing Caesar plugin in CrypTool 2 looks like:
155
156\begin{figure}[h!]
157        \centering
158                \includegraphics{figures/task_pane.jpg}
159        \caption{The completed TaskPane for the existing Caesar plugin.}
160        \label{fig:task_pane}
161\end{figure}
162\clearpage
163
164\subsection{Adding the namespaces and inheritance sources for the Caesar class}
165\label{sec:AddingTheNamespacesAndInheritanceSourcesForTheCaesarClass}
166
167Open the ``Caesar.cs" file by double clicking on it in the Solution Explorer. To include the necessary namespaces in the class header, use the ``using" statement followed by the name of the desired namespace. The CrypTool 2.0 API provides the following namespaces:
168
169\begin{itemize}
170        \item Cryptool.PluginBase --- contains interfaces such as IPlugin, IHash, and ISettings, as well as attributes, enumerations, delegates and extensions.
171        \item Cryptool.PluginBase.Analysis --- contains interfaces for cryptanalysis plugins (such as ``Stream Comparator").
172        \item Cryptool.PluginBase.Control --- contains global interfaces for the IControl feature for defining custom controls.
173        \item Cryptool.PluginBase.Cryptography --- contains interfaces for encryption and hash algorithms such as AES, DES and MD5.
174        \item Cryptool.PluginBase.Editor --- contains interfaces for editors that can be implemented in CrypTool 2.0, such as the default editor.
175        \item Cryptool.PluginBase.Generator --- contains interfaces for generators, including the random input generator.
176        \item Cryptool.PluginBase.IO --- contains interfaces for input, output and the CryptoolStream.
177        \item Cryptool.PluginBase.Miscellaneous --- contains assorted helper classes, including \textit{GuiLogMessage} and \textit{PropertyChanged}.
178        \item Cryptool.PluginBase.Resources --- used only by CrypWin and the editor; not necessary for plugin development.
179        \item Cryptool.PluginBase.Tool --- contains an interface for all external tools implemented by CrypTool 2.0 that do not entirely support the CrypTool 2.0 API .
180        \item Cryptool.PluginBase.Validation --- contains interfaces for validation methods, including regular expressions.
181\end{itemize}
182
183In our example, the Caesar algorithm necessitates the inclusion of the following namespaces:
184
185\begin{itemize}
186        \item ''Cryptool.PluginBase'' --- to provide ''ISettings'' for the CaesarSettings class
187        \item ''Cryptool.PluginBase.Cryptography'' --- to provide ''IEncryption'' for the Caesar class
188        \item ''Cryptool.PluginBase.IO'' --- to provide CryptoolStream for the input and output Data
189        \item ''Cryptool.PluginBase.Miscellaneous'' --- to use the entire CrypTool event handler
190\end{itemize}
191
192It is important to define a new default namespace of our public class (''Caesar''). In CrypTool the default namespace is presented by ''Cryptool.[name of class]''. Therefore our namespace has to be defined as follows: ''Cryptool.Caesar''.\clearpage
193
194Up to now the source code should look as you can see below:
195
196\begin{lstlisting}
197using System.Collections.Generic;
198using System.Text;
199
200//needed CrypTool namespaces
201using Cryptool.PluginBase;
202using Cryptool.PluginBase.Cryptography;
203using Cryptool.PluginBase.IO;
204using Cryptool.PluginBase.Miscellaneous;
205
206namespace Cryptool.Caesar
207{
208        public class Caesar
209        {
210        }
211}
212\end{lstlisting}
213Next let your class ''Caesar'' inherit from IEncryption by inserting of the following statement:
214\begin{lstlisting}
215namespace Cryptool.Caesar
216{
217        public class Caesar: IEncryption
218        {
219        }
220}
221\end{lstlisting}
222\subsection{Add the interface functions for the class Caesar}
223\label{sec:AddTheInterfaceFunctionsForTheClassCaesar}
224There is an underscore at the ''I'' in IEncryption statement. Move your mouse over it or place the cursor at it and press ''Shift+Alt+F10'' and you will see the following submenu:
225\begin{figure}[h!]
226        \centering
227                \includegraphics{figures/inherit_submenu.jpg}
228        \caption{Inherit submenu}
229        \label{fig:inherit_submenu}
230\end{figure}\\
231Choose the item ''Implement interface 'IEncryption'''. Visual Studio/C\# Express will now place all available and needed interface members to interact with the CrypTool core (this saves you also a lot of typing code).\\
232Your code will now look like this:
233\begin{lstlisting}
234using System.Collections.Generic;
235using System.Text;
236
237using Cryptool.PluginBase;
238using Cryptool.PluginBase.Cryptography;
239using Cryptool.PluginBase.IO;
240using Cryptool.PluginBase.Miscellaneous;
241
242namespace Cryptool.Caesar
243{
244    public class Caesar : IEncryption
245    {
246        #region IPlugin Members
247
248        public void Dispose()
249        {
250            throw new NotImplementedException();
251        }
252
253        public void Execute()
254        {
255            throw new NotImplementedException();
256        }
257
258        public void Initialize()
259        {
260            throw new NotImplementedException();
261        }
262
263        public event GuiLogNotificationEventHandler OnGuiLogNotificationOccured;
264
265        public event PluginProgressChangedEventHandler OnPluginProgressChanged;
266
267        public event StatusChangedEventHandler OnPluginStatusChanged;
268
269        public void Pause()
270        {
271            throw new NotImplementedException();
272        }
273
274        public void PostExecution()
275        {
276            throw new NotImplementedException();
277        }
278
279        public void PreExecution()
280        {
281            throw new NotImplementedException();
282        }
283
284        public System.Windows.Controls.UserControl Presentation
285        {
286            get { throw new NotImplementedException(); }
287        }
288
289        public System.Windows.Controls.UserControl QuickWatchPresentation
290        {
291            get { throw new NotImplementedException(); }
292        }
293
294        public ISettings Settings
295        {
296            get { throw new NotImplementedException(); }
297        }
298
299        public void Stop()
300        {
301            throw new NotImplementedException();
302        }
303
304        #endregion
305
306        #region INotifyPropertyChanged Members
307
308        public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
309
310        #endregion
311    }
312}
313\end{lstlisting}
314\subsection{Add namespace and interfaces for the class CaesarSettings}\label{sec:AddNamespaceAndInterfacesForTheClassCaesarSettings}
315Let's now take a look at the second class "CaesarSettings" by double clicking at the "CaesarSettings.cs" file at the Solution Explorer. First we also have to include the namespace of "Cryptool.PluginBase" to the class header and let the settings class inherit from "ISettings" analogous as seen before at the Caesar class. Visual Studio/C\# Express will here also automatically place code from the CrypTool interface if available.
316\begin{lstlisting}
317using System.Collections.Generic;
318using System.Text;
319
320using Cryptool.PluginBase;
321
322namespace Cryptool.Caesar
323{
324    public class CaesarSettings : ISettings
325    {
326        #region ISettings Members
327
328        public bool HasChanges
329        {
330            get
331            {
332                throw new NotImplementedException();
333            }
334            set
335            {
336                throw new NotImplementedException();
337            }
338        }
339
340        #endregion
341
342        #region INotifyPropertyChanged Members
343
344        public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
345
346        #endregion
347    }
348}
349\end{lstlisting}
350\subsection{Add controls for the class CaesarSettings (if needed)}\label{sec:AddControlsForTheClassCaesarSettingsIfNeeded}
351Now we have to implement some kind of controls (like button, text box) if we need them in the CrypTool \textbf{TaskPane} to modify settings of the algorithm. If you decided to provide an algorithm (e.g. Hash) which do not have any kind of settings you can leave this class now empty. The only part you have to modify is the ''HasChanges'' property to avoid any ''NotImplementedException''. How to modify this property you can see in the following code which demonstrate the modifications fot the TaskPane for our Caesar algorithm. You can also take a look at the other algorithm source codes which are stored in our subversion how you can provide a TaskPane. The following source code demonstrates how we provide our TaskPane as seen above.
352\begin{lstlisting}
353using System;
354using System.ComponentModel;
355using System.Windows;
356using Cryptool.PluginBase;
357using System.Windows.Controls;
358
359namespace Cryptool.Caesar
360{
361    public class CaesarSettings : ISettings
362    {
363        #region Public Caesar specific interface
364
365        /// <summary>
366        /// We use this delegate to send log messages from the settings class to the Caesar plugin
367        /// </summary>
368        public delegate void CaesarLogMessage(string msg, NotificationLevel loglevel);
369
370        /// <summary>
371        /// An enumaration for the different modes of dealing with unknown characters
372        /// </summary>
373        public enum UnknownSymbolHandlingMode { Ignore = 0, Remove = 1, Replace = 2 };
374
375        /// <summary>
376        /// Fire if a new status message was send
377        /// </summary>
378        public event CaesarLogMessage LogMessage;
379
380        public delegate void CaesarReExecute();
381
382        public event CaesarReExecute ReExecute;
383
384        /// <summary>
385        /// Retrieves the current sihft value of Caesar (i.e. the key), or sets it
386        /// </summary>
387        [PropertySaveOrder(0)]
388        public int ShiftKey
389        {
390            get { return shiftValue; }
391            set
392            {
393                setKeyByValue(value);
394            }
395        }
396
397        /// <summary>
398        /// Retrieves the current setting whether the alphabet should be treated as case sensitive or not
399        /// </summary>
400        [PropertySaveOrder(1)]
401        public bool CaseSensitiveAlphabet
402        {
403            get
404            {
405                if (caseSensitiveAlphabet == 0)
406                {   return false;   }
407                else
408                {   return true;    }
409            }
410            set {} // readonly, because there are some problems if we omit the set part.
411        }
412
413
414        /// <summary>
415        /// Returns true if some settings have been changed. This value should be set externally to false e.g.
416        /// when a project was saved.
417        /// </summary>
418        [PropertySaveOrder(3)]
419        public bool HasChanges
420        {
421            get { return hasChanges; }
422            set { hasChanges = value; }
423        }
424
425        #endregion
426
427        #region Private variables
428        private bool hasChanges;
429        private int selectedAction = 0;
430        private string upperAlphabet = ''ABCDEFGHIJKLMNOPQRSTUVWXYZ'';
431        private string lowerAlphabet = ''abcdefghijklmnopqrstuvwxyz'';
432        private string alphabet = ''ABCDEFGHIJKLMNOPQRSTUVWXYZ'';
433        private char shiftChar = 'C';
434        private int shiftValue = 2;
435        // private int shiftValue = 2;
436        private UnknownSymbolHandlingMode unknownSymbolHandling = UnknownSymbolHandlingMode.Ignore;
437        private int caseSensitiveAlphabet = 0; // 0 = case insensitve, 1 = case sensitive
438        private bool sensitivityEnabled = true;
439        #endregion
440
441        #region Private methods
442
443        private string removeEqualChars(string value)
444        {
445            int length = value.Length;
446
447            for (int i = 0; i < length; i++)
448            {
449                for (int j = i + 1; j < length; j++)
450                {
451                    if ((value[i] == value[j]) || (!CaseSensitiveAlphabet & (char.ToUpper(value[i]) == char.ToUpper(value[j]))))
452                    {
453                        LogMessage(''Removing duplicate letter: \''' + value[j] + ''\' from alphabet!'', NotificationLevel.Warning);
454                        value = value.Remove(j,1);
455                        j--;
456                        length--;
457                    }
458                }
459            }
460
461            return value;
462        }
463
464        /// <summary>
465        /// Set the new shiftValue and the new shiftCharacter to offset % alphabet.Length
466        /// </summary>
467        private void setKeyByValue(int offset)
468        {
469            HasChanges = true;
470
471            // making sure the shift value lies within the alphabet range
472            offset = offset % alphabet.Length;
473
474            // set the new shiftChar
475            shiftChar = alphabet[offset];
476
477            // set the new shiftValue
478            shiftValue = offset;
479
480            // Anounnce this to the settings pane
481            OnPropertyChanged(''ShiftValue'');
482            OnPropertyChanged(''ShiftChar'');
483
484            // print some info in the log.
485            LogMessage(''Accepted new shift value '' + offset + ''! (Adjusted shift character to \''' + shiftChar + ''\')'', NotificationLevel.Info);
486        }
487
488        private void setKeyByCharacter(string value)
489        {
490            try
491            {
492                int offset;
493                if (this.CaseSensitiveAlphabet)
494                {
495                    offset = alphabet.IndexOf(value[0]);
496                }
497                else
498                {
499                    offset = alphabet.ToUpper().IndexOf(char.ToUpper(value[0]));
500                }
501
502                if (offset >= 0)
503                {
504                    HasChanges = true;
505                    shiftValue = offset;
506                    shiftChar = alphabet[shiftValue];
507                    LogMessage(''Accepted new shift character \''' + shiftChar + ''\'! (Adjusted shift value to '' + shiftValue + '')'', NotificationLevel.Info);
508                    OnPropertyChanged(''ShiftValue'');
509                    OnPropertyChanged(''ShiftChar'');
510                }
511                else
512                {
513                    LogMessage(''Bad input \'''' + value + ''\''! (Character not in alphabet!) Reverting to '' + shiftChar.ToString() + ''!'', NotificationLevel.Error);
514                }
515            }
516            catch (Exception e)
517            {
518                LogMessage(''Bad input \'''' + value + ''\''! ('' + e.Message + '') Reverting to '' + shiftChar.ToString() + ''!'', NotificationLevel.Error);
519            }
520        }
521
522        #endregion
523
524        #region Algorithm settings properties (visible in the Settings pane)
525
526        [PropertySaveOrder(4)]
527        [ContextMenu(''Action'', ''Select the Algorithm action'', 1, DisplayLevel.Beginner, ContextMenuControlType.ComboBox, new int[] { 1, 2 }, ''Encrypt'', ''Decrypt'')]
528        [TaskPane(''Action'', ''setAlgorithmActionDescription'', null, 1, true, DisplayLevel.Beginner, ControlType.ComboBox, new string[] { ''Encrypt'', ''Decrypt'' })]
529        public int Action
530        {
531            get
532            {
533                return this.selectedAction;
534            }
535            set
536            {
537                if (value != selectedAction) HasChanges = true;
538                this.selectedAction = value;
539                OnPropertyChanged(''Action'');
540
541                if (ReExecute != null) ReExecute();
542            }
543        }
544
545        [PropertySaveOrder(5)]
546        [TaskPane(''Key as integer'', ''Enter the number of letters to shift. For instance a value of 1 means that the plaintext character a gets mapped to the ciphertext character B, b to C and so on.'', null, 2, true, DisplayLevel.Beginner, ControlType.NumericUpDown, ValidationType.RangeInteger, 0, 100)]
547        public int ShiftValue
548        {
549            get { return shiftValue; }
550            set
551            {
552                setKeyByValue(value);
553                if (ReExecute != null) ReExecute();
554            }
555        }
556
557
558        [PropertySaveOrder(6)]
559        [TaskPaneAttribute(''Key as single letter'', ''Enter a single letter as the key. This letter is mapped to an integer stating the position in the alphabet. The values for 'Key as integer' and 'Key as single letter' are always synchronized.'', null, 3, true, DisplayLevel.Beginner, ControlType.TextBox, ValidationType.RegEx, ''^([A-Z]|[a-z]){1,1}'')]
560        public string ShiftChar
561        {
562            get { return this.shiftChar.ToString(); }
563            set
564            {
565                setKeyByCharacter(value);
566                if (ReExecute != null) ReExecute();
567            }
568        }
569
570        [PropertySaveOrder(7)]
571        [ContextMenu(''Unknown symbol handling'', ''What should be done with encountered characters at the input which are not in the alphabet?'', 4, DisplayLevel.Expert, ContextMenuControlType.ComboBox, null, new string[] { ''Ignore (leave unmodified)'', ''Remove'', ''Replace with \'?\''' })]
572        [TaskPane(''Unknown symbol handling'', ''What should be done with encountered characters at the input which are not in the alphabet?'', null, 4, true, DisplayLevel.Expert, ControlType.ComboBox, new string[] { ''Ignore (leave unmodified)'', ''Remove'', ''Replace with \'?\''' })]
573        public int UnknownSymbolHandling
574        {
575            get { return (int)this.unknownSymbolHandling; }
576            set
577            {
578                if ((UnknownSymbolHandlingMode)value != unknownSymbolHandling) HasChanges = true;
579                this.unknownSymbolHandling = (UnknownSymbolHandlingMode)value;
580                OnPropertyChanged(''UnknownSymbolHandling'');
581
582                if (ReExecute != null) ReExecute();
583            }
584        }
585
586        [SettingsFormat(0, ''Normal'', ''Normal'', ''Black'', ''White'', Orientation.Vertical)]
587        [PropertySaveOrder(9)]
588        [TaskPane(''Alphabet'', ''This is the used alphabet.'', null, 6, true, DisplayLevel.Expert, ControlType.TextBox, '''')]
589        public string AlphabetSymbols
590        {
591          get { return this.alphabet; }
592          set
593          {
594            string a = removeEqualChars(value);
595            if (a.Length == 0) // cannot accept empty alphabets
596            {
597              LogMessage(''Ignoring empty alphabet from user! Using previous alphabet: \'''' + alphabet + ''\'' ('' + alphabet.Length.ToString() + '' Symbols)'', NotificationLevel.Info);
598            }
599            else if (!alphabet.Equals(a))
600            {
601              HasChanges = true;
602              this.alphabet = a;
603              setKeyByValue(shiftValue); //re-evaluate if the shiftvalue is still within the range
604              LogMessage(''Accepted new alphabet from user: \'''' + alphabet + ''\'' ('' + alphabet.Length.ToString() + '' Symbols)'', NotificationLevel.Info);
605              OnPropertyChanged(''AlphabetSymbols'');
606
607              if (ReExecute != null) ReExecute();
608            }
609          }
610        }
611
612        /// <summary>
613        /// Visible setting how to deal with alphabet case. 0 = case insentive, 1 = case sensitive
614        /// </summary>
615        //[SettingsFormat(1, ''Normal'')]
616        [PropertySaveOrder(8)]
617        [ContextMenu(''Alphabet case sensitivity'', ''Should upper and lower case be treated differently? (Should a == A)'', 7, DisplayLevel.Expert, ContextMenuControlType.ComboBox, null, new string[] { ''Case insensitive'', ''Case sensitive'' })]
618        [TaskPane(''Alphabet case sensitivity'', ''Should upper and lower case be treated differently? (Should a == A)'', null, 7, true, DisplayLevel.Expert, ControlType.ComboBox, new string[] { ''Case insensitive'', ''Case sensitive'' })]
619        public int AlphabetCase
620        {
621            get { return this.caseSensitiveAlphabet; }
622            set
623            {
624                if (value != caseSensitiveAlphabet) HasChanges = true;
625                this.caseSensitiveAlphabet = value;
626                if (value == 0)
627                {
628                    if (alphabet == (upperAlphabet + lowerAlphabet))
629                    {
630                        alphabet = upperAlphabet;
631                        LogMessage(''Changing alphabet to: \'''' + alphabet + ''\'' ('' + alphabet.Length.ToString() + '' Symbols)'', NotificationLevel.Info);
632                        OnPropertyChanged(''AlphabetSymbols'');
633                        // re-set also the key (shiftvalue/shiftChar to be in the range of the new alphabet
634                        setKeyByValue(shiftValue);
635                    }
636                }
637                else
638                {
639                    if (alphabet == upperAlphabet)
640                    {
641                        alphabet = upperAlphabet + lowerAlphabet;
642                        LogMessage(''Changing alphabet to: \'''' + alphabet + ''\'' ('' + alphabet.Length.ToString() + '' Symbols)'', NotificationLevel.Info);
643                        OnPropertyChanged(''AlphabetSymbols'');
644                    }
645                }
646
647                // remove equal characters from the current alphabet
648                string a = alphabet;
649                alphabet = removeEqualChars(alphabet);
650
651                if (a != alphabet)
652                {
653                    OnPropertyChanged(''AlphabetSymbols'');
654                    LogMessage(''Changing alphabet to: \'''' + alphabet + ''\'' ('' + alphabet.Length.ToString() + '' Symbols)'', NotificationLevel.Info);
655                }
656
657                OnPropertyChanged(''AlphabetCase'');
658                if (ReExecute != null) ReExecute();
659            }
660        }
661
662        #endregion
663
664        #region INotifyPropertyChanged Members
665
666        public event PropertyChangedEventHandler PropertyChanged;
667
668        protected void OnPropertyChanged(string name)
669        {
670          if (PropertyChanged != null)
671          {
672            PropertyChanged(this, new PropertyChangedEventArgs(name));
673          }
674        }
675
676        #endregion
677
678        #region TaskPaneAttributeChanged-Sample
679        /// <summary>
680        /// This event is just used here for sample reasons
681        /// </summary>
682        public event TaskPaneAttributeChangedHandler TaskPaneAttributeChanged;
683
684        [TaskPane(''Enable/Disable sensitivity'', ''This setting is just a sample and shows how to enable / disable a setting.'', ''AttributeChangedSample'', 8, false, DisplayLevel.Beginner, ControlType.Button)]
685        public void EnableDisableSesitivity()
686        {
687          if (TaskPaneAttributeChanged!= null)
688          {
689            sensitivityEnabled = !sensitivityEnabled;
690            if (sensitivityEnabled)
691            {
692              TaskPaneAttributeChanged(this, new TaskPaneAttributeChangedEventArgs(new TaskPaneAttribteContainer(''AlphabetCase'', Visibility.Visible)));
693            }
694            else
695            {
696              TaskPaneAttributeChanged(this, new TaskPaneAttributeChangedEventArgs(new TaskPaneAttribteContainer(''AlphabetCase'', Visibility.Collapsed)));
697            }
698          }
699        }
700        #endregion TaskPaneAttributeChanged-Sample
701    }
702}
703\end{lstlisting}
704\section{Select and add an image as icon for the class Caesar}\label{sec:SelectAndAddAnImageAsIconForTheClassCaesar}
705Before we go back to the code of the Caesar class, we have to add an icon image to our project, which will be shown in the CrypTool \textbf{ribbon bar} or/and \textbf{navigation pane}. As there is no default, using an icon image is mandatory.\\\\
706\textit{\small Note: This will be changed in future. A default icon will be used if no icon image has been provided.}\\\\
707For testing purposes you may create a simple black and white PNG image with MS Paint or Paint.NET. As image size you can use 40x40 pixels for example, but as the image will be scaled when required, any size should do it. Place the image file in your project directory or in a subdirectory.\clearpage
708Then make a right click on the project item "Caesar" or any subdirectory within the Solution Explorer, and select ''Add-$>$Existing Item...'':
709
710\begin{figure}[h!]
711        \centering
712                \includegraphics{figures/add_existing_item.jpg}
713        \caption{Add existing item}
714        \label{fig:add_existing_item}
715\end{figure}
716
717As you can see, in our solution we create an new folder named ''Images'' (make a right click on the project item ''Caesar'' and select ''Add-$>$New Folder'') and placed there the new icon by clicking right on the folder as mentioned aboved.\clearpage
718Then select ''Image Files'' as file type, and choose the icon for your plugin:
719\begin{figure}[h!]
720        \centering
721                \includegraphics{figures/choose_icon.jpg}
722        \caption{Choose the right icon}
723        \label{fig:choose_icon}
724\end{figure}
725Finally we have to set the icon as a ''Resource'' to avoid providing the icon as a separate file. Make a right click on the icon and select the item ''Properties'':\clearpage
726\begin{figure}[h!]
727        \centering
728                \includegraphics{figures/icon_properties.jpg}
729        \caption{Icon properties}
730        \label{fig:icon_properties}
731\end{figure}
732In the ''Properties'' panel you have to set the ''Build Action'' to ''Resource'' (not embedded resource):
733\begin{figure}[h!]
734        \centering
735                \includegraphics{figures/icon_build_action.jpg}
736        \caption{Icon  build action}
737        \label{fig:icon_build_action}
738\end{figure}
739\section{Set the attributes for the class Caesar}\label{sec:SetTheAttributesForTheClassCaesar}
740Now let's go back to the code of the Caesar class (''Caesar.cs'' file). First we have to set the necessary attributes for our class. This attributes are used to provide additional information for the CrypTool 2.0 environment. If not set, your plugin won't show up in the GUI, even if everything else is implemented correctly.
741
742Attributes are used for \textbf{declarative} programming and provide meta data, that can be attached to the existing .NET meta data , like classes and properties. CrypTool provides a set of custom attributes, that are used to mark the different parts of your plugin.
743
744
745\textit{[Author]}\\
746The first attribute called ''Author'' is optional, which means we are not forced to define this attribute. It provides the additional information about the plugin developer. This informations you can see for example in the TaskPane as shown on a screenshot above. We set this attribute to demonstrate how it has to look in case you want to provide this attribute.
747\begin{figure}[h!]
748        \centering
749                \includegraphics[width=1.00\textwidth]{figures/attribute_author.jpg}
750        \caption{Attribute author}
751        \label{fig:attribute_author}
752\end{figure}
753
754As we can see above the author attribute takes four elements of type string. These elements are:
755\begin{itemize}
756        \item Author = name of the plugin developer
757        \item Email = email of the plugin developer if he wants to be contact
758        \item Institute = current employment of the developer like University or Company
759        \item Url = the website or homepage of the developer
760\end{itemize}
761All this elements are also optional. The developer decides what he wants to publish. Unused elements shall be set to null or a zero-length string ('''').
762
763Our author attribute should look now as you can see below:
764\begin{figure}[h!]
765        \centering
766                \includegraphics[width=1.00\textwidth]{figures/attribute_author_filled.jpg}
767        \caption{Filled author auttribute}
768        \label{fig:attribute_author_filled}
769\end{figure}
770
771
772\textit{[PluginInfo]}\\
773The second attribute called ''PluginInfo'' provides the necessary information about the plugin like caption and tool tip. This attribute is mandatory. The attribute has the definition as you can see below:
774\begin{figure}[h]
775        \centering
776                \includegraphics[width=1.00\textwidth]{figures/attribute_plugininfo.jpg}
777        \caption{Attribute PluginInfo}
778        \label{fig:attribute_plugininfo}
779\end{figure}
780
781This attribute expects the following elements:
782\begin{itemize}
783        \item resourceFile = Defines if resource files will be provided and where to find them. E.g. to provide the plugin multilingual you can store the labels in such a resource file. This element is optional.
784        \item startable = Set this flag to true only if your plugin is some kind of input or generator plugin (probably if your plugin just has outputs and no inputs). In all other cases use false here. This flag is important. Setting this flag to true for a non input/generator plugin will result in unpredictable chain runs. This element is mandatory.
785        \item caption = from type string, the name of the plugin or the resource field name if you provide the caption in a resource file (e.g. to provide the button content). This element is mandatory.
786        \item toolTip = from type string, description of the plugin or the resource field name if you provide the toolTip in a resource file (e.g. to provide the button tool tip). This element is optional.
787        \item descriptionUrl = from type string, define where to find the whole description files (e.g. XAML files). This element is optional.
788        \item icons = from type string array, which provides all necessary icon paths you want to use in the plugin (e.g. the plugin icon as seen above). This element is mandatory.
789\end{itemize}
790Unused optional elements shall be set to null or a zero-length string ('''').
791
792
793\textit{\small Note 1: It is possible to use the plugin without setting a caption though it is not recommended. This will be changed in future and the plugin will fail to load without a caption.\\\\
794\small Note 2: Currently a zero-length toolTip string appears as empty box. This will be changed in future.\\\\
795\small Note 3: Tooltip and description currently do not support internationalization and localization. This will be changed in future.\\\\}
796In our example the first parameter called ''resourceFile'' has to be set to ''Cryptool.Caesar.Resource.res'' because we want to provide the plugin multilingual and want to store the labels and caption in a resource file. Otherwise ignore this element.
797\begin{figure}[h]
798        \centering
799                \includegraphics[width=1.00\textwidth]{figures/attribute_plugininfo_resourceFile.JPG}
800        \caption{Attribute PluginInfo element resourceFile}
801        \label{fig:attribute_plugininfo_resourceFile}
802\end{figure}
803
804The second parameter called ''startable'' has to be set to ''false'', because our encryption algorithm is neither an input nor generator plugin.
805\begin{figure}[h!]
806        \centering
807                \includegraphics[width=1.00\textwidth]{figures/attribute_plugininfo_startable.jpg}
808        \caption{Attribute PluginInfo startable}
809        \label{fig:attribute_plugininfo_startable}
810\end{figure}
811
812The next two parameters are needed to define the plugin's name and its description. Now that we decided to provide a resource file we have to place here the both resource field names which contains the description and captions. Otherwise just write here a simple string text:
813\begin{figure}[h!]
814        \centering
815                \includegraphics[width=1.00\textwidth]{figures/attribute_plugininfo_description.jpg}
816        \caption{Attribute PluginInfo name and description}
817        \label{fig:attribute_plugininfo_description}
818\end{figure}
819
820The next element defines the location path of the description file. The parameter is made up by $<$Assembly name$>$/$<$filename$>$ or $<$Assembly name$>$/$<$Path$>$/$<$file name$>$ if you want to store your description files in a separate folder (as seen on the icon). The description file has to be of type XAML. In our case we create a folder called ''DetailedDescription'' and store our XAML file there with the necessary images if needed. How you manage the files and folders is up to you. This folder could now look as you can see below:
821\begin{figure}[h!]
822        \centering
823                \includegraphics{figures/attribute_plugininfo_detailed_descr_path.jpg}
824        \caption{Attribute PluginInfo icon and description file path}
825        \label{fig:attribute_plugininfo_icon_path}
826\end{figure}
827
828Accordingly the attribute parameter has to be set to:
829\begin{figure}[h!]
830        \centering
831                \includegraphics[width=1.00\textwidth]{figures/attribute_plugininfo_detailed_descr.jpg}
832        \caption{Attribute PluginInfo description file}
833        \label{fig:attribute_plugininfo_icon}
834\end{figure}
835
836The detailed description could now look like this in CrypTool (right click plugin icon on workspace and select ''Show description''):\clearpage
837\begin{figure}[h!]
838        \centering
839                \includegraphics[width=1.00\textwidth]{figures/xaml_description.jpg}
840        \caption{XAML detailed description}
841        \label{fig:xaml_description}
842\end{figure}
843
844The last parameter tells CrypTool the names of the provided icons. This parameter is made up by $<$Assembly name$>$/$<$file name$>$ or $<$Assembly name$>$/$<$Path$>$/$<$file name$>$.\\\\
845The most important icon is the plugin icon, which will be shown in CrypTool in the ribbon bar or navigation pane (This is the first icon in list, so you have to provide at least one icon for a plugin). As named above how to add an icon to the solution accordingly we have to tell CrypTool where to find the icon by setting this parameter as you can see below:
846\begin{figure}[h!]
847        \centering
848                \includegraphics[width=1.00\textwidth]{figures/attribute_plugininfo_icons.jpg}
849        \caption{Attribute PluginInfo icons}
850        \label{fig:attribute_plugininfo_icons}
851\end{figure}
852
853You can define further icon paths if needed, by adding the path string separated by a comma. We just add here two further icons (don't forget to add the icons to your solution) to provide them for the context menu in the CrypTool workspace.\\\\
854\textit{[EncryptionType]}\\
855The third and last attribute called ''EncryptionType'' is needed to tell CrypTool which type of plugin we want to provide. CrypTool is now able to place the plugin in the right group at the navigation pane or/and ribbon bar. Therefore Caesar is a classical algorithm so we have to set the following attribute:
856\begin{figure}[h]
857        \centering
858                \includegraphics[width=1.00\textwidth]{figures/attribute_encryption_type.JPG}
859        \caption{Attribute encryption type}
860        \label{fig:attribute_encryption_type}
861\end{figure}
862
863The ''EncryptionType'' attribute can also be set as the following types:
864\begin{itemize}
865        \item Asymmetric = for asymmetric encryption algorithms like RSA
866        \item Classic = for classic encryption or hash algorithms like Caesar or MD5
867        \item Hybrid = for a combination of several algorithm where the data is encrypted symmetric and the encryption key asymmetric
868        \item SymmetricBlock = for all block cipher algorithms like DES, AES or Twofish
869        \item SymmetricStream = for all stream cipher algorithms like RC4, Rabbit or SEAL
870\end{itemize}
871
872
873\section{Set the private variables for the settings in the class Caesar}\label{sec:SetThePrivateVariablesForTheSettingsInTheClassCaesar}
874The next step is to define some private variables needed for the settings, input and output data which could look like this:
875\begin{lstlisting}
876public class Caesar : IEncryption
877{
878        #region Private variables
879        private CaesarSettings settings;
880        private string inputString;
881        private string outputString;
882        private enum CaesarMode { encrypt, decrypt };
883        private List<CryptoolStream> listCryptoolStreamsOut = new List<CryptoolStream>();
884        #endregion
885\end{lstlisting}
886Please notice if there is a sinuous line at the code you type for example at the ''CryptoolStream'' type of the variable listCryptoolStreamsOut. ''CryptoolStream'' is a data type for input and output between plugins and is able to handle large data amounts. To use the CrypTool own stream type, include the namespace ''Cryptool.PluginBase.IO'' with a ''using'' statement as explained in chapter \ref{sec:CaesarNamespacesAndInheritance}. Check the other code entries while typing and update the missing namespaces.\\
887The following private variables are being used in this example:
888\begin{itemize}
889        \item CaesarSettings settings: required to implement the IPlugin interface properly
890        \item string inputString: sting to read the input data from
891        \item string outputString: string to save the output data
892        \item enum CaesarMode: our own definition how to select between an encryption or decryption. It's up to you how to solve your algorithm
893        \item List$<$CryptoolStream$>$ listCryptoolStreamsOut: list of all streams being created by Caesar plugin, required to perform a clean dispose
894\end{itemize}
895\section{Define the code of the class Caesar to fit the interface}\label{sec:DefineTheCodeOfTheClassCaesarToFitTheInterface}
896Next we have to complete our code to correctly serve the interface.\\
897First we add a constructor to our class where we can create an instance of our settings class and a function to handle events:
898\begin{lstlisting}
899public class Caesar : IEncryption
900{
901        #region Private variables
902        private CaesarSettings settings;
903        private string inputString;
904        private string outputString;
905        private enum CaesarMode { encrypt, decrypt };
906        private List<CryptoolStream> listCryptoolStreamsOut = new List<CryptoolStream>();
907        #endregion
908       
909        public Caesar()
910        {
911                this.settings = new CaesarSettings();
912                this.settings.LogMessage += Caesar_LogMessage;
913        }
914\end{lstlisting}
915Secondly, we have to implement the property ''Settings'' defined in the interface:
916\begin{lstlisting}
917public ISettings Settings
918{
919        get { return (ISettings)this.settings; }
920        set { this.settings = (CaesarSettings)value; }
921}
922\end{lstlisting}
923Thirdly we have to define five properties with their according attributes. This step is necessary to tell CrypTool that these properties are input/output properties used for data exchange with other plugins or to provide our plugin with external data.\\
924The attribute is named ''PropertyInfo'' and consists of the following elements:
925\begin{itemize}
926        \item direction = defines whether this property is an input or output property, i.e. whether it reads input data or writes output data
927        \begin{itemize}
928                \item Direction.Input
929                \item Direction.Output
930        \end{itemize}
931        \item caption = caption of the property (e.g. shown at the input on the dropped icon in the editor), see below:
932\begin{figure}[h]
933        \centering
934                \includegraphics{figures/property_caption.jpg}
935        \caption{Possible property caption}
936        \label{fig:property_caption}
937\end{figure}
938        \item toolTip = tooltip of the property (e.g. shown at the input arrow on the dropped icon in the editor), see above
939        \item descriptionUrl = not used right now
940        \item mandatory = this flag defines whether an input is required to be connected by the user. If set to true, there has to be an input connection that provides data. If no input data is provided for mandatory input, your plugin will not be executed in the workflow chain. If set to false, connecting the input is optional. This only applies to input properties. If using Direction.Output, this flag is ignored.
941        \item hasDefaultValue = if this flag is set to true, CrypTool treats this plugin as though the input has already input data.
942        \item DisplayLevel = define in which display levels your property will be shown in CrypTool. CrypTool provides the following display levels:
943        \begin{itemize}
944                \item DisplayLevel.Beginner
945                \item DisplayLevel.Experienced
946                \item DisplayLevel.Expert
947                \item DisplayLevel.Professional
948        \end{itemize}
949        \item QuickWatchFormat = defines how the content of the property will be shown in the quick watch. CrypTool accepts the following quick watch formats:
950        \begin{itemize}
951                \item QuickWatchFormat.Base64
952                \item QuickWatchFormat.Hex
953                \item QuickWatchFormat.None
954                \item QuickWatchFormat.Text\\
955                A quick watch in Hex could look like this:
956\begin{figure}[h]
957        \centering
958                \includegraphics{figures/quick_watch.jpg}
959        \caption{Possible quick watch}
960        \label{fig:quick_watch}
961\end{figure}
962        \end{itemize}
963        \item quickWatchConversionMethod = this string points to a conversion method; most plugins can use a ''null'' value here, because no conversion is necessary. The QuickWatch function uses system ''default'' encoding to display data. So only if your data is in some other format, like Unicode or UTF8, you have to provide the name of a conversion method as string. The method header has to look like this:
964\begin{lstlisting}
965object YourMethodName(string PropertyNameToConvert)
966\end{lstlisting}
967\end{itemize}
968First we define the ''InputString'' property getter and setter which is needed to provide our plugin with data which has to be encrypted or decrypted:
969\begin{lstlisting}
970[PropertyInfo(Direction.InputData, ''Text input'', ''Input a string to be processed by the Caesar cipher'', '''', true, false, DisplayLevel.Beginner, QuickWatchFormat.Text, null)]
971public string InputString
972{
973        get { return this.inputString; }
974        set
975  {
976                if (value != inputString)
977                {
978                        this.inputString = value;
979                        OnPropertyChanged(''InputString'');
980                }
981        }
982}
983\end{lstlisting}
984In the getter we return the value of the input data.\\\\
985\textit{\small Note 1: It is currently not possible to read directly from the input data stream without creating an intermediate CryptoolStream.\\\\
986\small Note 2: The naming may be confusing. The new CryptoolStream is not an output stream, but it is added to the list of output streams to enable a clean dispose afterwards. See chapter 9 below.\\\\}
987The setter checkes if the input value has changed and sets the new input data and announces the data to the CrypTool 2.0 environment by using the expression ''OnPropertyChanged($<$Property name$>$)''. For input properties this step is necessary to update the quick watch view.\\
988The output data property (which provides the encrypted or decrypted input data) could look like this:
989\begin{lstlisting}
990[PropertyInfo(Direction.OutputData, ''Text output'', ''The string after processing with the Caesar cipher'', '''', false, false, DisplayLevel.Beginner, QuickWatchFormat.Text, null)]
991public string OutputString
992{
993        get { return this.outputString; }
994        set
995        {
996                outputString = value;
997                OnPropertyChanged(''OutputString'');
998        }
999}
1000\end{lstlisting}
1001CrypTool does not require implementing output setters, as they will never be called from outside of the plugin. Nevertheless in this example our plugin accesses the property itself, therefore we chose to implement the setter.\\
1002You can also provide additional output data types if you like. For example we provide also an output data of type CryptoolStream, an input data for external alphabets and an input data for the shift value of our Caesar algorithm:
1003\begin{lstlisting}
1004[PropertyInfo(Direction.OutputData, ''propStreamOutputToolTip'', ''propStreamOutputDescription'', '''', false, false, DisplayLevel.Beginner, QuickWatchFormat.Text, null)]
1005public CryptoolStream OutputData
1006{
1007        get
1008        {
1009                if (outputString != null)
1010                {
1011                        CryptoolStream cs = new CryptoolStream();
1012                        listCryptoolStreamsOut.Add(cs);
1013                        cs.OpenRead(Encoding.Default.GetBytes(outputString.ToCharArray()));
1014                        return cs;
1015                }
1016                else
1017                {
1018                        return null;
1019                }
1020        }
1021        set { }
1022}
1023
1024[PropertyInfo(Direction.InputData, ''External alphabet input'', ''Input a string containing the alphabet which should be used by Caesar.\nIf no alphabet is provided on this input, the internal alphabet will be used.'', '''', false, false, DisplayLevel.Expert, QuickWatchFormat.Text, null)]
1025public string InputAlphabet
1026{
1027        get { return ((CaesarSettings)this.settings).AlphabetSymbols; }
1028        set
1029        {
1030                if (value != null && value != settings.AlphabetSymbols)
1031                {
1032                        ((CaesarSettings)this.settings).AlphabetSymbols = value;
1033                        OnPropertyChanged(''InputAlphabet'');
1034                }
1035        }
1036}
1037
1038[PropertyInfo(Direction.InputData, ''Shift value (integer)'', ''Same setting as Shift value in Settings-Pane but as dynamic input.'', '''', false, false, DisplayLevel.Expert, QuickWatchFormat.Text, null)]
1039public int ShiftKey
1040{
1041        get { return settings.ShiftKey; }
1042        set
1043        {
1044                if (value != settings.ShiftKey)
1045                {
1046                        settings.ShiftKey = value;
1047                }
1048        }
1049}
1050\end{lstlisting}
1051This property's setter is not called and therefore not implemented.\\
1052The CrypTool-API provides two methods to send messages to the CrypTool. The method ''GuiLogMessage'' is used to send messages to the CrypTool status bar. This is a nice feature to inform the user what your plugin is currently doing.
1053\begin{figure}[h]
1054        \centering
1055                \includegraphics[width=1.00\textwidth]{figures/status_bar.jpg}
1056        \caption{Status Bar}
1057        \label{fig:status_bar}
1058\end{figure}\\
1059The method takes two parameters which are:
1060\begin{itemize}
1061        \item Message = will be shown in the status bar and is of type string
1062        \item NotificationLevel = to group the messages to their alert level
1063        \begin{itemize}
1064                \item NotificationLevel.Error
1065                \item NotificationLevel.Warning
1066                \item NotificationLevel.Info
1067                \item NotificationLevel.Debug
1068        \end{itemize}
1069\end{itemize}
1070As we can recognize we have two methods named ''OnPropertyChanged'' and ''GuiLogMessage'' which are not defined. So we have to define these two methods as you can see below:
1071\begin{lstlisting}
1072public event GuiLogNotificationEventHandler OnGuiLogNotificationOccured;
1073private void GuiLogMessage(string message, NotificationLevel logLevel)
1074{
1075        EventsHelper.GuiLogMessage(OnGuiLogNotificationOccured, this, new GuiLogEventArgs(message, this, logLevel));
1076}
1077
1078public event PropertyChangedEventHandler PropertyChanged;
1079
1080public void OnPropertyChanged(String name)
1081{
1082        EventsHelper.PropertyChanged(PropertyChanged, this, new PropertyChangedEventArgs(name));
1083}
1084\end{lstlisting}
1085To use the ''PropertyChangedEventHandler'' you have to include the namespace ''System.ComponentModel''.\\
1086Our whole included namespaces looks now like this:
1087\begin{lstlisting}
1088using System.Collections.Generic;
1089using System.Text;
1090using System.ComponentModel;
1091using System.Windows.Control;
1092
1093using Cryptool.PluginBase;
1094using Cryptool.PluginBase.Cryptography;
1095using Cryptool.PluginBase.IO;
1096using Cryptool.PluginBase.Miscellaneous;
1097\end{lstlisting}
1098\section{Complete the actual code for the class Caesar}\label{sec:CompleteTheActualCodeForTheClassCaesar}
1099Up to now, the plugin is ready for the CrypTool base application to be accepted and been shown correctly in the CrypTool menu. What we need now, is the implementation of the actual algorithm in the function ''Execute()'' which is up to you as the plugin developer. CrypTool will always call first the Execute() function.If you place the whole algorithm in this function or split in other as needed is also up to you.
1100
1101We decided to split our algorithm encryption and decryption in two separate functions, which finally call the function ProcessCaesar.
1102
1103Let us demonstrate the Execute() function, too:
1104\begin{lstlisting}
1105private void ProcessCaesar(CaesarMode mode)
1106{
1107        CaesarSettings cfg = (CaesarSettings)this.settings;
1108        StringBuilder output = new StringBuilder('''');
1109        string alphabet = cfg.AlphabetSymbols;
1110
1111  // in case we want don't consider case in the alphabet, we use only capital letters, hence transform
1112        // the whole alphabet to uppercase
1113        if (!cfg.CaseSensitiveAlphabet)
1114        {
1115                alphabet = cfg.AlphabetSymbols.ToUpper(); ;
1116        }
1117
1118        if (inputString != null)
1119        {
1120                for (int i = 0; i < inputString.Length; i++)
1121                {
1122                        // get plaintext char which is currently processed
1123                        char currentchar = inputString[i];
1124
1125                        // remember if it is upper case (otherwise lowercase is assumed)
1126                        bool uppercase = char.IsUpper(currentchar);
1127
1128                        // get the position of the plaintext character in the alphabet
1129                        int ppos = 0;
1130                        if (cfg.CaseSensitiveAlphabet)
1131                        {
1132                                ppos = alphabet.IndexOf(currentchar);
1133                        }
1134                        else
1135                        {
1136                                ppos = alphabet.IndexOf(char.ToUpper(currentchar));
1137                        }
1138
1139                        if (ppos >= 0)
1140                        {
1141                                // we found the plaintext character in the alphabet, hence we do the shifting
1142                                int cpos = 0; ;
1143                                switch (mode)
1144                                {
1145                                        case CaesarMode.encrypt:
1146                                                cpos = (ppos + cfg.ShiftKey) % alphabet.Length;
1147                                                break;
1148                                        case CaesarMode.decrypt:
1149                                                cpos = (ppos - cfg.ShiftKey + alphabet.Length) % alphabet.Length;
1150                                                break;
1151                                }
1152
1153                                // we have the position of the ciphertext character, hence just output it in the correct case
1154                                if (cfg.CaseSensitiveAlphabet)
1155                                {
1156                                        output.Append(alphabet[cpos]);
1157                                }
1158                                else
1159                                {
1160                                        if (uppercase)
1161                                        {
1162                                                output.Append(char.ToUpper(alphabet[cpos]));
1163                                        }
1164                                        else
1165                                        {
1166                                                output.Append(char.ToLower(alphabet[cpos]));
1167                                        }
1168                                }
1169                        }
1170                        else
1171                        {
1172                                // the plaintext character was not found in the alphabet, hence proceed with handling unknown characters
1173                                switch ((CaesarSettings.UnknownSymbolHandlingMode)cfg.UnknownSymbolHandling)
1174                                {
1175                                        case CaesarSettings.UnknownSymbolHandlingMode.Ignore:
1176                                                output.Append(inputString[i]);
1177                                                break;
1178                                        case CaesarSettings.UnknownSymbolHandlingMode.Replace:
1179                                                output.Append('?');
1180                                                break;
1181                                }
1182                        }
1183
1184                        //show the progress
1185                        if (OnPluginProgressChanged != null)
1186                        {
1187                                OnPluginProgressChanged(this, new PluginProgressEventArgs(i, inputString.Length - 1));
1188                        }
1189                }
1190                outputString = output.ToString();
1191                OnPropertyChanged(''OutputString'');
1192                OnPropertyChanged(''OutputData'');
1193        }
1194}
1195
1196public void Encrypt()
1197{
1198        ProcessCaesar(CaesarMode.encrypt);
1199}
1200
1201public void Decrypt()
1202{
1203        ProcessCaesar(CaesarMode.decrypt);
1204}
1205
1206public void Execute()
1207{
1208        switch (settings.Action)
1209        {
1210                case 0:
1211                        Caesar_LogMessage(''encrypting'', NotificationLevel.Debug);
1212                        Encrypt();
1213                        break;
1214                case 1:
1215                        Decrypt();
1216                        break;
1217                default:
1218        break;
1219        }
1220}
1221\end{lstlisting}
1222It is important to make sure that all changes of output properties will be announced to the CrypTool environment. In this example this happens by calling the setter of OutputData which in turn calls ''OnPropertyChanged'' for both output properties ''OutputData'' and ''OutputDataStream''. Instead of calling the property's setter you can as well call ''OnPropertyChanged'' directly within the ''Execute()'' method.\clearpage
1223Certainly you have seen the unknown method ''ProgressChanged'' which you can use to show the current algorithm process as a progress on the plugin icon.
1224To use this method you also have to declare this method to afford a successful compilation:
1225\begin{lstlisting}
1226public event PluginProgressChangedEventHandler OnPluginProgressChanged;
1227private void ProgressChanged(double value, double max)
1228{
1229        EventsHelper.ProgressChanged(OnPluginProgressChanged, this, new PluginProgressEventArgs(value, max));
1230}
1231\end{lstlisting}
1232\section{Perform a clean dispose}\label{sec:PerformACleanDispose}
1233Be sure you have closed and cleaned all your streams after execution and when CrypTool decides to dispose the plugin instance. Though not required, we run the dispose code before execution as well:
1234\begin{lstlisting}
1235public void Dispose()
1236{
1237        foreach(CryptoolStream stream in listCryptoolStreamOut)
1238        {
1239                stream.Close();
1240        }
1241        listCryptoolStreamOut.Clear();
1242}
1243
1244public void PostExecution()
1245{
1246        Dispose();
1247}
1248
1249public void PreExecution()
1250{
1251        Dispose();
1252}
1253\end{lstlisting}\clearpage
1254\section{Finish implementation}\label{sec:FinishImplementation}
1255When adding plugin instances to the CrypTool workspace, CrypTool checks whether the plugin runs without any exception. If any IPlugin method throws an exception, CrypTool will show an error and prohibit using the plugin. Therefore we have to remove the ''NotImplementedException'' from the methods ''Initialize()'', ''Pause()'' and ''Stop()''. In our example it's sufficient to provide empty implementations.
1256\begin{lstlisting}
1257public void Initialize()
1258{
1259}
1260
1261public void Pause()
1262{
1263}
1264
1265public void Stop()
1266{
1267}
1268\end{lstlisting}
1269The methods ''Presentation()'' and ''QuickWatchPresentation()'' can be used if a plugin developer wants to provide an own visualization of the plugin algorithm which will be shown in CrypTool. Take a look at the PRESENT plugin to see how a custom visualization can be realized. For our Caesar example we don't want to implement a custom visualization, therefore we return ''null'':
1270\begin{lstlisting}
1271public UserControl Presentation
1272{
1273        get { return null; }
1274}
1275
1276public UserControl QuickWatchPresentation
1277{
1278        get { return null; }
1279}
1280\end{lstlisting}
1281Your plugin should compile without errors at this point.\clearpage
1282
1283\section{Import the plugin to CrypTool and test it}\label{sec:ImportThePluginToCryptoolAndTestIt}
1284After you have built the plugin, you need to move the newly created plugin DLL to a location, where CrypTool can find it. To do this, there are the following ways:
1285\begin{itemize}
1286        \item Copy your plugin DLL file in the folder ''CrypPlugins'' which has to be in the same folder as the CrypTool executable, called ''CrypWin.exe''. If necessary, create the folder ''CrypPlugins''.
1287\begin{figure}[h]
1288        \centering
1289                \includegraphics{figures/copy_dll_global_storage.jpg}
1290        \caption{Copy plugin to global storage}
1291        \label{fig:copy_dll_global_storage}
1292\end{figure}
1293
1294This folder is called ''Global storage'' in the CrypTool architecture. Changes in this folder will take effect for all users on a multi user Windows. Finally restart CrypTool.\clearpage
1295\begin{figure}[h]
1296        \centering
1297                \includegraphics{figures/global_storage.jpg}
1298        \caption{Plugins global storage}
1299        \label{fig:global_storage}
1300\end{figure}
1301
1302        \item Copy your plugin DLL file in the folder ''CrypPlugins'' which is located in your home path in the folder ''ApplicationData'' and restart CrypTool.  This home folder path is called ''Custom storage'' in the CrypTool architecture. Changes in this folder will only take effect for current user.  On a German Windows XP the home folder path could look like:
1303''C:\textbackslash Dokumente und Einstellungen\textbackslash $<$User$>$\textbackslash Anwendungsdaten\textbackslash CrypPlugins'' and in Vista/Windows7 the path will look like ''C:\textbackslash Users\textbackslash $<$user$>$\textbackslash Application Data\textbackslash CrypPlugins''.\clearpage
1304\begin{figure}[h]
1305        \centering
1306                \includegraphics[width=1.00\textwidth]{figures/custom_storage.jpg}
1307        \caption{Plugins custom storage}
1308        \label{fig:custom_storage}
1309\end{figure}
1310        \item You can also import new plugins directly from the CrypTool interface. Just execute CrypWin.exe and select the ''Download Plugins'' button. An ''Open File Dialog'' will open and ask where the new plugin is located. After selecting the new plugin, CrypTool will automatically import the new plugin in the custom storage folder. With this option you will not have to restart CrypTool. All according menu entries will be updated automatically.
1311Notice, that this plugin importing function only accepts \textbf{signed} plugins.
1312
1313\textit{\small Note: This option is a temporary solution for importing new plugins. In the future this will be done online by a web service.}\clearpage
1314
1315        \item Use post-build in your project properties to copy the DLL automatically after building it in Visual Studio with other plugins. Right-click on your plugin project and select ''Properties'':
1316\begin{figure}[h]
1317        \centering
1318                \includegraphics{figures/solution_properties.JPG}
1319        \caption{Solution Properties}
1320        \label{fig:solution_properties}
1321\end{figure}\clearpage
1322Select ''Build Events'':
1323\begin{figure}[h]
1324        \centering
1325                \includegraphics{figures/post_build.JPG}
1326        \caption{Build Events}
1327        \label{fig:post_build}
1328\end{figure}
1329
1330Enter the following text snippet into ''Post-build event command line'':\\\\
1331cd ''\$(ProjectDir)''\\
1332cd ..\textbackslash ..\textbackslash CrypWin\$(OutDir)\\
1333if not exist ''./CrypPlugins'' mkdir ''./CrypPlugins''\\
1334del /F /S /Q /s /q ''\fcolorbox{yellow}{yellow}{Caesar}*.*''\\
1335copy ''\$(TargetDir)\fcolorbox{yellow}{yellow}{Caesar}*.*'' ''./CrypPlugins''\\\\
1336You need to adapt the yellow marked field to your actual project name.
1337\end{itemize}
1338
1339
1340\section{Source code and source template}\label{sec:SourceCodeAndSourceTemplate}
1341Here you can download the whole source code which was presented in this ''Howto'' as a Visual Studio \textbf{solution}:\\\\
1342\textit{username: anonymous\\
1343password: not required\\}
1344\htmladdnormallink{https://www.cryptool.org/svn/CrypTool2/trunk/CrypPlugins/Caesar/}{https://www.cryptool.org/svn/CrypTool2/trunk/CrypPlugins/Caesar/}\\\\
1345%\textit{\small Note: You should commit your sources to our subversion so often you can. This will ensure your interoperability for further development.}\\\\
1346Here you can download the Visual Studio plugin \textbf{template} to begin with the development of a new CrypTool plugin:\\\\
1347\htmladdnormallink{http://cryptool2.vs.uni-due.de/downloads/template/encryptionplugin.zip}{http://cryptool2.vs.uni-due.de/downloads/template/encryptionplugin.zip}\clearpage
1348\section{Provide a workflow file of your plugin}\label{ProvideAWorkflowFileOfYourPlugin}
1349Every plugin developer should provide a workflow file which shows his algorithm working in CrypTool2. You will automatically create a workflow file by saving your project which was created on CrypTool2 work space. Here is an example how a workflow could look like:
1350\begin{figure}[h]
1351        \centering
1352                \includegraphics{figures/sample.jpg}
1353        \caption{Plugin sample}
1354        \label{fig:sample}
1355\end{figure}
Note: See TracBrowser for help on using the repository browser.