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

Last change on this file since 1625 was 1625, checked in by Matthäus Wander, 11 years ago

Plugin HowTo:

  • prepared part 2 to rely on the plugin template
  • removed no longer needed sections
File size: 51.6 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 plugin. We assume, you have retrieved the CrypTool 2 source code from the SVN repository, have set up Visual Studio 2010 or Visual C\# 2010 Express to build CrypTool 2, and you have placed the template at the right place.
4
5\section{Downloading the example}
6\label{sec:DownloadingTheExample}
7
8We will use the \textbf{Caesar cipher} (also known as the \textbf{shift cipher}) as an example throughout this chapter. If you did not to download the entire CrypTool 2 source code as described in Section \ref{CheckingOutTheSources}, you can still get a copy of the source code for the Caesar algorithm referenced throughout this guide from the following location:\\\\
9\textit{username: anonymous\\
10password:} (not required)\\
11\url{https://www.cryptool.org/svn/CrypTool2/trunk/CrypPlugins/Caesar/}
12
13\section{Creating a new project}
14\label{sec:CreatingANewProject}
15
16%To begin, open Visual Studio, go to the menu bar and select \textit{File~$\rightarrow$ New $\rightarrow$ Project\ldots }. The following window will appear:
17
18XXX: update screenshot
19
20XXX: right click in solution explorer on CrypPlugins (Express: on solution), select Add, New Project
21
22XXX: select CrypTool 2 Plugin as project type
23
24XXX: enter some plugin name
25
26XXX: enter CrypPlugins as location (!!!)
27
28\begin{figure}[h!]
29        \centering
30                \includegraphics[width=1.00\textwidth]{figures/vs_create_new_project.jpg}
31        \caption{Creating a new Visual Studio project.}
32        \label{fig:vs_create_new_project}
33\end{figure}
34\clearpage
35
36%Select \textbf{\textit{.NET-Framework 3.5}} as the target framework. Then choose \textit{Class Library} as the default template, as this will build the project for your plugin as a DLL file. Give the project a unique and meaningful name (such as \textit{Caesar} in our case), and choose a location to save it to. Select the subdirectory \textit{CrypPlugins} from your SVN trunk as the location. Finally, confirm by pressing the \textit{OK} button. Note that creating a new project in this manner also creates a new solution into which the project is placed. At this point, your Visual Studio solution should look like this:
37
38\begin{figure}[h!]
39        \centering
40                \includegraphics[width=1.00\textwidth]{figures/solution_start_up.jpg}
41        \caption{A newly created solution and project.}
42        \label{fig:solution_start_up}
43\end{figure}
44\clearpage
45
46XXX: rename files in solution explorer to something meaningful (ExamplePluginCT2.cs, ExamplePluginCT2Settings.cs)
47
48XXX: rename class ExamplePluginCT2Settings to something meaningful (right-click, refactor/rename).
49
50%In our case, this class has to inherit from \textit{IEncryption} because it will be an encryption plugin. If it was instead a hash plugin, this class should inherit from \textit{IHash}. The second class will be used to store setting information for the plugin, and thus we will name ours \textit{CaesarSettings}. It will need to inherit from \textit{ISettings}.
51
52%When starting a new project, Visual Studio automatically creates a class named \textit{Class1.cs}. Since this is a rather non-descriptive name, we will change it. In our example, it will be \textit{Caesar.cs}.
53
54%Then right-click on the project item (in our case, \textit{Caesar}) and select \textit{Add $\rightarrow$ Class\ldots }:
55
56%The settings class will store 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.
57\clearpage
58
59\noindent Below is an example of what a completed TaskPane for the existing Caesar plugin in CrypTool 2 looks like:
60
61\begin{figure}[h!]
62        \centering
63                \includegraphics{figures/task_pane.jpg}
64        \caption{The completed TaskPane for the existing Caesar plugin.}
65        \label{fig:task_pane}
66\end{figure}
67\clearpage
68
69\subsection{Adding the namespaces and inheritance sources for the Caesar class}
70\label{sec:AddingTheNamespacesAndInheritanceSourcesForTheCaesarClass}
71
72XXX: your plugin main class should inherit from some interface from the following CrypPluginBase interfaces
73
74XXX: CT2 determines by your chosen interface in which algorithm category your plugin will be shown (encryption, hash, analysis etc.)
75
76Open the \textit{Caesar.cs} file by double clicking on it in the Solution Explorer. To include the necessary namespaces in the class header, use the \texttt{using} statement followed by the name of the desired namespace. The CrypTool 2 API provides the following namespaces:
77
78\begin{itemize}
79        \item \textit{Cryptool.PluginBase} --- contains interfaces such as \textit{IPlugin}, \textit{IHash}, and \textit{ISettings}, as well as attributes, enumerations, delegates and extensions.
80        \item \textit{Cryptool.PluginBase.Analysis} --- contains interfaces for cryptanalysis plugins (such as \textit{Stream Comparator}).
81        \item \textit{Cryptool.PluginBase.Control} --- contains global interfaces for the \textit{IControl} feature for defining custom controls.
82        \item \textit{Cryptool.PluginBase.Cryptography} --- contains interfaces for encryption and hash algorithms such as AES, DES and MD5.
83        \item \textit{Cryptool.PluginBase.Editor} --- contains interfaces for editors that can be implemented in CrypTool 2, such as the default editor.
84        \item \textit{Cryptool.PluginBase.Generator} --- contains interfaces for generators, including the random input generator.
85        \item \textit{Cryptool.PluginBase.IO} --- contains interfaces for input, output and the \textit{CryptoolStream}.
86        \item \textit{Cryptool.PluginBase.Miscellaneous} --- contains assorted helper classes, including \textit{GuiLogMessage} and \textit{PropertyChanged}.
87        \item \textit{Cryptool.PluginBase.Resources} --- used only by CrypWin and the editor; not necessary for plugin development.
88        \item \textit{Cryptool.PluginBase.Tool} --- contains an interface for all external tools implemented by CrypTool~2 that do not entirely support the CrypTool 2 API.
89        \item \textit{Cryptool.PluginBase.Validation} --- contains interfaces for validation methods, including regular expressions.
90\end{itemize}
91
92\noindent In our example, the Caesar algorithm necessitates the inclusion of the following namespaces:
93
94\begin{itemize}
95        \item \textit{Cryptool.PluginBase} --- to implement \textit{ISettings} in the CaesarSettings class.
96        \item \textit{Cryptool.PluginBase.Cryptography} --- to implement \textit{IEncryption} in the Caesar class.
97        \item \textit{Cryptool.PluginBase.IO} --- to use CryptoolStream for data input and output.
98        \item \textit{Cryptool.PluginBase.Miscellaneous} --- to use the CrypTool event handler.
99\end{itemize}
100
101\clearpage
102
103\subsection{Adding controls to the CaesarSettings class}
104\label{sec:AddingControlsToTheCaesarSettingsClass}
105
106The settings class is used to populate the TaskPane in the CrypTool 2 application so that the user can modify the plugin settings at will. Thus we will need to implement some controls, such as buttons and text boxes, to allow for the necessary interaction. If you will be implementing an algorithm that does not have any user-defined settings (i.e.\ a hash function), then this class can be left mostly empty. The following code demonstrates the modifications necessary to create the backend for the TaskPane for our Caesar algorithm. You can also look at the source code of other CrypTool 2 plugins for examples of how to create the TaskPane backend.\\
107
108\begin{lstlisting}
109using System;
110using System.ComponentModel;
111using System.Windows;
112using System.Windows.Controls;
113
114using Cryptool.PluginBase;
115
116namespace Cryptool.Caesar
117{
118    public class CaesarSettings : ISettings
119    {
120        #region Public Caesar specific interface
121
122        /// <summary>
123        /// This delegate is ued to send log messages from
124        /// the settings class to the Caesar plugin.
125        /// </summary>
126        public delegate void CaesarLogMessage(string msg, NotificationLevel loglevel);
127
128        /// <summary>
129        /// An enumeration for the different modes of handling
130        /// unknown characters.
131        /// </summary>
132        public enum UnknownSymbolHandlingMode { Ignore = 0, Remove = 1, Replace = 2 };
133
134        /// <summary>
135        /// Fires when a new status message was sent.
136        /// </summary>
137        public event CaesarLogMessage LogMessage;
138
139        public delegate void CaesarReExecute();
140
141        public event CaesarReExecute ReExecute;
142
143        /// <summary>
144        /// Retrieves or sets the current shift value (i.e. the key).
145        /// </summary>
146        [PropertySaveOrder(0)]
147        public int ShiftKey
148        {
149            get { return shiftValue; }
150            set
151            {
152                setKeyByValue(value);
153            }
154        }
155
156        /// <summary>
157        /// Retrieves the current setting of whether or not the
158        /// alphabet should be treated as case-sensitive.
159        /// </summary>
160        [PropertySaveOrder(1)]
161        public bool CaseSensitiveAlphabet
162        {
163            get
164            {
165                if (caseSensitiveAlphabet == 0)
166                {   return false;   }
167                else
168                {   return true;    }
169            }
170            set {} // this setting is readonly, but we must include
171                   // some form of set method to prevent problems.
172        }
173
174        /// <summary>
175        /// Returns true if any settings have been changed.
176        /// This value should be set externally to false, i.e.
177        /// when a project is saved.
178        /// </summary>
179        [PropertySaveOrder(3)]
180        public bool HasChanges
181        {
182            get { return hasChanges; }
183            set { hasChanges = value; }
184        }
185
186        #endregion
187
188        #region Private variables
189        private bool hasChanges;
190        private int selectedAction = 0;
191        private string upperAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
192        private string lowerAlphabet = "abcdefghijklmnopqrstuvwxyz";
193        private string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
194        private char shiftChar = 'C';
195        private int shiftValue = 2;
196        private UnknownSymbolHandlingMode unknownSymbolHandling = UnknownSymbolHandlingMode.Ignore;
197        private int caseSensitiveAlphabet = 0; // 0 = case-insensitve, 1 = case-sensitive
198        private bool sensitivityEnabled = true;
199        #endregion
200
201        #region Private methods
202
203        private string removeEqualChars(string value)
204        {
205            int length = value.Length;
206
207            for (int i = 0; i < length; i++)
208            {
209                for (int j = i + 1; j < length; j++)
210                {
211                    if ((value[i] == value[j]) || (!CaseSensitiveAlphabet & (char.ToUpper(value[i]) == char.ToUpper(value[j]))))
212                    {
213                        LogMessage("Removing duplicate letter: \'" + value[j] + "\' from alphabet!", NotificationLevel.Warning);
214                        value = value.Remove(j,1);
215                        j--;
216                        length--;
217                    }
218                }
219            }
220
221            return value;
222        }
223
224        /// <summary>
225        /// Set the new shiftValue and the new shiftCharacter
226        /// to offset % alphabet.Length.
227        /// </summary>
228        private void setKeyByValue(int offset)
229        {
230            HasChanges = true;
231
232            // Make sure the shift value lies within the alphabet range.
233            offset = offset % alphabet.Length;
234
235            // Set the new shiftChar.
236            shiftChar = alphabet[offset];
237
238            // Set the new shiftValue.
239            shiftValue = offset;
240
241            // Announce this to the settings pane.
242            OnPropertyChanged("ShiftValue");
243            OnPropertyChanged("ShiftChar");
244
245            // Print some info in the log.
246            LogMessage("Accepted new shift value " + offset + "! (Adjusted shift character to \'" + shiftChar + "\')", NotificationLevel.Info);
247        }
248
249        private void setKeyByCharacter(string value)
250        {
251            try
252            {
253                int offset;
254                if (this.CaseSensitiveAlphabet)
255                {
256                    offset = alphabet.IndexOf(value[0]);
257                }
258                else
259                {
260                    offset = alphabet.ToUpper().IndexOf(char.ToUpper(value[0]));
261                }
262
263                if (offset >= 0)
264                {
265                    HasChanges = true;
266                    shiftValue = offset;
267                    shiftChar = alphabet[shiftValue];
268                    LogMessage("Accepted new shift character \'" + shiftChar + "\'! (Adjusted shift value to " + shiftValue + ")", NotificationLevel.Info);
269                    OnPropertyChanged("ShiftValue");
270                    OnPropertyChanged("ShiftChar");
271                }
272                else
273                {
274                    LogMessage("Bad input \"" + value + "\"! (Character not in alphabet!) Reverting to " + shiftChar.ToString() + "!", NotificationLevel.Error);
275                }
276            }
277            catch (Exception e)
278            {
279                LogMessage("Bad input \"" + value + "\"! (" + e.Message + ") Reverting to " + shiftChar.ToString() + "!", NotificationLevel.Error);
280            }
281        }
282
283        #endregion
284
285        #region Algorithm settings properties (visible in the Settings pane)
286
287        [PropertySaveOrder(4)]
288        [ContextMenu("Action", "Select the algorithm action", 1, DisplayLevel.Beginner, ContextMenuControlType.ComboBox, new int[] { 1, 2 }, "Encrypt", "Decrypt")]
289        [TaskPane("Action", "setAlgorithmActionDescription", null, 1, true, DisplayLevel.Beginner, ControlType.ComboBox, new string[] { "Encrypt", "Decrypt" })]
290        public int Action
291        {
292            get
293            {
294                return this.selectedAction;
295            }
296            set
297            {
298                if(value != selectedAction)
299                {
300                        HasChanges = true;
301                        this.selectedAction = value;
302                    OnPropertyChanged("Action");
303                }
304                if(ReExecute != null)
305                {       ReExecute();    }
306            }
307        }
308
309        [PropertySaveOrder(5)]
310        [TaskPane("Key as integer", "Enter the number of letters to shift. For example, 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)]
311        public int ShiftValue
312        {
313            get { return shiftValue; }
314            set
315            {
316                setKeyByValue(value);
317                if (ReExecute != null)
318                {       ReExecute();    }
319            }
320        }
321
322        [PropertySaveOrder(6)]
323        [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}")]
324        public string ShiftChar
325        {
326            get { return this.shiftChar.ToString(); }
327            set
328            {
329                setKeyByCharacter(value);
330                if (ReExecute != null)
331                        {   ReExecute();    }
332            }
333        }
334
335        [PropertySaveOrder(7)]
336        [ContextMenu("Unknown symbol handling", "What should be done with characters encountered in the input which are not in the alphabet?", 4, DisplayLevel.Expert, ContextMenuControlType.ComboBox, null, new string[] { "Ignore (leave unmodified)", "Remove", "Replace with \'?\'" })]
337        [TaskPane("Unknown symbol handling", "What should be done with characters encountered in the input which are not in the alphabet?", null, 4, true, DisplayLevel.Expert, ControlType.ComboBox, new string[] { "Ignore (leave unmodified)", "Remove", "Replace with \'?\'" })]
338        public int UnknownSymbolHandling
339        {
340            get { return (int)this.unknownSymbolHandling; }
341            set
342            {
343                if((UnknownSymbolHandlingMode)value != unknownSymbolHandling)
344                {
345                        HasChanges = true;
346                        this.unknownSymbolHandling = (UnknownSymbolHandlingMode)value;
347                    OnPropertyChanged("UnknownSymbolHandling");
348                                }
349                if (ReExecute != null)
350                {       ReExecute();    }
351            }
352        }
353
354        [SettingsFormat(0, "Normal", "Normal", "Black", "White", Orientation.Vertical)]
355        [PropertySaveOrder(9)]
356        [TaskPane("Alphabet", "This is the alphabet currently in use.", null, 6, true, DisplayLevel.Expert, ControlType.TextBox, "")]
357        public string AlphabetSymbols
358        {
359          get { return this.alphabet; }
360          set
361          {
362            string a = removeEqualChars(value);
363            if (a.Length == 0) // cannot accept empty alphabets
364            {
365              LogMessage("Ignoring empty alphabet from user! Using previous alphabet instead: \" + alphabet + "\" (" + alphabet.Length.ToString() + " Symbols)", NotificationLevel.Info);
366            }
367            else if (!alphabet.Equals(a))
368            {
369              HasChanges = true;
370              this.alphabet = a;
371              setKeyByValue(shiftValue); // reevaluate if the shiftvalue is still within the range
372              LogMessage("Accepted new alphabet from user: \"" + alphabet + "\" (" + alphabet.Length.ToString() + " Symbols)", NotificationLevel.Info);
373              OnPropertyChanged("AlphabetSymbols");
374
375              if (ReExecute != null)
376              { ReExecute();    }
377            }
378          }
379        }
380
381        /// <summary>
382        /// Visible setting how to deal with alphabet case.
383        /// 0 = case-insentive, 1 = case-sensitive
384        /// </summary>
385        [PropertySaveOrder(8)]
386        [ContextMenu("Alphabet case sensitivity", "Should upper and lower case be treated as the same (so that 'a' = 'A')?", 7, DisplayLevel.Expert, ContextMenuControlType.ComboBox, null, new string[] { "Case insensitive", "Case sensitive" })]
387        [TaskPane("Alphabet case sensitivity", "Should upper and lower case be treated as the same (so that 'a' = 'A')?", null, 7, true, DisplayLevel.Expert, ControlType.ComboBox, new string[] { "Case insensitive", "Case sensitive" })]
388        public int AlphabetCase
389        {
390            get { return this.caseSensitiveAlphabet; }
391            set
392            {
393                if (value != caseSensitiveAlphabet)
394                {       HasChanges = true;      }
395                this.caseSensitiveAlphabet = value;
396                if (value == 0)
397                {
398                    if (alphabet == (upperAlphabet + lowerAlphabet))
399                    {
400                        alphabet = upperAlphabet;
401                        LogMessage("Changing alphabet to: \"" + alphabet + "\" (" + alphabet.Length.ToString() + " Symbols)", NotificationLevel.Info);
402                        OnPropertyChanged("AlphabetSymbols");
403                        // reset the key (shiftvalue/shiftChar)
404                        // to be in the range of the new alphabet.
405                        setKeyByValue(shiftValue);
406                    }
407                }
408                else
409                {
410                    if (alphabet == upperAlphabet)
411                    {
412                        alphabet = upperAlphabet + lowerAlphabet;
413                        LogMessage("Changing alphabet to: \"" + alphabet + "\" (" + alphabet.Length.ToString() + " Symbols)", NotificationLevel.Info);
414                        OnPropertyChanged("AlphabetSymbols");
415                    }
416                }
417
418                // Remove equal characters from the current alphabet.
419                string a = alphabet;
420                alphabet = removeEqualChars(alphabet);
421                if (a != alphabet)
422                {
423                    OnPropertyChanged("AlphabetSymbols");
424                    LogMessage("Changing alphabet to: \"" + alphabet + "\" (" + alphabet.Length.ToString() + " Symbols)", NotificationLevel.Info);
425                }
426                OnPropertyChanged("AlphabetCase");
427                if (ReExecute != null)
428                {       ReExecute();    }
429            }
430        }
431
432        #endregion
433
434        #region INotifyPropertyChanged Members
435
436        public event PropertyChangedEventHandler PropertyChanged;
437
438        protected void OnPropertyChanged(string name)
439        {
440          if (PropertyChanged != null)
441          {
442            PropertyChanged(this, new PropertyChangedEventArgs(name));
443          }
444        }
445
446        #endregion
447
448        #region TaskPaneAttributeChanged (Sample)
449        /// <summary>
450        /// This event is here merely as a sample.
451        /// </summary>
452        public event TaskPaneAttributeChangedHandler TaskPaneAttributeChanged;
453
454        [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)]
455        public void EnableDisableSesitivity()
456        {
457          if (TaskPaneAttributeChanged!= null)
458          {
459            sensitivityEnabled = !sensitivityEnabled;
460            if (sensitivityEnabled)
461            {
462              TaskPaneAttributeChanged(this, new TaskPaneAttributeChangedEventArgs(new TaskPaneAttribteContainer("AlphabetCase", Visibility.Visible)));
463            }
464            else
465            {
466              TaskPaneAttributeChanged(this, new TaskPaneAttributeChangedEventArgs(new TaskPaneAttribteContainer("AlphabetCase", Visibility.Collapsed)));
467            }
468          }
469        }
470        #endregion TaskPaneAttributeChanged (Sample)
471    }
472}
473\end{lstlisting}
474\clearpage
475
476\section{Adding an icon to the Caesar class}
477\label{sec:AddingAnIconToTheCaesarClass}
478
479Before we go back to the code of the Caesar class, we have to add an icon to our project, which will be shown in the CrypTool 2 \textbf{ribbon bar} and \textbf{navigation pane}. As there is currently no default, it is mandatory to add an icon. (It is planned to include a default icon in future versions.)
480
481For testing purposes you can just create a simple black and white PNG image with any graphics editing program, such as MS Paint or Paint.NET. The proper image size is 40x40 pixels, but since the image will be rescaled if necessary, any size is technically acceptable.
482
483Once you have saved your icon, you should add it directly to the project or to a subdirectory with it. In the project solution, we created a new folder named \textit{Images}. This can be done by right-clicking on the project item (\textit{Caesar} in our example) and selecting \textit{Add $\rightarrow$ New Folder}. The icon can be added to this folder (or to the project directly, or to any other subdirectory) by right-clicking on the folder and selecting \textit{Add $\rightarrow$ Existing Item}.
484
485\begin{figure}[h!]
486        \centering
487                \includegraphics{figures/add_existing_item.jpg}
488        \caption{Adding an existing item.}
489        \label{fig:add_existing_item}
490\end{figure}
491\clearpage
492
493A new window will then appear. Select \textit{Image Files} as the file type and select your newly-created icon for your plugin.
494
495\begin{figure}[h!]
496        \centering
497                \includegraphics{figures/choose_icon.jpg}
498        \caption{Selecting the image file.}
499        \label{fig:choose_icon}
500\end{figure}
501\clearpage
502
503Finally, we must set the icon as a \textit{Resource} to avoid including the icon as a separate file. Right-click on the icon and select \textit{Properties} as seen below.
504
505\begin{figure}[h!]
506        \centering
507                \includegraphics{figures/icon_properties.jpg}
508        \caption{Selecting the image properties.}
509        \label{fig:icon_properties}
510\end{figure}
511
512In the \textit{Properties} panel, set the \textit{Build Action} to \textit{Resource}.
513
514\begin{figure}[h!]
515        \centering
516                \includegraphics{figures/icon_build_action.jpg}
517        \caption{Selecting the icon's build action.}
518        \label{fig:icon_build_action}
519\end{figure}
520\clearpage
521
522\section{Defining the attributes of the Caesar class}
523\label{sec:DefiningTheAttributesOfTheCaesarClass}
524
525Now let's go back to the code of the Caesar class (the \textit{Caesar.cs} file in our example). The first thing we will do is define the attributes of our class. These attributes are used to provide additional information for the CrypTool 2 environment. If they are not properly defined, your plugin won't show up in the application user interface, even if everything else is implemented correctly.
526
527Attributes are used for declarative programming and provide metadata that can be added to the existing .NET metadata. CrypTool 2 provides a set of custom attributes that are used to mark the different parts of your plugin.
528
529These attributes can be defined anywhere within the \textit{Cryptool.Caesar} namespace, but customarily they are defined right before the class declaration.
530
531\subsection{The \protect\textit{[Author]} attribute}
532\label{sec:TheAuthorAttribute}
533
534The \textit{[Author]} attribute is optional, meaning that we are not required to define it. The attribute can be used to provide additional information about the plugin developer (or developers, as the case may be). This information will appear in the TaskPane, as for example in Figure \ref{fig:task_pane}. We will define the attribute to demonstrate how it should look in case you want to use it in your plugin.
535
536\begin{figure}[h!]
537        \centering
538                \includegraphics[width=.90\textwidth]{figures/attribute_author.jpg}
539        \caption{The defintion for the \textit{[Author]} attribute.}
540        \label{fig:attribute_author}
541\end{figure}
542
543As can be seen above, the author attribute takes four elements of type string. These elements are:
544
545\begin{itemize}
546        \item \textit{Author} --- the name of the plugin developer.
547        \item \textit{Email} --- the email address of the plugin developer, should he or she wish to be available for contact.
548        \item \textit{Institute} --- the organization, company or university with which the developer is affiliated.
549        \item \textit{URL} --- the website of the developer or of his or her institution.
550\end{itemize}
551
552All of these elements are optional; the developer can choose what information will be published. Unused elements should be set to \texttt{null} or an empty string.
553\clearpage
554
555\subsection{The \protect\textit{[PluginInfo]} attribute}
556\label{sec:ThePluginInfoAttribute}
557
558The second attribute, \textit{[PluginInfo]}, provides necessary information about the plugin, and is therefore mandatory. The information defined in this attribute appears in the caption and tool tip window. The attribute is defined as follows:
559
560\begin{figure}[h]
561        \centering
562                \includegraphics[width=1.00\textwidth]{figures/attribute_plugininfo.jpg}
563        \caption{The defintion for the \textit{[PluginInfo]} attribute.}
564        \label{fig:attribute_plugininfo}
565\end{figure}
566
567\noindent This attribute has the following parameters:
568
569\begin{itemize}
570        \item \textit{Resource File} --- the relative path of the associated resource file (if the plugin makes use of one). These files are used primarily to provide multilingual support for the plugin, although this is currently a work in progress. This element is optional.
571        \item \textit{Startable} --- a flag that should be set to \texttt{true} only if the plugin is an input generator (i.e.\ if your plugin only has outputs and no inputs). In all other cases this should be set to \texttt{false}. This flag is important --- setting it incorrectly will result in unpredictable results. This element is mandatory.
572        \item \textit{Caption} --- the name of the plugin, or, if using a resource file, the name of the field in the file with the caption data. This element is mandatory.
573        \item \textit{ToolTip} --- a description of the plugin, or, if using a resource file, the name of the field in the resource file with the toolTip data. This element is optional.
574        \item \textit{DescriptionURL} --- the local path of the description file (e.g.\ XAML file). This element is optional.
575        \item \textit{Icons} --- an array of strings to define all the paths of the icons used in the plugin (i.e.\ the plugin icon described in Section \ref{sec:AddingAnIconToTheCaesarClass}). This element is mandatory.
576\end{itemize}
577
578\noindent Unused elements should be set to \texttt{null} or an empty string.
579
580There are a few limitations and bugs that still exist in the \textit{[PluginInfo]} attribute that will be resolved in a future version. First, it is possible to use the plugin without setting a caption, although this is not recommended, and future versions of the plugin will fail to load without a caption. Second, a zero-length toolTip string currently causes the toolTip to appear as an empty box in the application. Third, the toolTip and description do not currently support internationalization and localization. Since the precise formulation and functionality of this attribute is still being developed, it is recommended to view other plugins for examples.
581
582In our example, the \textit{resourceFile} parameter should be set to \textit{Cryptool.Caesar.Resource.res}. This file will be used to store the label and caption text to support multilingualism.
583
584The second parameter, \textit{startable}, should be set to \texttt{false}, because our encryption algorithm is not an input generator.
585
586The next two parameters are necessary to define the plugin's name and description. Since we are using a resource file, we should place here the names of the resource fields that contain the caption and toolTip. (We could also just write simple text strings instead of using outsourced references.)
587
588The \textit{DescriptionURL} element defines the location path of the description file. The parameter is composed in the format \textit{$<$assembly name$>$/$<$file name$>$} or, if you want to store your description files in a separate folder (as in our case), \textit{$<$assembly name$>$/$<$path$>$/$<$file name$>$}. The description file must be an XAML file. In our case, we shall create a folder named \textit{DetailedDescription} in which to store our XAML file with any necessary images. Our folder structure now looks as follows:
589
590\begin{figure}[h!]
591        \centering
592                \includegraphics[width=.30\textwidth]{figures/detailed_description.jpg}
593        \caption{The folder structure as seen in the Solution Explorer.}
594        \label{fig:attribute_plugininfo_icon_path}
595\end{figure}
596
597Once a detailed description has been written in the XAML file, it can be accessed in the CrypTool~2 application by right-clicking on the plugin icon in the workspace and selecting \textit{Show description}.
598
599\begin{figure}[h!]
600        \centering
601                \includegraphics[width=1.00\textwidth]{figures/xaml_description.jpg}
602        \caption{A detailed description provided through an XAML file.}
603        \label{fig:xaml_description}
604\end{figure}
605\clearpage
606
607The last parameter tells CrypTool 2 the names of the provided icons. This parameter is an array composed of strings in the format \textit{$<$assembly name$>$/$<$file name$>$} or \textit{$<$assembly name$>$/$<$path$>$/\linebreak $<$file~name$>$}.
608
609The first and most important icon is the plugin icon, which will be shown in CrypTool 2 in the ribbon bar and navigation pane. Once the icon has been added to the project as described in Section~\ref{sec:AddingAnIconToTheCaesarClass}, we must accordingly tell CrypTool 2 where to find the icon. This can be seen above in Figure \ref{fig:attribute_plugininfo}.
610
611If your plugin will use additional icons, you should define the paths to each of them by adding the path strings to the \textit{[PluginInfo]} attribute parameter list, each separated by a comma. We have added two further icons for the context menu in the CrypTool 2 workspace. (If you choose to add more icons, don't forget to add the icons to your solution.)
612
613\subsection{The \protect\textit{[EncryptionType]} attribute}
614\label{sec:TheEncryptionTypeAttribute}
615
616The third and last attribute, \textit{[EncryptionType]}, is needed to tell CrypTool 2 what type of plugin we are creating. CrypTool 2 uses this information to place the plugin in the correct group in the navigation pane and ribbon bar. In our example, since Caesar is a classical algorithm, we will define the attribute as follows:
617
618\begin{figure}[h]
619        \centering
620                \includegraphics[width=.90\textwidth]{figures/attribute_encryptiontype.jpg}
621        \caption{A defined \textit{[EncryptionType]} attribute.}
622        \label{fig:attribute_encryption_type}
623\end{figure}
624
625The possible values of the \textit{[EncryptionType]} attribute are as follows:
626
627\begin{itemize}
628        \item \textit{Asymmetric} --- for asymmetrical encryption algorithms, such as RSA.
629        \item \textit{SymmetricBlock} --- for block cipher algorithms, such as DES, AES and Twofish.
630        \item \textit{SymmetricStream} --- for stream cipher algorithms, such as RC4, Rabbit and SEAL.
631        \item \textit{Hybrid} --- for algorithms which are actually a combination of several algorithms, such as algorithms in which the data is encrypted symmetrically and the encryption key asymmetrically.
632        \item \textit{Classic} --- for classical encryption or hash algorithms, such as Caesar or MD5.
633\end{itemize}
634
635\section{Defining the private variables of the settings in the Caesar class}
636\label{sec:DefiningThePrivateVariablesOfTheSettingsInTheCaesarClass}
637
638The next step is to define some private variables that are needed for the settings, input, and output data. In our example, this will look like the following:
639
640\begin{lstlisting}
641public class Caesar : IEncryption
642{
643        #region Private variables
644        private CaesarSettings settings;
645        private string inputString;
646        private string outputString;
647        private enum CaesarMode { encrypt, decrypt };
648        private List<CryptoolStream> listCryptoolStreamsOut = new List<CryptoolStream>();
649        #endregion
650\end{lstlisting}
651
652\ \\ % ugly but functional
653If your algorithm deals with long strings of code, it is recommended to use the \textit{CryptoolStream} data type. This was designed for input and output between plugins and to handle large amounts of data. To use the native CrypTool stream type, include the namespace \textit{Cryptool.PluginBase.IO} with a \texttt{using} statement as explained in Section \ref{sec:AddingTheNamespacesAndInheritanceSourcesForTheCaesarClass}.
654
655Our example makes use of the following private variables:
656
657\begin{itemize}
658        \item \texttt{CaesarSettings settings} --- required to implement the IPlugin interface properly.
659        \item \texttt{string inputString} --- string from which to read the input data.
660        \item \texttt{string outputString} --- string to which to save the output data.
661        \item \texttt{enum CaesarMode} --- used to select either encryption or decryption.
662        \item \texttt{List$<$CryptoolStream$>$ listCryptoolStreamsOut} --- a list of all streams created by the plugin, which helps to perform a clean dispose.
663\end{itemize}
664
665\section{Implementing the interfaces in the Caesar class}
666\label{sec:ImplementingTheInterfacesInTheCaesarClass}
667
668\subsection{Connecting the settings class}
669\label{sec:ConnectingTheSettingsClass}
670
671The next major step is to write out our implementations of the interfaces. First we will add a constructor to our class. We will use this to create an instance of our settings class and a function to handle events:
672
673\begin{lstlisting}
674public Caesar()
675{
676        this.settings = new CaesarSettings();
677        this.settings.LogMessage += GuiLogMessage;
678}
679\end{lstlisting}
680
681\ \\
682\indent Secondly, we must implement the \textit{Settings} property declared in the interface. An outline of this property should have been automatically generated by implementing the interface (see Section \ref{sec:AddingInterfaceFunctionsToTheCaesarClass}); just edit it appropriately to communicate with your settings class as we have done here:
683
684\begin{lstlisting}
685public ISettings Settings
686{
687        get { return (ISettings)this.settings; }
688        set { this.settings = (CaesarSettings)value; }
689}
690\end{lstlisting}
691\clearpage
692
693\subsection{The input/output attributes}
694\label{sec:TheInputOutputAttributes}
695
696%\ \\
697\indent Next we will define five properties, each with an appropriate attribute, to be used for input and output. Th attributes are necessary to tell CrypTool 2 whether the properties are used for input or output and to provide the plugin with external data.
698
699The attribute that we will use for each proprerty is called \textit{[PropertyInfo]} and it consists of the following elements:
700
701\begin{itemize}
702        \item \textit{direction} --- defines whether this property is an input or output property, e.g.\ whether it reads input data or writes output data. The possible values are:
703        \begin{itemize}
704                \item \texttt{Direction.Input}
705                \item \texttt{Direction.Output}
706        \end{itemize}
707        \item \textit{caption} --- the caption for the property displayed over the input or output arrow of the icon after it has been placed in the editor; ``Input stream'' in the example below:
708       
709\begin{figure}[h!]
710        \centering
711                \includegraphics[width=.55\textwidth]{figures/property_caption.jpg}
712        \caption{A possible property caption and toolTip.}
713        \label{fig:property_caption}
714\end{figure}
715
716        \item \textit{toolTip} --- the toolTip for the property displayed over the input or output arrow of the icon after it has been placed in the editor; ``Input data to be hashed'' in the example above.
717        \item \textit{descriptionUrl} --- currently not used; fill it with \texttt{null} or an empty string.
718        \item \textit{mandatory} --- this flag determines whether an input must be attached by the user to use the plugin. If set to \texttt{true}, an input connection will be required or else the plugin will not be executed in the workflow chain. If set to \texttt{false}, connecting an input is optional. As this only applies to input properties, if the direction has been set to \texttt{Direction.Output}, this flag will be ignored.
719        \item \textit{hasDefaultValue} --- if this flag is set to \texttt{true}, CrypTool 2 will assume that the property has a default input value that does not require user input.
720        \item \textit{displayLevel} --- determines in which display levels your property will be shown in CrypTool~2. These are used to hide more advanced item from less-experienced users; a beginner using the corresponding display level will not see the properties marked as any other level, but a professional using the appropriate display level will have access to everything. These levels are as follows:
721       
722        \begin{itemize}
723                \item \texttt{DisplayLevel.Beginner}
724                \item \texttt{DisplayLevel.Experienced}
725                \item \texttt{DisplayLevel.Expert}
726                \item \texttt{DisplayLevel.Professional}
727        \end{itemize}
728\clearpage
729       
730        \item \textit{quickWatchFormat} --- determines how the content of the property will be shown in the quickwatch perspective. CrypTool 2 accepts the following quickwatch formats:
731       
732        \begin{itemize}
733                \item \texttt{QuickWatchFormat.Base64}
734                \item \texttt{QuickWatchFormat.Hex}
735                \item \texttt{QuickWatchFormat.None}
736                \item \texttt{QuickWatchFormat.Text}
737        \end{itemize}
738
739\begin{figure}[h]
740        \centering
741                \includegraphics{figures/quick_watch.jpg}
742        \caption{A quickwatch display in hexadecimal.}
743        \label{fig:quick_watch}
744\end{figure}
745       
746        \item \textit{quickWatchConversionMethod} --- this is used to indicate a conversion method; most plugins do not ned to convert their data and thus should use a \texttt{null} value here. The quickwatch function uses the default system encoding to display data, so if your data is in another format, such as UTF-16 or Windows-1250, you should provide here the name of a conversion method as string. The header for such a method should look something like the following:
747
748\begin{lstlisting}
749object YourMethodName(string PropertyNameToConvert)
750\end{lstlisting}
751
752\end{itemize}
753
754\subsection{Defining the input/output properties}
755\label{sec:DefiningTheInputOutputProperties}
756
757The first of the five properties that we will define is \textit{InputString}. This is used to provide our plugin with the data to be encrypted or decrypted:
758
759\begin{lstlisting}
760[PropertyInfo(Direction.InputData, "Text input", "Input a string to be processed by the Caesar cipher", "", true, false, DisplayLevel.Beginner, QuickWatchFormat.Text, null)]
761public string InputString
762{
763        get { return this.inputString; }
764        set
765  {
766                if (value != inputString)
767                {
768                        this.inputString = value;
769                        OnPropertyChanged("InputString");
770                }
771        }
772}
773\end{lstlisting}
774
775\ \\
776In the get method we simply return the value of the input data. The set method checks if the input value has changed, and, if so, sets the new input data and announces the change to the CrypTool 2 environment by calling the function \textit{OnPropertyChanged(\textit{$<$Property name$>$})}. This step is necessary for input properties to update the quickwatch view.
777\clearpage
778
779%\textit{\small Note 1: It is currently not possible to read directly from the input data stream without creating an intermediate CryptoolStream.\\\\
780%\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.\\\\}
781
782The output data property (which handles the input data after it has been encrypted or decrypted) will in our example look as follows:
783
784\begin{lstlisting}
785[PropertyInfo(Direction.OutputData, "Text output", "The string after processing with the Caesar cipher", "", false, false, DisplayLevel.Beginner, QuickWatchFormat.Text, null)]
786public string OutputString
787{
788        get { return this.outputString; }
789        set
790        {
791                outputString = value;
792                OnPropertyChanged("OutputString");
793        }
794}
795\end{lstlisting}
796
797\ \\
798\indent CrypTool 2 does not require implementing set methods for output properties, as they will never be called from outside the plugin. Nevertheless, in our example the plugin itself accesses the property, and therefore we have chosen to implement the set method.
799
800You can provide additional output data types if you so desire. In our example, we will also offer output data of type \textit{CryptoolStream}, input data for external alphabets, and input data for the shift value of our Caesar algorithm. Note that for the first of these, the set method is not implemented since it will never be called. We shall define these properties as follows:
801
802\begin{lstlisting}
803[PropertyInfo(Direction.OutputData, "CryptoolStream output", "The raw CryptoolStream data after processing with the Caesar cipher", "", false, false, DisplayLevel.Beginner, QuickWatchFormat.Text, null)]
804public CryptoolStream OutputData
805{
806        get
807        {
808                if (outputString != null)
809                {
810                        CryptoolStream cs = new CryptoolStream();
811                        listCryptoolStreamsOut.Add(cs);
812                        cs.OpenRead(Encoding.Default.GetBytes(outputString.ToCharArray()));
813                        return cs;
814                }
815                else
816                {
817                        return null;
818                }
819        }
820        set { }
821}
822
823[PropertyInfo(Direction.InputData, "External alphabet input", "Input a string containing the alphabet to be used by Caesar.\nIf no alphabet is provided for this input, the internal default alphabet will be used.", "", false, false, DisplayLevel.Expert, QuickWatchFormat.Text, null)]
824public string InputAlphabet
825{
826        get { return ((CaesarSettings)this.settings).AlphabetSymbols; }
827        set
828        {
829                if (value != null && value != settings.AlphabetSymbols)
830                {
831                        ((CaesarSettings)this.settings).AlphabetSymbols = value;
832                        OnPropertyChanged("InputAlphabet");
833                }
834        }
835}
836
837[PropertyInfo(Direction.InputData, "Shift value (integer)", "This is the same setting as the shift value in the Settings pane but as dynamic input.", "", false, false, DisplayLevel.Expert, QuickWatchFormat.Text, null)]
838public int ShiftKey
839{
840        get { return settings.ShiftKey; }
841        set
842        {
843                if (value != settings.ShiftKey)
844                {
845                        settings.ShiftKey = value;
846                }
847        }
848}
849\end{lstlisting}
850
851
852\subsection{Sending messages to the CrypTool 2 core}
853\label{sec:SendingMessagesToTheCrypTool2Core}
854
855The CrypTool 2 API provides two methods to send messages from the plugin to the CrypTool 2 core. \textit{GuiLogMessage} is used to send messages to the CrypTool 2 status bar. This method is a nice mechanism to inform the user as to what your plugin is currently doing. \textit{OnPropertyChanged} is used to inform the core application of changes to any plugin properties and data. This may not affect the user interface, but is important to keep the core appraised of the plugin's current state.
856
857\begin{figure}[h]
858        \centering
859                \includegraphics[width=1.00\textwidth]{figures/status_bar.jpg}
860        \caption{An example status bar.}
861        \label{fig:status_bar}
862\end{figure}
863\clearpage
864
865The \textit{GuiLogMessage} method takes two parameters:
866
867\begin{itemize}
868        \item \textit{Message} --- the text to be shown in the status bar.
869        \item \textit{NotificationLevel} --- the type of message, that is, its alert level:
870        \begin{itemize}
871                \item \texttt{NotificationLevel.Error}
872                \item \texttt{NotificationLevel.Warning}
873                \item \texttt{NotificationLevel.Info}
874                \item \texttt{NotificationLevel.Debug}
875        \end{itemize}
876\end{itemize}
877
878Both of these notification methods also have associated events. Outlines of both related events will have been automatically generated by implementing the interface (see Section \ref{sec:AddingInterfaceFunctionsToTheCaesarClass}), but we must define the appropriate methods as follows:
879
880\begin{lstlisting}
881public event GuiLogNotificationEventHandler OnGuiLogNotificationOccured;
882
883private void GuiLogMessage(string message, NotificationLevel logLevel)
884{
885        EventsHelper.GuiLogMessage(OnGuiLogNotificationOccured, this, new GuiLogEventArgs(message, this, logLevel));
886}
887
888public event PropertyChangedEventHandler PropertyChanged;
889
890public void OnPropertyChanged(String name)
891{
892        EventsHelper.PropertyChanged(PropertyChanged, this, new PropertyChangedEventArgs(name));
893}
894\end{lstlisting}
895
896\ \\
897\indent Note that to use \textit{PropertyChangedEventHandler} you must include the namespace \textit{System.\linebreak ComponentModel}. Our collection of included namespaces should now look as follows:
898
899\begin{lstlisting}
900using System;
901using System.Collections.Generic;
902using System.ComponentModel;
903using System.Text;
904
905using Cryptool.PluginBase;
906using Cryptool.PluginBase.Cryptography;
907using Cryptool.PluginBase.IO;
908using Cryptool.PluginBase.Miscellaneous;
909\end{lstlisting}
910\clearpage
911
912\section{Completing the algorithmic code of the Caesar class}
913\label{sec:CompletingTheAlgorithmicCodeOfTheCaesarClass}
914
915At this point, the plugin should be ready to be read by and shown correctly in the CrypTool 2 application. However, we haven't actually implemented the algorithm yet; we have just implemented interfaces and constructed a thorough set of properties. Algorithmic processing should be done in the \textit{Execute()} function, as this is what CrypTool 2 will always call first. The actual functionality of your algorithm, as well as the structure thereof, is up to you. Note that an outline of the \textit{Execute()} function will have been automatically generated by implementing the interface (see Section \ref{sec:AddingInterfaceFunctionsToTheCaesarClass}).
916
917We have chosen to split our algorithm's encryption and decryption processes into two separate functions, which will both ultimately call the \textit{ProcessCaesar()} function. Below is our implementation of the Caesar algothmic processing and the \textit{Execute()} function:
918
919\begin{lstlisting}
920private void ProcessCaesar(CaesarMode mode)
921{
922        CaesarSettings cfg = (CaesarSettings)this.settings;
923        StringBuilder output = new StringBuilder("");
924        string alphabet = cfg.AlphabetSymbols;
925
926        // If we are working in case-insensitive mode, we will use only
927        // capital letters, hence we must transform the whole alphabet
928        // to uppercase.
929        if (!cfg.CaseSensitiveAlphabet)
930        {
931                alphabet = cfg.AlphabetSymbols.ToUpper();
932        }
933
934        if (inputString != null)
935        {
936                for (int i = 0; i < inputString.Length; i++)
937                {
938                        // Get the plaintext char currently being processed.
939                        char currentchar = inputString[i];
940
941                        // Store whether it is upper case (otherwise lowercase is assumed).
942                        bool uppercase = char.IsUpper(currentchar);
943
944                        // Get the position of the plaintext character in the alphabet.
945                        int ppos = 0;
946                        if (cfg.CaseSensitiveAlphabet)
947                        {
948                                ppos = alphabet.IndexOf(currentchar);
949                        }
950                        else
951                        {
952                                ppos = alphabet.IndexOf(char.ToUpper(currentchar));
953                        }
954
955                        if (ppos >= 0)
956                        {
957                                // We found the plaintext character in the alphabet,
958                                // hence we will commence shifting.
959                                int cpos = 0;
960                                switch (mode)
961                                {
962                                        case CaesarMode.encrypt:
963                                                cpos = (ppos + cfg.ShiftKey) % alphabet.Length;
964                                                break;
965                                        case CaesarMode.decrypt:
966                                                cpos = (ppos - cfg.ShiftKey + alphabet.Length) % alphabet.Length;
967                                                break;
968                                }
969
970                                // We have the position of the ciphertext character,
971                                // hence just output it in the correct case.
972                                if (cfg.CaseSensitiveAlphabet)
973                                {
974                                        output.Append(alphabet[cpos]);
975                                }
976                                else
977                                {
978                                        if (uppercase)
979                                        {
980                                                output.Append(char.ToUpper(alphabet[cpos]));
981                                        }
982                                        else
983                                        {
984                                                output.Append(char.ToLower(alphabet[cpos]));
985                                        }
986                                }
987                        }
988                        else
989                        {
990                                // The plaintext character was not found in the alphabet,
991                                // hence proceed with handling unknown characters.
992                                switch ((CaesarSettings.UnknownSymbolHandlingMode)cfg.UnknownSymbolHandling)
993                                {
994                                        case CaesarSettings.UnknownSymbolHandlingMode.Ignore:
995                                                output.Append(inputString[i]);
996                                                break;
997                                        case CaesarSettings.UnknownSymbolHandlingMode.Replace:
998                                                output.Append('?');
999                                                break;
1000                                }
1001                        }
1002
1003                        // Show the progress.
1004                        if (OnPluginProgressChanged != null)
1005                        {
1006                                OnPluginProgressChanged(this, new PluginProgressEventArgs(i, inputString.Length - 1));
1007                        }
1008                }
1009                outputString = output.ToString();
1010                OnPropertyChanged("OutputString");
1011                OnPropertyChanged("OutputData");
1012        }
1013}
1014
1015public void Encrypt()
1016{
1017        ProcessCaesar(CaesarMode.encrypt);
1018}
1019
1020public void Decrypt()
1021{
1022        ProcessCaesar(CaesarMode.decrypt);
1023}
1024
1025public void Execute()
1026{
1027        switch (settings.Action)
1028        {
1029                case 0:
1030                        GuiLogMessage("Encrypting", NotificationLevel.Debug);
1031                        Encrypt();
1032                        break;
1033                case 1:
1034                        GuiLogMessage("Decrypting", NotificationLevel.Debug);
1035                        Decrypt();
1036                        break;
1037                default:
1038        break;
1039        }
1040}
1041\end{lstlisting}
1042
1043\ \\
1044It is important to make sure that all changes to the output properties will be announced to the CrypTool 2 environment. In our example this happens by calling the set method of \textit{OutputData}, which in turn calls \textit{OnPropertyChanged} to indicate that both output properties \textit{OutputData} and \textit{OutputDataStream} have changed. Instead of calling the property's set method you could instead call \textit{OnPropertyChanged} directly within the \textit{Execute()} method.
1045\clearpage
1046
1047You may have noticed that the \textit{ProgressChanged} method is undefined. This method can be used to show the current algorithm process as a progress bar in the plugin icon. To use this method and compile successfully, you must declare this method, which we have done for our example below. Note that the \textit{OnPluginProgressChanged} event will have been automatically generated by implementing the interface (see Section \ref{sec:AddingInterfaceFunctionsToTheCaesarClass}).
1048
1049\begin{lstlisting}
1050public event PluginProgressChangedEventHandler OnPluginProgressChanged;
1051
1052private void ProgressChanged(double value, double max)
1053{
1054        EventsHelper.ProgressChanged(OnPluginProgressChanged, this, new PluginProgressEventArgs(value, max));
1055}
1056\end{lstlisting}
1057
1058\section{Performing a clean dispose}
1059\label{sec:PerformingACleanDispose}
1060
1061Be sure you have closed and cleaned all your streams after execution before CrypTool 2 decides to dispose the plugin instance.
1062\begin{lstlisting}
1063public void Dispose()
1064{
1065        foreach(CryptoolStream stream in listCryptoolStreamsOut)
1066        {
1067                stream.Close();
1068        }
1069        listCryptoolStreamsOut.Clear();
1070}
1071\end{lstlisting}
1072\clearpage
1073
1074\section{Drawing the workflow of your plugin}
1075\label{DrawingTheWorkfloweOfYourPlugin}
1076
1077Each plugin should have an associated workflow file to show the algorithm in action in CrypTool 2. These workflow files are saved with the special \textit{.cte} file extension. You can view the example files from other plugins by opening any of the files in the \textit{\textbackslash ProjectSamples} folder with CrypTool 2. Below is a sample workflow for our Caesar example:
1078
1079\begin{figure}[h]
1080        \centering
1081                \includegraphics{figures/sample.jpg}
1082        \caption{A sample workflow diagram for the Caesar algorithm.}
1083        \label{fig:sample}
1084\end{figure}
1085
1086As your last step of development, once your plugin runs smoothly, you should also create one of these sample workflow files for your plugin. Such a file can be automatically created by simply saving a CrypTool 2 workspace project featuring your plugin. You should store the workflow file in the \textit{\textbackslash ProjectSamples} folder and make sure to commit the file to the SVN repository (see Section \ref{CommitingYourChanges}).
Note: See TracBrowser for help on using the repository browser.