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

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

HowTo: Small improvements; moved example download section to the beginning of Chapter 2 instead of the end.

File size: 65.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 plugin. The given instructions refer primarily to the usage of \textbf{Microsoft Visual Studio Professional 2008}, so before starting you should have a copy of the program installed on your computer.
4
5\section{Downloading the example and template}
6\label{sec:DownloadingTheExampleAndTemplate}
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/}\\\\
12We have also created a Visual Studio plugin \textbf{template} to help with the development of new plugins. Using this template is strongly recommended over copying and pasting code from this document! The template can be found here:\\\\
13\url{http://cryptool2.vs.uni-due.de/downloads/template/encryptionplugin.zip}
14
15\section{Creating a new project}
16\label{sec:CreatingANewProject}
17
18To begin, open Visual Studio, go to the menu bar and select \textit{File~$\rightarrow$ New $\rightarrow$ Project\ldots }. The following window will appear:
19
20\begin{figure}[h!]
21        \centering
22                \includegraphics[width=1.00\textwidth]{figures/vs_create_new_project.jpg}
23        \caption{Creating a new Visual Studio project.}
24        \label{fig:vs_create_new_project}
25\end{figure}
26\clearpage
27
28Select \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:
29
30\begin{figure}[h!]
31        \centering
32                \includegraphics[width=1.00\textwidth]{figures/solution_start_up.jpg}
33        \caption{A newly created solution and project.}
34        \label{fig:solution_start_up}
35\end{figure}
36\clearpage
37
38\section{Interface selection}
39\label{sec:InterfaceSelection}
40
41To include our new plugin in the CrypTool 2 application, we must first add a reference to the CrypTool 2 library \textbf{\textit{CrypPluginBase.dll}}, where all the necessary CrypTool 2 plugin interfaces are declared.
42
43\begin{figure}[h!]
44        \includegraphics{figures/add_reference.jpg}
45        \caption{Adding a new reference.}
46        \label{fig:add_reference}
47\end{figure}
48
49\noindent Right-click in the Solution Explorer on the \textit{Reference} item and choose \textit{Add Reference}. A window like the following should appear:
50
51\begin{figure}[h!]
52        \centering
53                \includegraphics{figures/add_pluginbase_source.jpg}
54        \caption{Adding a reference to the CrypPluginBase source code.}
55        \label{fig:add_pluginbase_source}
56\end{figure}
57\clearpage
58
59Unless you have created your new project in the same CrypTool 2 solution, you probably will not be able to select the library directly as seen above in Figure \ref{fig:add_pluginbase_source}; instead you can browse for the binary DLL as seen below in Figure \ref{fig:browse_reference}. Click on the \textit{Browse} tab and navigate to the folder in which you downloaded the CrypTool 2 project. Within that folder, go to \textit{\textbackslash CrypPluginBase\textbackslash bin\textbackslash Debug} and select the file \textit{CrypPluginBase.dll}. The library reference can then be added by double clicking the file or pressing the \textit{OK} button.
60
61\begin{figure}[h!]
62        \centering
63                \includegraphics{figures/browse_reference.jpg}
64        \caption{Browsing for a reference.}
65        \label{fig:browse_reference}
66\end{figure}
67
68Besides CrypPluginBase you will need to add three Windows assembly references to provide the necessary namespaces for the user control functions \textit{Presentation} and \textit{QuickWatchPresentation}. This can be done in a similar manner as before with the \textit{CrypPluginBase} reference, but by selecting the \textit{.NET} tab and searching for the references there. Select the following .NET components:
69
70\textit{
71\begin{itemize}
72    \item PresentationCore
73    \item PresentationFramework
74    \item WindowsBase
75\end{itemize}}
76\clearpage
77
78\noindent After these additions, your reference tree view should look like this:
79
80\begin{figure}[h!]
81                \includegraphics{figures/reference_tree.jpg}
82        \caption{A reference tree with the essential components.}
83        \label{fig:reference_tree}
84\end{figure}
85
86\noindent If your plugin will require other additional libraries, you can add them in the same way.
87
88\section{Modifing the project properties}
89\label{sec:ModifyTheProjectProperties}
90
91It 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 \textit{AssemblyInfo.cs}, which can be found in the \textit{Properties} folder. Make the following two changes:
92
93\begin{itemize}
94        \item Change the attribute \textit{AssemblyVersion} to have the value "2.0.*", and
95        \item Comment out the attribute \textit{AssemblyFileVersion}.
96\end{itemize}
97
98\noindent This section of your assembly file should now look something like this:
99
100\begin{lstlisting}
101[assembly: AssemblyVersion("2.0.*")]
102//[assembly: AssemblyFileVersion("1.0.0.0")]
103\end{lstlisting}
104
105\section{Creating classes for the algorithm and its settings}
106\label{sec:CreatingClassesForTheAlgorithmAndItsSettings}
107
108In the next step we will create two classes. The first class will be the main driver; we will call ours \textit{Caesar} since that is the name of the cipher that it will implement. 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}.
109\clearpage
110
111\subsection{Creating a class for the algorithm}
112\label{sec:CreatingAClassForTheAlgorithm}
113
114When 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}. There are two ways to change the name:
115
116\begin{itemize}
117        \item Rename the existing class, or
118        \item Delete the existing class and create a new one.
119\end{itemize}
120%\clearpage
121
122\noindent Both options will achieve the same results. We will guide you through the second method. First, delete \textit{Class1.cs}.
123
124\begin{figure}[h!]
125        \centering
126                \includegraphics{figures/new_class.jpg}
127        \caption{Deleting a class.}
128        \label{fig:new_class}
129\end{figure}
130\clearpage
131
132\noindent Then right-click on the project item (in our case, \textit{Caesar}) and select \textit{Add $\rightarrow$ Class\ldots }:
133
134\begin{figure}[h]
135        \centering
136                \includegraphics{figures/add_new_class.jpg}
137        \caption{Adding a new class.}
138        \label{fig:add_new_class}
139\end{figure}
140\clearpage
141
142\noindent Finally, give your class a unique name. We will call our class \textit{Caesar.cs} and define it as public so that it will be available to other classes.
143
144\begin{figure}[h!]
145        \centering
146                \includegraphics[width=1.00\textwidth]{figures/name_new_class.jpg}
147        \caption{Naming the new class.}
148        \label{fig:name_new_class}
149\end{figure}
150
151Note that Visual Studio will automatically generate a very basic code outline for the new class. In our example, we will not use the all the namespaces that are automatically imported, so you can delete the line \texttt{using System.Linq;}.
152
153\subsection{Creating a settings class}
154\label{sec:CreatingASettingsClass}
155
156Add a second public class in the same way. We will call the class \textit{CaesarSettings}. 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.
157\clearpage
158
159\noindent Below is an example of what a completed TaskPane for the existing Caesar plugin in CrypTool 2 looks like:
160
161\begin{figure}[h!]
162        \centering
163                \includegraphics{figures/task_pane.jpg}
164        \caption{The completed TaskPane for the existing Caesar plugin.}
165        \label{fig:task_pane}
166\end{figure}
167\clearpage
168
169\subsection{Adding the namespaces and inheritance sources for the Caesar class}
170\label{sec:AddingTheNamespacesAndInheritanceSourcesForTheCaesarClass}
171
172Open 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:
173
174\begin{itemize}
175        \item \textit{Cryptool.PluginBase} --- contains interfaces such as \textit{IPlugin}, \textit{IHash}, and \textit{ISettings}, as well as attributes, enumerations, delegates and extensions.
176        \item \textit{Cryptool.PluginBase.Analysis} --- contains interfaces for cryptanalysis plugins (such as \textit{Stream Comparator}).
177        \item \textit{Cryptool.PluginBase.Control} --- contains global interfaces for the \textit{IControl} feature for defining custom controls.
178        \item \textit{Cryptool.PluginBase.Cryptography} --- contains interfaces for encryption and hash algorithms such as AES, DES and MD5.
179        \item \textit{Cryptool.PluginBase.Editor} --- contains interfaces for editors that can be implemented in CrypTool 2, such as the default editor.
180        \item \textit{Cryptool.PluginBase.Generator} --- contains interfaces for generators, including the random input generator.
181        \item \textit{Cryptool.PluginBase.IO} --- contains interfaces for input, output and the \textit{CryptoolStream}.
182        \item \textit{Cryptool.PluginBase.Miscellaneous} --- contains assorted helper classes, including \textit{GuiLogMessage} and \textit{PropertyChanged}.
183        \item \textit{Cryptool.PluginBase.Resources} --- used only by CrypWin and the editor; not necessary for plugin development.
184        \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.
185        \item \textit{Cryptool.PluginBase.Validation} --- contains interfaces for validation methods, including regular expressions.
186\end{itemize}
187
188\noindent In our example, the Caesar algorithm necessitates the inclusion of the following namespaces:
189
190\begin{itemize}
191        \item \textit{Cryptool.PluginBase} --- to implement \textit{ISettings} in the CaesarSettings class.
192        \item \textit{Cryptool.PluginBase.Cryptography} --- to implement \textit{IEncryption} in the Caesar class.
193        \item \textit{Cryptool.PluginBase.IO} --- to use CryptoolStream for data input and output.
194        \item \textit{Cryptool.PluginBase.Miscellaneous} --- to use the CrypTool event handler.
195\end{itemize}
196
197\noindent It is important to define a new default namespace for our public class (\textit{Caesar}). In CrypTool 2  the standard namespace convention is \textit{Cryptool.[name of class]}. Therefore our namespace will be defined as \textit{Cryptool.Caesar}.\clearpage
198
199\noindent At this point, the source code should look like the following:
200
201\begin{lstlisting}
202using System;
203using System.Collections.Generic;
204using System.Text;
205
206//required CrypTool namespaces
207using Cryptool.PluginBase;
208using Cryptool.PluginBase.Cryptography;
209using Cryptool.PluginBase.IO;
210using Cryptool.PluginBase.Miscellaneous;
211
212namespace Cryptool.Caesar
213{
214        public class Caesar
215        {
216        }
217}
218\end{lstlisting}
219
220\ \\ % ugly but functional
221\noindent Next we should let the \textit{Caesar} class inherit from \textit{IEncryption} by making the following alteration:
222
223\begin{lstlisting}
224namespace Cryptool.Caesar
225{
226        public class Caesar : IEncryption
227        {
228        }
229}
230\end{lstlisting}
231
232\subsection{Adding interface functions to the Caesar class}
233\label{sec:AddingInterfaceFunctionsToTheCaesarClass}
234
235You may notice an underscore underneath the \textit{I} in \textit{IEncryption}. Move your mouse over it, or place the cursor on it and press \textit{Shift+Alt+F10} and the following submenu should appear:
236
237\begin{figure}[h!]
238        \centering
239                \includegraphics{figures/inherit_submenu.jpg}
240        \caption{An inheritance submenu.}
241        \label{fig:inherit_submenu}
242\end{figure}
243
244Select the item \textit{Implement interface `IEncryption'}. Visual Studio will automatically generate all the interface members necessary for interaction with the CrypTool 2 core. (This step will save you a lot of typing!)
245\clearpage
246
247\noindent Your code should now look like this:
248
249\begin{lstlisting}
250using System;
251using System.Collections.Generic;
252using System.Text;
253
254using Cryptool.PluginBase;
255using Cryptool.PluginBase.Cryptography;
256using Cryptool.PluginBase.IO;
257using Cryptool.PluginBase.Miscellaneous;
258
259namespace Cryptool.Caesar
260{
261    public class Caesar : IEncryption
262    {
263        #region IPlugin Members
264
265        public void Dispose()
266        {
267            throw new NotImplementedException();
268        }
269
270        public void Execute()
271        {
272            throw new NotImplementedException();
273        }
274
275        public void Initialize()
276        {
277            throw new NotImplementedException();
278        }
279
280        public event GuiLogNotificationEventHandler OnGuiLogNotificationOccured;
281
282        public event PluginProgressChangedEventHandler OnPluginProgressChanged;
283
284        public event StatusChangedEventHandler OnPluginStatusChanged;
285
286        public void Pause()
287        {
288            throw new NotImplementedException();
289        }
290
291        public void PostExecution()
292        {
293            throw new NotImplementedException();
294        }
295
296        public void PreExecution()
297        {
298            throw new NotImplementedException();
299        }
300
301        public System.Windows.Controls.UserControl Presentation
302        {
303            get { throw new NotImplementedException(); }
304        }
305
306        public System.Windows.Controls.UserControl QuickWatchPresentation
307        {
308            get { throw new NotImplementedException(); }
309        }
310
311        public ISettings Settings
312        {
313            get { throw new NotImplementedException(); }
314        }
315
316        public void Stop()
317        {
318            throw new NotImplementedException();
319        }
320
321        #endregion
322
323        #region INotifyPropertyChanged Members
324
325        public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
326
327        #endregion
328    }
329}
330\end{lstlisting}
331
332\subsection{Adding the namespace and interfaces to the CaesarSettings class}
333\label{sec:AddingTheNamespaceAndInterfacesToTheCaesarSettingsClass}
334
335Let's now take a look at the second class in our example, \textit{CaesarSettings}, by double-clicking on the \textit{CaesarSettings.cs} file in the Solution Explorer. First, we need to again include the \textit{Cryptool.PluginBase} namespace to the class header. Then we must let the settings class inherit from \textit{ISettings} in the same manner as was done with the Caesar class. Visual Studio will again automatically generate code from the CrypTool interface as seen below. (In this case, we can remove the using \texttt{System.Collections.Generic;}, \texttt{using System.Linq;}, and \texttt{using System.Text;} lines, as we will not use those references.)
336\clearpage
337
338\begin{lstlisting}
339using System;
340
341using Cryptool.PluginBase;
342
343namespace Cryptool.Caesar
344{
345    public class CaesarSettings : ISettings
346    {
347        #region ISettings Members
348
349        public bool HasChanges
350        {
351            get
352            {
353                throw new NotImplementedException();
354            }
355            set
356            {
357                throw new NotImplementedException();
358            }
359        }
360
361        #endregion
362
363        #region INotifyPropertyChanged Members
364
365        public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
366
367        #endregion
368    }
369}
370\end{lstlisting}
371
372\subsection{Adding controls to the CaesarSettings class}
373\label{sec:AddingControlsToTheCaesarSettingsClass}
374
375The 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; you will, however, still have to modify the \textit{HasChanges} property to avoid a \textit{NotImplementedException}. 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.\\
376
377\begin{lstlisting}
378using System;
379using System.ComponentModel;
380using System.Windows;
381using System.Windows.Controls;
382
383using Cryptool.PluginBase;
384
385namespace Cryptool.Caesar
386{
387    public class CaesarSettings : ISettings
388    {
389        #region Public Caesar specific interface
390
391        /// <summary>
392        /// This delegate is ued to send log messages from
393        /// the settings class to the Caesar plugin.
394        /// </summary>
395        public delegate void CaesarLogMessage(string msg, NotificationLevel loglevel);
396
397        /// <summary>
398        /// An enumeration for the different modes of handling
399        /// unknown characters.
400        /// </summary>
401        public enum UnknownSymbolHandlingMode { Ignore = 0, Remove = 1, Replace = 2 };
402
403        /// <summary>
404        /// Fires when a new status message was sent.
405        /// </summary>
406        public event CaesarLogMessage LogMessage;
407
408        public delegate void CaesarReExecute();
409
410        public event CaesarReExecute ReExecute;
411
412        /// <summary>
413        /// Retrieves or sets the current shift value (i.e. the key).
414        /// </summary>
415        [PropertySaveOrder(0)]
416        public int ShiftKey
417        {
418            get { return shiftValue; }
419            set
420            {
421                setKeyByValue(value);
422            }
423        }
424
425        /// <summary>
426        /// Retrieves the current setting of whether or not the
427        /// alphabet should be treated as case-sensitive.
428        /// </summary>
429        [PropertySaveOrder(1)]
430        public bool CaseSensitiveAlphabet
431        {
432            get
433            {
434                if (caseSensitiveAlphabet == 0)
435                {   return false;   }
436                else
437                {   return true;    }
438            }
439            set {} // this setting is readonly, but we must include
440                   // some form of set method to prevent problems.
441        }
442
443        /// <summary>
444        /// Returns true if any settings have been changed.
445        /// This value should be set externally to false, i.e.
446        /// when a project is saved.
447        /// </summary>
448        [PropertySaveOrder(3)]
449        public bool HasChanges
450        {
451            get { return hasChanges; }
452            set { hasChanges = value; }
453        }
454
455        #endregion
456
457        #region Private variables
458        private bool hasChanges;
459        private int selectedAction = 0;
460        private string upperAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
461        private string lowerAlphabet = "abcdefghijklmnopqrstuvwxyz";
462        private string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
463        private char shiftChar = 'C';
464        private int shiftValue = 2;
465        private UnknownSymbolHandlingMode unknownSymbolHandling = UnknownSymbolHandlingMode.Ignore;
466        private int caseSensitiveAlphabet = 0; // 0 = case-insensitve, 1 = case-sensitive
467        private bool sensitivityEnabled = true;
468        #endregion
469
470        #region Private methods
471
472        private string removeEqualChars(string value)
473        {
474            int length = value.Length;
475
476            for (int i = 0; i < length; i++)
477            {
478                for (int j = i + 1; j < length; j++)
479                {
480                    if ((value[i] == value[j]) || (!CaseSensitiveAlphabet & (char.ToUpper(value[i]) == char.ToUpper(value[j]))))
481                    {
482                        LogMessage("Removing duplicate letter: \'" + value[j] + "\' from alphabet!", NotificationLevel.Warning);
483                        value = value.Remove(j,1);
484                        j--;
485                        length--;
486                    }
487                }
488            }
489
490            return value;
491        }
492
493        /// <summary>
494        /// Set the new shiftValue and the new shiftCharacter
495        /// to offset % alphabet.Length.
496        /// </summary>
497        private void setKeyByValue(int offset)
498        {
499            HasChanges = true;
500
501            // Make sure the shift value lies within the alphabet range.
502            offset = offset % alphabet.Length;
503
504            // Set the new shiftChar.
505            shiftChar = alphabet[offset];
506
507            // Set the new shiftValue.
508            shiftValue = offset;
509
510            // Announce this to the settings pane.
511            OnPropertyChanged("ShiftValue");
512            OnPropertyChanged("ShiftChar");
513
514            // Print some info in the log.
515            LogMessage("Accepted new shift value " + offset + "! (Adjusted shift character to \'" + shiftChar + "\')", NotificationLevel.Info);
516        }
517
518        private void setKeyByCharacter(string value)
519        {
520            try
521            {
522                int offset;
523                if (this.CaseSensitiveAlphabet)
524                {
525                    offset = alphabet.IndexOf(value[0]);
526                }
527                else
528                {
529                    offset = alphabet.ToUpper().IndexOf(char.ToUpper(value[0]));
530                }
531
532                if (offset >= 0)
533                {
534                    HasChanges = true;
535                    shiftValue = offset;
536                    shiftChar = alphabet[shiftValue];
537                    LogMessage("Accepted new shift character \'" + shiftChar + "\'! (Adjusted shift value to " + shiftValue + ")", NotificationLevel.Info);
538                    OnPropertyChanged("ShiftValue");
539                    OnPropertyChanged("ShiftChar");
540                }
541                else
542                {
543                    LogMessage("Bad input \"" + value + "\"! (Character not in alphabet!) Reverting to " + shiftChar.ToString() + "!", NotificationLevel.Error);
544                }
545            }
546            catch (Exception e)
547            {
548                LogMessage("Bad input \"" + value + "\"! (" + e.Message + ") Reverting to " + shiftChar.ToString() + "!", NotificationLevel.Error);
549            }
550        }
551
552        #endregion
553
554        #region Algorithm settings properties (visible in the Settings pane)
555
556        [PropertySaveOrder(4)]
557        [ContextMenu("Action", "Select the algorithm action", 1, DisplayLevel.Beginner, ContextMenuControlType.ComboBox, new int[] { 1, 2 }, "Encrypt", "Decrypt")]
558        [TaskPane("Action", "setAlgorithmActionDescription", null, 1, true, DisplayLevel.Beginner, ControlType.ComboBox, new string[] { "Encrypt", "Decrypt" })]
559        public int Action
560        {
561            get
562            {
563                return this.selectedAction;
564            }
565            set
566            {
567                if(value != selectedAction)
568                {
569                        HasChanges = true;
570                        this.selectedAction = value;
571                    OnPropertyChanged("Action");
572                }
573                if(ReExecute != null)
574                {       ReExecute();    }
575            }
576        }
577
578        [PropertySaveOrder(5)]
579        [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)]
580        public int ShiftValue
581        {
582            get { return shiftValue; }
583            set
584            {
585                setKeyByValue(value);
586                if (ReExecute != null)
587                {       ReExecute();    }
588            }
589        }
590
591        [PropertySaveOrder(6)]
592        [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}")]
593        public string ShiftChar
594        {
595            get { return this.shiftChar.ToString(); }
596            set
597            {
598                setKeyByCharacter(value);
599                if (ReExecute != null)
600                        {   ReExecute();    }
601            }
602        }
603
604        [PropertySaveOrder(7)]
605        [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 \'?\'" })]
606        [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 \'?\'" })]
607        public int UnknownSymbolHandling
608        {
609            get { return (int)this.unknownSymbolHandling; }
610            set
611            {
612                if((UnknownSymbolHandlingMode)value != unknownSymbolHandling)
613                {
614                        HasChanges = true;
615                        this.unknownSymbolHandling = (UnknownSymbolHandlingMode)value;
616                    OnPropertyChanged("UnknownSymbolHandling");
617                                }
618                if (ReExecute != null)
619                {       ReExecute();    }
620            }
621        }
622
623        [SettingsFormat(0, "Normal", "Normal", "Black", "White", Orientation.Vertical)]
624        [PropertySaveOrder(9)]
625        [TaskPane("Alphabet", "This is the alphabet currently in use.", null, 6, true, DisplayLevel.Expert, ControlType.TextBox, "")]
626        public string AlphabetSymbols
627        {
628          get { return this.alphabet; }
629          set
630          {
631            string a = removeEqualChars(value);
632            if (a.Length == 0) // cannot accept empty alphabets
633            {
634              LogMessage("Ignoring empty alphabet from user! Using previous alphabet instead: \" + alphabet + "\" (" + alphabet.Length.ToString() + " Symbols)", NotificationLevel.Info);
635            }
636            else if (!alphabet.Equals(a))
637            {
638              HasChanges = true;
639              this.alphabet = a;
640              setKeyByValue(shiftValue); // reevaluate if the shiftvalue is still within the range
641              LogMessage("Accepted new alphabet from user: \"" + alphabet + "\" (" + alphabet.Length.ToString() + " Symbols)", NotificationLevel.Info);
642              OnPropertyChanged("AlphabetSymbols");
643
644              if (ReExecute != null)
645              { ReExecute();    }
646            }
647          }
648        }
649
650        /// <summary>
651        /// Visible setting how to deal with alphabet case.
652        /// 0 = case-insentive, 1 = case-sensitive
653        /// </summary>
654        [PropertySaveOrder(8)]
655        [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" })]
656        [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" })]
657        public int AlphabetCase
658        {
659            get { return this.caseSensitiveAlphabet; }
660            set
661            {
662                if (value != caseSensitiveAlphabet)
663                {       HasChanges = true;      }
664                this.caseSensitiveAlphabet = value;
665                if (value == 0)
666                {
667                    if (alphabet == (upperAlphabet + lowerAlphabet))
668                    {
669                        alphabet = upperAlphabet;
670                        LogMessage("Changing alphabet to: \"" + alphabet + "\" (" + alphabet.Length.ToString() + " Symbols)", NotificationLevel.Info);
671                        OnPropertyChanged("AlphabetSymbols");
672                        // reset the key (shiftvalue/shiftChar)
673                        // to be in the range of the new alphabet.
674                        setKeyByValue(shiftValue);
675                    }
676                }
677                else
678                {
679                    if (alphabet == upperAlphabet)
680                    {
681                        alphabet = upperAlphabet + lowerAlphabet;
682                        LogMessage("Changing alphabet to: \"" + alphabet + "\" (" + alphabet.Length.ToString() + " Symbols)", NotificationLevel.Info);
683                        OnPropertyChanged("AlphabetSymbols");
684                    }
685                }
686
687                // Remove equal characters from the current alphabet.
688                string a = alphabet;
689                alphabet = removeEqualChars(alphabet);
690                if (a != alphabet)
691                {
692                    OnPropertyChanged("AlphabetSymbols");
693                    LogMessage("Changing alphabet to: \"" + alphabet + "\" (" + alphabet.Length.ToString() + " Symbols)", NotificationLevel.Info);
694                }
695                OnPropertyChanged("AlphabetCase");
696                if (ReExecute != null)
697                {       ReExecute();    }
698            }
699        }
700
701        #endregion
702
703        #region INotifyPropertyChanged Members
704
705        public event PropertyChangedEventHandler PropertyChanged;
706
707        protected void OnPropertyChanged(string name)
708        {
709          if (PropertyChanged != null)
710          {
711            PropertyChanged(this, new PropertyChangedEventArgs(name));
712          }
713        }
714
715        #endregion
716
717        #region TaskPaneAttributeChanged (Sample)
718        /// <summary>
719        /// This event is here merely as a sample.
720        /// </summary>
721        public event TaskPaneAttributeChangedHandler TaskPaneAttributeChanged;
722
723        [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)]
724        public void EnableDisableSesitivity()
725        {
726          if (TaskPaneAttributeChanged!= null)
727          {
728            sensitivityEnabled = !sensitivityEnabled;
729            if (sensitivityEnabled)
730            {
731              TaskPaneAttributeChanged(this, new TaskPaneAttributeChangedEventArgs(new TaskPaneAttribteContainer("AlphabetCase", Visibility.Visible)));
732            }
733            else
734            {
735              TaskPaneAttributeChanged(this, new TaskPaneAttributeChangedEventArgs(new TaskPaneAttribteContainer("AlphabetCase", Visibility.Collapsed)));
736            }
737          }
738        }
739        #endregion TaskPaneAttributeChanged (Sample)
740    }
741}
742\end{lstlisting}
743\clearpage
744
745\section{Adding an icon to the Caesar class}
746\label{sec:AddingAnIconToTheCaesarClass}
747
748Before 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.)
749
750For 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.
751
752Once 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}.
753
754\begin{figure}[h!]
755        \centering
756                \includegraphics{figures/add_existing_item.jpg}
757        \caption{Adding an existing item.}
758        \label{fig:add_existing_item}
759\end{figure}
760\clearpage
761
762A new window will then appear. Select \textit{Image Files} as the file type and select your newly-created icon for your plugin.
763
764\begin{figure}[h!]
765        \centering
766                \includegraphics{figures/choose_icon.jpg}
767        \caption{Selecting the image file.}
768        \label{fig:choose_icon}
769\end{figure}
770\clearpage
771
772Finally, 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.
773
774\begin{figure}[h!]
775        \centering
776                \includegraphics{figures/icon_properties.jpg}
777        \caption{Selecting the image properties.}
778        \label{fig:icon_properties}
779\end{figure}
780
781In the \textit{Properties} panel, set the \textit{Build Action} to \textit{Resource}.
782
783\begin{figure}[h!]
784        \centering
785                \includegraphics{figures/icon_build_action.jpg}
786        \caption{Selecting the icon's build action.}
787        \label{fig:icon_build_action}
788\end{figure}
789\clearpage
790
791\section{Defining the attributes of the Caesar class}
792\label{sec:DefiningTheAttributesOfTheCaesarClass}
793
794Now 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.
795
796Attributes 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.
797
798These attributes can be defined anywhere within the \textit{Cryptool.Caesar} namespace, but customarily they are defined right before the class declaration.
799
800\subsection{The \protect\textit{[Author]} attribute}
801\label{sec:TheAuthorAttribute}
802
803The \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.
804
805\begin{figure}[h!]
806        \centering
807                \includegraphics[width=.90\textwidth]{figures/attribute_author.jpg}
808        \caption{The defintion for the \textit{[Author]} attribute.}
809        \label{fig:attribute_author}
810\end{figure}
811
812As can be seen above, the author attribute takes four elements of type string. These elements are:
813
814\begin{itemize}
815        \item \textit{Author} --- the name of the plugin developer.
816        \item \textit{Email} --- the email address of the plugin developer, should he or she wish to be available for contact.
817        \item \textit{Institute} --- the organization, company or university with which the developer is affiliated.
818        \item \textit{URL} --- the website of the developer or of his or her institution.
819\end{itemize}
820
821All 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.
822\clearpage
823
824\subsection{The \protect\textit{[PluginInfo]} attribute}
825\label{sec:ThePluginInfoAttribute}
826
827The second attribute, \textit{[PluginInfo]}, provides necessary information about the plugin, and is therefore mandatory. This information appears in the caption and tool tip window. The attribute is defined as follows:
828
829\begin{figure}[h]
830        \centering
831                \includegraphics[width=1.00\textwidth]{figures/attribute_plugininfo.jpg}
832        \caption{The defintion for the \textit{[PluginInfo]} attribute.}
833        \label{fig:attribute_plugininfo}
834\end{figure}
835
836\noindent This attribute has the following parameters:
837
838\begin{itemize}
839        \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. This element is optional.
840        \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.
841        \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.
842        \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.
843        \item \textit{DescriptionURL} --- the local path of the description file (e.g.\ XAML file). This element is optional.
844        \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.
845\end{itemize}
846
847\noindent Unused elements should be set to \texttt{null} or an empty string.
848
849(There are a few limitations and bugs that still exist in the \textit{[PluginInfo]} attribute that will be resolved in a future version. Firstly, it is possible to use the plugin without setting a caption, although this is not recommended. In the future the plugin will fail to load without a caption. Secondly, a zero-length toolTip string currently causes the toolTip to appear as an empty box in the application. Lastly, the toolTip and description do not currently support internationalization and localization.)
850
851In 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.
852
853The second parameter, \textit{startable}, should be set to \texttt{false}, because our encryption algorithm is not an input generator.
854
855The 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.)
856
857The \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:
858
859\begin{figure}[h!]
860        \centering
861                \includegraphics[width=.30\textwidth]{figures/detailed_description.jpg}
862        \caption{The folder structure as seen in the Solution Explorer.}
863        \label{fig:attribute_plugininfo_icon_path}
864\end{figure}
865
866Once 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}.
867
868\begin{figure}[h!]
869        \centering
870                \includegraphics[width=1.00\textwidth]{figures/xaml_description.jpg}
871        \caption{A detailed description provided through an XAML file.}
872        \label{fig:xaml_description}
873\end{figure}
874\clearpage
875
876The 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$>$}.
877
878The 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}.
879
880If 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.)
881
882\subsection{The \protect\textit{[EncryptionType]} attribute}
883\label{sec:TheEncryptionTypeAttribute}
884
885The 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:
886
887\begin{figure}[h]
888        \centering
889                \includegraphics[width=.90\textwidth]{figures/attribute_encryptiontype.jpg}
890        \caption{A defined \textit{[EncryptionType]} attribute.}
891        \label{fig:attribute_encryption_type}
892\end{figure}
893
894The possible values of the \textit{[EncryptionType]} attribute are as follows:
895
896\begin{itemize}
897        \item \textit{Asymmetric} --- for asymmetrical encryption algorithms, such as RSA.
898        \item \textit{SymmetricBlock} --- for block cipher algorithms, such as DES, AES and Twofish.
899        \item \textit{SymmetricStream} --- for stream cipher algorithms, such as RC4, Rabbit and SEAL.
900        \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.
901        \item \textit{Classic} --- for classical encryption or hash algorithms, such as Caesar or MD5.
902\end{itemize}
903
904\section{Defining the private variables of the settings in the Caesar class}
905\label{sec:DefiningThePrivateVariablesOfTheSettingsInTheCaesarClass}
906
907The 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:
908
909\begin{lstlisting}
910public class Caesar : IEncryption
911{
912        #region Private variables
913        private CaesarSettings settings;
914        private string inputString;
915        private string outputString;
916        private enum CaesarMode { encrypt, decrypt };
917        private List<CryptoolStream> listCryptoolStreamsOut = new List<CryptoolStream>();
918        #endregion
919\end{lstlisting}
920
921\ \\ % ugly but functional
922If 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}.
923
924Our example makes use of the following private variables:
925
926\begin{itemize}
927        \item \texttt{CaesarSettings settings} --- required to implement the IPlugin interface properly.
928        \item \texttt{string inputString} --- string from which to read the input data.
929        \item \texttt{string outputString} --- string to which to save the output data.
930        \item \texttt{enum CaesarMode} --- used to select either encryption or decryption.
931        \item \texttt{List$<$CryptoolStream$>$ listCryptoolStreamsOut} --- a list of all streams created by the plugin, which helps to perform a clean dispose.
932\end{itemize}
933
934\section{Implementing the interfaces in the Caesar class}
935\label{sec:ImplementingTheInterfacesInTheCaesarClass}
936
937\subsection{Connecting the settings class}
938\label{sec:ConnectingTheSettingsClass}
939
940The 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:
941
942\begin{lstlisting}
943public Caesar()
944{
945        this.settings = new CaesarSettings();
946        this.settings.LogMessage += GuiLogMessage;
947}
948\end{lstlisting}
949
950\ \\
951\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:
952
953\begin{lstlisting}
954public ISettings Settings
955{
956        get { return (ISettings)this.settings; }
957        set { this.settings = (CaesarSettings)value; }
958}
959\end{lstlisting}
960\clearpage
961
962\subsection{The input/output attributes}
963\label{sec:TheInputOutputAttributes}
964
965%\ \\
966\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.
967
968The attribute that we will use for each proprerty is called \textit{[PropertyInfo]} and it consists of the following elements:
969
970\begin{itemize}
971        \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:
972        \begin{itemize}
973                \item \texttt{Direction.Input}
974                \item \texttt{Direction.Output}
975        \end{itemize}
976        \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:
977       
978\begin{figure}[h!]
979        \centering
980                \includegraphics[width=.55\textwidth]{figures/property_caption.jpg}
981        \caption{A possible property caption and toolTip.}
982        \label{fig:property_caption}
983\end{figure}
984
985        \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.
986        \item \textit{descriptionUrl} --- currently not used; fill it with \texttt{null} or an empty string.
987        \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.
988        \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.
989        \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:
990       
991        \begin{itemize}
992                \item \texttt{DisplayLevel.Beginner}
993                \item \texttt{DisplayLevel.Experienced}
994                \item \texttt{DisplayLevel.Expert}
995                \item \texttt{DisplayLevel.Professional}
996        \end{itemize}
997\clearpage
998       
999        \item \textit{quickWatchFormat} --- determines how the content of the property will be shown in the quickwatch perspective. CrypTool 2 accepts the following quickwatch formats:
1000       
1001        \begin{itemize}
1002                \item \texttt{QuickWatchFormat.Base64}
1003                \item \texttt{QuickWatchFormat.Hex}
1004                \item \texttt{QuickWatchFormat.None}
1005                \item \texttt{QuickWatchFormat.Text}
1006        \end{itemize}
1007
1008\begin{figure}[h]
1009        \centering
1010                \includegraphics{figures/quick_watch.jpg}
1011        \caption{A quickwatch display in hexadecimal.}
1012        \label{fig:quick_watch}
1013\end{figure}
1014       
1015        \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:
1016
1017\begin{lstlisting}
1018object YourMethodName(string PropertyNameToConvert)
1019\end{lstlisting}
1020
1021\end{itemize}
1022
1023\subsection{Defining the input/output properties}
1024\label{sec:DefiningTheInputOutputProperties}
1025
1026The 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:
1027
1028\begin{lstlisting}
1029[PropertyInfo(Direction.InputData, "Text input", "Input a string to be processed by the Caesar cipher", "", true, false, DisplayLevel.Beginner, QuickWatchFormat.Text, null)]
1030public string InputString
1031{
1032        get { return this.inputString; }
1033        set
1034  {
1035                if (value != inputString)
1036                {
1037                        this.inputString = value;
1038                        OnPropertyChanged("InputString");
1039                }
1040        }
1041}
1042\end{lstlisting}
1043
1044\ \\
1045In 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.
1046\clearpage
1047
1048%\textit{\small Note 1: It is currently not possible to read directly from the input data stream without creating an intermediate CryptoolStream.\\\\
1049%\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.\\\\}
1050
1051The output data property (which handles the input data after it has been encrypted or decrypted) will in our example look as follows:
1052
1053\begin{lstlisting}
1054[PropertyInfo(Direction.OutputData, "Text output", "The string after processing with the Caesar cipher", "", false, false, DisplayLevel.Beginner, QuickWatchFormat.Text, null)]
1055public string OutputString
1056{
1057        get { return this.outputString; }
1058        set
1059        {
1060                outputString = value;
1061                OnPropertyChanged("OutputString");
1062        }
1063}
1064\end{lstlisting}
1065
1066\ \\
1067\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.
1068
1069You 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:
1070
1071\begin{lstlisting}
1072[PropertyInfo(Direction.OutputData, "CryptoolStream output", "The raw CryptoolStream data after processing with the Caesar cipher", "", false, false, DisplayLevel.Beginner, QuickWatchFormat.Text, null)]
1073public CryptoolStream OutputData
1074{
1075        get
1076        {
1077                if (outputString != null)
1078                {
1079                        CryptoolStream cs = new CryptoolStream();
1080                        listCryptoolStreamsOut.Add(cs);
1081                        cs.OpenRead(Encoding.Default.GetBytes(outputString.ToCharArray()));
1082                        return cs;
1083                }
1084                else
1085                {
1086                        return null;
1087                }
1088        }
1089        set { }
1090}
1091
1092[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)]
1093public string InputAlphabet
1094{
1095        get { return ((CaesarSettings)this.settings).AlphabetSymbols; }
1096        set
1097        {
1098                if (value != null && value != settings.AlphabetSymbols)
1099                {
1100                        ((CaesarSettings)this.settings).AlphabetSymbols = value;
1101                        OnPropertyChanged("InputAlphabet");
1102                }
1103        }
1104}
1105
1106[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)]
1107public int ShiftKey
1108{
1109        get { return settings.ShiftKey; }
1110        set
1111        {
1112                if (value != settings.ShiftKey)
1113                {
1114                        settings.ShiftKey = value;
1115                }
1116        }
1117}
1118\end{lstlisting}
1119
1120
1121\subsection{Sending messages to the CrypTool 2 core}
1122\label{sec:SendingMessagesToTheCrypTool2Core}
1123
1124The CrypTool 2 API provides two methods to send messages from the plugin to the CrypTool 2 core: \textit{GuiLogMessage} (used to send messages to the CrypTool 2 status bar) and \textit{OnPropertyChanged} (used to inform the core of changes to the plugin data). The \textit{GuiLogMessage} method is a nice mechanism to inform the user as to what your plugin is currently doing.
1125
1126\begin{figure}[h]
1127        \centering
1128                \includegraphics[width=1.00\textwidth]{figures/status_bar.jpg}
1129        \caption{An example status bar.}
1130        \label{fig:status_bar}
1131\end{figure}
1132\clearpage
1133
1134The \textit{GuiLogMessage} method takes two parameters:
1135
1136\begin{itemize}
1137        \item \textit{Message} --- the text to be shown in the status bar.
1138        \item \textit{NotificationLevel} --- the type of message, that is, its alert level:
1139        \begin{itemize}
1140                \item \texttt{NotificationLevel.Error}
1141                \item \texttt{NotificationLevel.Warning}
1142                \item \texttt{NotificationLevel.Info}
1143                \item \texttt{NotificationLevel.Debug}
1144        \end{itemize}
1145\end{itemize}
1146
1147Both 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:
1148
1149\begin{lstlisting}
1150public event GuiLogNotificationEventHandler OnGuiLogNotificationOccured;
1151
1152private void GuiLogMessage(string message, NotificationLevel logLevel)
1153{
1154        EventsHelper.GuiLogMessage(OnGuiLogNotificationOccured, this, new GuiLogEventArgs(message, this, logLevel));
1155}
1156
1157public event PropertyChangedEventHandler PropertyChanged;
1158
1159public void OnPropertyChanged(String name)
1160{
1161        EventsHelper.PropertyChanged(PropertyChanged, this, new PropertyChangedEventArgs(name));
1162}
1163\end{lstlisting}
1164
1165\ \\
1166\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:
1167
1168\begin{lstlisting}
1169using System;
1170using System.Collections.Generic;
1171using System.ComponentModel;
1172using System.Text;
1173
1174using Cryptool.PluginBase;
1175using Cryptool.PluginBase.Cryptography;
1176using Cryptool.PluginBase.IO;
1177using Cryptool.PluginBase.Miscellaneous;
1178\end{lstlisting}
1179\clearpage
1180
1181\section{Completing the algorithmic code of the Caesar class}
1182\label{sec:CompletingTheAlgorithmicCodeOfTheCaesarClass}
1183
1184At 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}).
1185
1186We 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:
1187
1188\begin{lstlisting}
1189private void ProcessCaesar(CaesarMode mode)
1190{
1191        CaesarSettings cfg = (CaesarSettings)this.settings;
1192        StringBuilder output = new StringBuilder("");
1193        string alphabet = cfg.AlphabetSymbols;
1194
1195        // If we are working in case-insensitive mode, we will use only
1196        // capital letters, hence we must transform the whole alphabet
1197        // to uppercase.
1198        if (!cfg.CaseSensitiveAlphabet)
1199        {
1200                alphabet = cfg.AlphabetSymbols.ToUpper();
1201        }
1202
1203        if (inputString != null)
1204        {
1205                for (int i = 0; i < inputString.Length; i++)
1206                {
1207                        // Get the plaintext char currently being processed.
1208                        char currentchar = inputString[i];
1209
1210                        // Store whether it is upper case (otherwise lowercase is assumed).
1211                        bool uppercase = char.IsUpper(currentchar);
1212
1213                        // Get the position of the plaintext character in the alphabet.
1214                        int ppos = 0;
1215                        if (cfg.CaseSensitiveAlphabet)
1216                        {
1217                                ppos = alphabet.IndexOf(currentchar);
1218                        }
1219                        else
1220                        {
1221                                ppos = alphabet.IndexOf(char.ToUpper(currentchar));
1222                        }
1223
1224                        if (ppos >= 0)
1225                        {
1226                                // We found the plaintext character in the alphabet,
1227                                // hence we will commence shifting.
1228                                int cpos = 0;
1229                                switch (mode)
1230                                {
1231                                        case CaesarMode.encrypt:
1232                                                cpos = (ppos + cfg.ShiftKey) % alphabet.Length;
1233                                                break;
1234                                        case CaesarMode.decrypt:
1235                                                cpos = (ppos - cfg.ShiftKey + alphabet.Length) % alphabet.Length;
1236                                                break;
1237                                }
1238
1239                                // We have the position of the ciphertext character,
1240                                // hence just output it in the correct case.
1241                                if (cfg.CaseSensitiveAlphabet)
1242                                {
1243                                        output.Append(alphabet[cpos]);
1244                                }
1245                                else
1246                                {
1247                                        if (uppercase)
1248                                        {
1249                                                output.Append(char.ToUpper(alphabet[cpos]));
1250                                        }
1251                                        else
1252                                        {
1253                                                output.Append(char.ToLower(alphabet[cpos]));
1254                                        }
1255                                }
1256                        }
1257                        else
1258                        {
1259                                // The plaintext character was not found in the alphabet,
1260                                // hence proceed with handling unknown characters.
1261                                switch ((CaesarSettings.UnknownSymbolHandlingMode)cfg.UnknownSymbolHandling)
1262                                {
1263                                        case CaesarSettings.UnknownSymbolHandlingMode.Ignore:
1264                                                output.Append(inputString[i]);
1265                                                break;
1266                                        case CaesarSettings.UnknownSymbolHandlingMode.Replace:
1267                                                output.Append('?');
1268                                                break;
1269                                }
1270                        }
1271
1272                        // Show the progress.
1273                        if (OnPluginProgressChanged != null)
1274                        {
1275                                OnPluginProgressChanged(this, new PluginProgressEventArgs(i, inputString.Length - 1));
1276                        }
1277                }
1278                outputString = output.ToString();
1279                OnPropertyChanged("OutputString");
1280                OnPropertyChanged("OutputData");
1281        }
1282}
1283
1284public void Encrypt()
1285{
1286        ProcessCaesar(CaesarMode.encrypt);
1287}
1288
1289public void Decrypt()
1290{
1291        ProcessCaesar(CaesarMode.decrypt);
1292}
1293
1294public void Execute()
1295{
1296        switch (settings.Action)
1297        {
1298                case 0:
1299                        GuiLogMessage("Encrypting", NotificationLevel.Debug);
1300                        Encrypt();
1301                        break;
1302                case 1:
1303                        GuiLogMessage("Decrypting", NotificationLevel.Debug);
1304                        Decrypt();
1305                        break;
1306                default:
1307        break;
1308        }
1309}
1310\end{lstlisting}
1311
1312\ \\
1313It 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.
1314\clearpage
1315
1316You 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}).
1317
1318\begin{lstlisting}
1319public event PluginProgressChangedEventHandler OnPluginProgressChanged;
1320
1321private void ProgressChanged(double value, double max)
1322{
1323        EventsHelper.ProgressChanged(OnPluginProgressChanged, this, new PluginProgressEventArgs(value, max));
1324}
1325\end{lstlisting}
1326
1327\section{Performing a clean dispose}
1328\label{sec:PerformingACleanDispose}
1329
1330Be sure you have closed and cleaned all your streams after execution before CrypTool 2 decides to dispose the plugin instance. Though not required, we will run the disposal code before execution as well. We will expand the associated automatically generated methods (see Section \ref{sec:AddingInterfaceFunctionsToTheCaesarClass}) as follows:
1331
1332\begin{lstlisting}
1333public void Dispose()
1334{
1335        foreach(CryptoolStream stream in listCryptoolStreamsOut)
1336        {
1337                stream.Close();
1338        }
1339        listCryptoolStreamsOut.Clear();
1340}
1341
1342public void PostExecution()
1343{
1344        Dispose();
1345}
1346
1347public void PreExecution()
1348{
1349        Dispose();
1350}
1351\end{lstlisting}
1352\clearpage
1353
1354\section{Finishing the implementation}
1355\label{sec:FinishingTheImplementation}
1356
1357When adding plugin instances to the CrypTool 2 workspace, the application core checks whether the plugin runs without any exceptions. If any method inherited from IPlugin throws an exception, CrypTool 2 will display an error message and prohibit use of the plugin. Therefore, we must remove the \textit{NotImplementedException} from the automatically generated methods \textit{Initialize()}, \textit{Pause()} and \textit{Stop()}. In our example it will be sufficient to provide empty implementations:
1358
1359\begin{lstlisting}
1360public void Initialize()
1361{
1362}
1363
1364public void Pause()
1365{
1366}
1367
1368public void Stop()
1369{
1370}
1371\end{lstlisting}
1372
1373\ \\
1374The methods \textit{Presentation()} and \textit{QuickWatchPresentation()} can be used to provide a specialized visualization of the plugin algorithm to be shown in CrypTool 2. Take a look at the \textit{PRESENT} plugin to see how a custom visualization can be realized. For our Caesar example, we have chosen not to implement a custom visualization. Therefore we will simply return \texttt{null}:
1375
1376\begin{lstlisting}
1377public UserControl Presentation
1378{
1379        get { return null; }
1380}
1381
1382public UserControl QuickWatchPresentation
1383{
1384        get { return null; }
1385}
1386\end{lstlisting}
1387
1388\ \\
1389Your plugin should compile without errors at this point.
1390\clearpage
1391
1392\section{Importing and testing the plugin}
1393\label{sec:ImportingAndTestingThePlugin}
1394
1395After you have built the plugin, you need to move the newly created plugin DLL to a location where CrypTool 2 can find it. There are a few different ways to accomplish this. First, though, you need to locate the DLL. Once you have successfully compiled the plugin, the DLL should be in \textit{\mbox{\textbackslash CrypPluginBase\textbackslash }bin\textbackslash Debug}.
1396
1397\subsection{Global storage}
1398\label{sec:GlobalStorage}
1399
1400The first option is to copy your plugin's DLL file to the \textit{CrypPlugins} folder in which the CrypTool 2 executable (\textit{CrypWin.exe}) can be found.
1401
1402\begin{figure}[h]
1403        \centering
1404                \includegraphics{figures/copy_dll_global_storage.jpg}
1405        \caption{Copying the plugin to the global storage folder}
1406        \label{fig:copy_dll_global_storage}
1407\end{figure}
1408
1409This folder is known as ``global storage'' in the CrypTool 2 architecture. Changes in this folder will affect all users on a multi-user Windows platform. You should now restart CrypTool 2.
1410\clearpage
1411
1412\begin{figure}[h]
1413        \centering
1414                \includegraphics{figures/global_storage.jpg}
1415        \caption{Inside the CrypPlugins folder (the global storage).}
1416        \label{fig:global_storage}
1417\end{figure}
1418
1419\subsection{Custom storage}
1420\label{sec:CustomStorage}
1421
1422The second possibility is to copy your plugin's DLL file to the \textit{CrypPlugins} folder located in the \textit{Application Data} folder in your home folder. In Windows XP, the home folder path should be as follows: \textit{C:\textbackslash Documents and Settings\textbackslash $<$user name$>$\textbackslash Application Data\textbackslash CrypPlugins}, and in Vista and Windows 7 the path should look like: \textit{C:\textbackslash Users\textbackslash $<$user name$>$\textbackslash Application Data\textbackslash CrypPlugins}. This home folder path is called ``custom storage'' in the CrypTool architecture. Changes in this folder will only take effect for current user. After copying the file, you must restart CrypTool 2.
1423\clearpage
1424
1425\begin{figure}[h]
1426        \centering
1427                \includegraphics[width=1.00\textwidth]{figures/custom_storage.jpg}
1428        \caption{The custom storage folder.}
1429        \label{fig:custom_storage}
1430\end{figure}
1431
1432\subsection{Importing directly}
1433\label{sec:ImportingDirectly}
1434
1435Alternatively, you can import new plugins directly from the CrypTool 2 interface. Just run \mbox{CrypWin.exe} and select the \textit{Download Plugins} button. An \textit{Open File Dialog} window will open and ask where the new plugin is located. After selecting the new plugin, CrypTool 2 will automatically import the plugin to the custom storage folder. With this option you will not have to restart the program. All corresponding menu entries will be updated automatically. Note that this import function only accepts \textbf{signed} plugins, and also that this option is just a temporary solution: in the future this will be done online by a web service.
1436\clearpage
1437
1438\subsection{Using build settings}
1439\label{sec:UsingBuildSettings}
1440
1441Yet another option is to use the build settings in your plugin's project properties to copy the DLL automatically after building it in Visual Studio. To set this up, right-click on your plugin project and select \textit{Properties}:
1442
1443\begin{figure}[h]
1444        \centering
1445                \includegraphics{figures/solution_properties.JPG}
1446        \caption{Selecting the solution properties.}
1447        \label{fig:solution_properties}
1448\end{figure}
1449\clearpage
1450
1451\noindent Then select \textit{Build Events}:
1452
1453\begin{figure}[h]
1454        \centering
1455                \includegraphics{figures/post_build.JPG}
1456        \caption{Setting the build events.}
1457        \label{fig:post_build}
1458\end{figure}
1459
1460\noindent And finally, enter the following text into the \textit{Post-build event command line} field:\\\\
1461cd "\$(ProjectDir)" \\
1462cd ..\textbackslash ..\textbackslash CrypWin\textbackslash bin\textbackslash Debug\\
1463if not exist ".\textbackslash CrypPlugins" mkdir ".\textbackslash CrypPlugins"\\
1464del /F /S /Q /s /q "\colorbox{yellow}{Caesar}*.*"\\
1465copy "\$(TargetDir)\colorbox{yellow}{Caesar}*.*" ".\textbackslash CrypPlugins"\\\\
1466You will need to change the highlighted fields to your particular plugin's name.
1467\clearpage
1468
1469\section{Drawing the workflow of your plugin}
1470\label{DrawingTheWorkfloweOfYourPlugin}
1471
1472Each plugin should have an associated workflow file to show the algorithm in action in CrypTool 2. Such a file can be automatically created by simply saving a CrypTool 2 workspace project featuring your plugin. Below is a possible workflow for our Caesar example:
1473
1474\begin{figure}[h]
1475        \centering
1476                \includegraphics{figures/sample.jpg}
1477        \caption{A sample workflow diagram for the Caesar algorithm.}
1478        \label{fig:sample}
1479\end{figure}
Note: See TracBrowser for help on using the repository browser.