aboutsummaryrefslogtreecommitdiffstats
path: root/doc/examples
diff options
context:
space:
mode:
Diffstat (limited to 'doc/examples')
-rw-r--r--doc/examples/gtk/Makefile18
-rw-r--r--doc/examples/gtk/dsa.cpp566
-rw-r--r--doc/examples/gtk/gtk_ui.cpp79
-rw-r--r--doc/examples/gtk/gtk_ui.h27
-rw-r--r--doc/examples/gtk/readme.txt18
5 files changed, 0 insertions, 708 deletions
diff --git a/doc/examples/gtk/Makefile b/doc/examples/gtk/Makefile
deleted file mode 100644
index 10e069bb3..000000000
--- a/doc/examples/gtk/Makefile
+++ /dev/null
@@ -1,18 +0,0 @@
-
-LIBS=$(shell botan-config --libs) $(shell pkg-config --libs gtk+-2.0)
-IFLAGS=$(shell botan-config --cflags) $(shell pkg-config --cflags gtk+-2.0)
-
-CXX = g++
-CXXFLAGS = -Wall -W $(IFLAGS)
-
-dsa: gtk_ui.o dsa.o
- $(CXX) $^ $(LIBS) -o $@
-
-gtk_ui.o: gtk_ui.cpp gtk_ui.h
- $(CXX) $(CXXFLAGS) -c $< -o $@
-
-dsa.o: dsa.cpp gtk_ui.h
- $(CXX) $(CXXFLAGS) -c $< -o $@
-
-clean:
- rm -f dsa *.o
diff --git a/doc/examples/gtk/dsa.cpp b/doc/examples/gtk/dsa.cpp
deleted file mode 100644
index 2cd91b0e8..000000000
--- a/doc/examples/gtk/dsa.cpp
+++ /dev/null
@@ -1,566 +0,0 @@
-/*
- This shows some of the details involved in a GUI application that uses
- Botan. Actually most of the code is just dealing with GTK+, but it shows how
- the password callback and pulse function stuff works. (See gtk_ui.cpp for the
- acutal password callback code.)
-
- The major points of interest (assuming what you care about is how to use
- Botan from a GUI, and not looking at my terrible GTK code) are gtk_ui.cpp
- and, in this file, GTK_Pulse, gen_key(), and get_key():
-
- gtk_ui.cpp and get_key() show how to get a passphrase from a user for
- decrypting (well, in theory, anything), but in this case, PKCS #8 private
- keys. Which is coincidentally the only thing Botan currently uses UI
- objects for, though that will probably change eventually. GTK_UI does
- double duty, for getting passphrases for encryption as well (in
- do_save_key).
-
- gen_key() and GTK_Pulse show how to do an activity meter while doing a
- long-term operation inside Botan. Since, typically, the only operations
- which take a long time and can't be broken up into smaller parts are prime
- generation/testing, that is currently where the pulse hooks are
- called. It's certainly not the most general callback method in the world,
- but it's general enough that it's usable without getting in the way too
- much. The callbacks will eventually be extended to other parts of the
- library (Pipe, maybe) where it's useful.
-
- This program is in the public domain.
-*/
-#include <fstream>
-#include <iostream>
-#include <memory>
-
-#include <botan/botan.h>
-#include <botan/libstate.h>
-#include <botan/look_pk.h>
-#include <botan/filters.h>
-#include <botan/pk_filts.h>
-#include <botan/dsa.h>
-
-// we don't have a 'using namespace' here, so it's easy to grep for code that
-// is actually dealing with the library (rather than messing around with GTK).
-
-#include <gtk/gtk.h>
-#include "gtk_ui.h"
-
-static Botan::RandomNumberGenerator* rng = 0;
-
-/*
-* Pop up an message box
-*/
-static void show_dialog(const std::string& about_message,
- const std::string& dialog_name)
- {
- GtkDialogFlags flags =
- (GtkDialogFlags)(GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL);
-
- GtkWidget* dialog = gtk_dialog_new_with_buttons(dialog_name.c_str(),
- NULL, flags,
- GTK_STOCK_OK,
- GTK_RESPONSE_NONE,
- NULL);
- GtkWidget* label = gtk_label_new(NULL);
- gtk_label_set_markup(GTK_LABEL(label), about_message.c_str());
- gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER);
-
- g_signal_connect_swapped(GTK_OBJECT(dialog), "response",
- G_CALLBACK(gtk_widget_destroy),
- GTK_OBJECT(dialog));
-
- gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label);
- gtk_widget_show_all(dialog);
- }
-
-/*
-* Pop up an About box
-*/
-static void show_about()
- {
- const std::string about_message =
- "<big>DSA Utility</big>\n"
- "\n"
- "A simple application showing how to use Botan within a GUI.\n"
- "It lets you generate or load keys, and sign text files.\n"
- "\n"
- "Send comments/questions to <tt>[email protected]</tt>";
-
- show_dialog(about_message, "About");
- }
-
-/*
-* Pop up a help box
-*/
-static void show_help()
- {
- const std::string help_message =
- "<big>DSA Utility Help</big>\n"
- "\n"
- "Simply, this is a (very) simple text editor, with the added ability\n"
- "of being able to generate or read a DSA private key, and sign the\n"
- "text buffer using that key.\n"
- "\n"
- "You can load, edit, and save text files as you would normally. If a\n"
- "key is loaded (done using the commands in the Keys menu), you can\n"
- "also use the Sign command (in the Signing menu) to generate a\n"
- "signature for the current file. It will be displayed at the bottom\n"
- "of the screen (if it has been calculated for the current buffer\n"
- "contents), and can be saved using the \"Save Sig\" command.\n"
- "\n"
- "Signatures generated by this program can be verified using a the\n"
- "<tt>dsa_ver</tt> example included in the Botan distribution.\n";
-
- show_dialog(help_message, "Help");
- }
-
-/*
-* Get and return a filename from the user
-*/
-static std::string get_filename(const std::string& title)
- {
- GtkWidget* dialog = gtk_file_selection_new(title.c_str());
-
- /* Some window managers don't display the titles of transient windows,
- put a message elsewhere for those people.
- */
- GtkWidget* label = gtk_label_new(title.c_str());
- gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label);
-
- std::string fsname;
-
- gtk_widget_show(label); /* dialog_run won't show sub-widgets */
- if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
- fsname = gtk_file_selection_get_filename(GTK_FILE_SELECTION(dialog));
- gtk_widget_destroy(dialog);
-
- /* If it's a directory, that's no good */
- if(fsname.size() && fsname[fsname.size()-1] == '/')
- return "";
-
- return fsname;
- }
-
-/*
-* Global state
-*/
-static Botan::DSA_PrivateKey* key = 0; // our key
-static GtkTextBuffer* buffer = 0; // the text buffer
-static std::string buffer_source;
- // what file (if any) the buffer's data came from
-static GtkWidget* sig_view = 0; // the signature
-
-/*
-* Zap the currently set signature (if any)
-*/
-static void zap_sig()
- {
- gtk_editable_delete_text(GTK_EDITABLE(sig_view), 0, -1);
- }
-
-/*
-* Save the current key
-*/
-static void do_save_key(const std::string& title)
- {
- if(key == 0)
- return;
-
- std::string filename = get_filename(title.c_str());
-
- if(filename != "")
- {
- const std::string msg = "Select a passphrase to encrypt the key:";
-
- std::ofstream out_priv(filename.c_str());
-
- GTK_UI ui;
- Botan::User_Interface::UI_Result result;
- std::string passphrase = ui.get_passphrase(msg, result);
-
- if(result == Botan::User_Interface::OK)
- out_priv << Botan::PKCS8::PEM_encode(*key, *rng, passphrase);
- else
- out_priv << Botan::PKCS8::PEM_encode(*key);
-
- // for testing
- //std::cout << X509::PEM_encode(*key);
- }
- }
-
-/*
-* Generate a signature for the text buffer
-*/
-static void sign_buffer()
- {
- /* No key? Ignore request. */
- if(key == 0)
- return;
-
- /* same format as the text-mode dsa_sign example */
- Botan::Pipe pipe(new Botan::PK_Signer_Filter(
- Botan::get_pk_signer(*key, "EMSA1(SHA-1)"), *rng
- ),
- new Botan::Base64_Encoder
- );
-
- /* It would probably be smart to do this a little bit at a time */
- GtkTextIter start, end;
- gtk_text_buffer_get_bounds(buffer, &start, &end);
- gchar* bits = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
- size_t length = strlen(bits);
-
- pipe.start_msg();
- pipe.write((unsigned char*)bits, length);
- pipe.end_msg();
-
- std::string sig = pipe.read_all_as_string();
-
- zap_sig();
-
- gint position = 0;
- gtk_editable_insert_text(GTK_EDITABLE(sig_view), sig.c_str(), sig.length(),
- &position);
-
- g_free(bits);
- }
-
-#if 0
-/*
-* GTK+ pulse callback
-*/
-class GTK_Pulse : public Botan::Library_State::UI
- {
- public:
- void pulse(Botan::Pulse_Type);
- };
-
-void GTK_Pulse::pulse(Botan::Pulse_Type)
- {
- /* We need this to flush the updates, otherwise GTK+ will wait until we're
- done with the computation before doing any updates (generally the right
- thing, but not with a progress bar).
- */
-
- while(gtk_events_pending())
- gtk_main_iteration();
- }
-#endif
-
-/*
-* Actual do the pulse (as a GTK+ timeout func) *
-*/
-static gboolean gtk_pulse_timeout(void* pbar)
- {
- GtkWidget* progress_bar = (GtkWidget*)pbar;
- gtk_progress_bar_pulse(GTK_PROGRESS_BAR(progress_bar));
- return TRUE; /* keep calling us */
- }
-
-/*
-* Generate a new key
-*/
-static void gen_key()
- {
- /* This gives a nice smooth progress bar, though we do use up quite a bit of
- CPU for it. Keep in mind that if PULSE_INTERVAL is significantly less
- than the average time between pulses from the library, the progress bar
- will jerk around going slower or faster. Keep it at at least 50ms.
- */
- const double PROGRESS_PER_PULSE = .01; /* % of bar */
- const guint32 PULSE_INTERVAL = 30; /* ms */
-
- delete key;
-
- GtkDialogFlags flags =
- (GtkDialogFlags)(GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL);
-
- GtkWidget* dialog =
- gtk_dialog_new_with_buttons("Generating Key", NULL, flags, NULL);
-
- GtkWidget* label = gtk_label_new(" Generating new key, please wait... \n");
- gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label);
-
- GtkWidget* progress_bar = gtk_progress_bar_new();
- gtk_progress_bar_set_pulse_step(GTK_PROGRESS_BAR(progress_bar),
- PROGRESS_PER_PULSE);
- gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), progress_bar);
-
- guint timer_id = gtk_timeout_add(PULSE_INTERVAL, gtk_pulse_timeout,
- progress_bar);
-
- gtk_widget_show_all(dialog);
-
- while(gtk_events_pending())
- gtk_main_iteration();
-
- /* Register gtk_pulse so it will be called every so often when we embark
- on our prime generation quest...
- */
- /* this just updates the GUI; the GTK+ timeout function actually updates
- the progress bar. That's because the amount of time between pulses
- from the library is rather irregular, so the progress bar looks jerky.
- */
- //Botan::global_state().set_ui(new GTK_Pulse);
-
- /* Not generally recommended, since it's slow and there's not much point.
- However, *because* it's slow, we'll want to put up a progress bar or
- something, and part of this whole thing is to show how to do that and get
- the pulse functions to do the right thing.
- */
- Botan::DL_Group group(*rng, Botan::DL_Group::DSA_Kosherizer, 1024);
- key = new Botan::DSA_PrivateKey(*rng, group);
-
- gtk_timeout_remove(timer_id);
- //Botan::global_state().set_ui(0); // unset the pulse function
-
- gtk_widget_destroy(dialog);
-
- do_save_key("Save New Key");
-
- /* new key, any old sigs are no longer useful */
- zap_sig();
- }
-
-/*
-* Load up a key
-*/
-static void get_key()
- {
- std::string fsname = get_filename("Select a DSA Key");
-
- if(fsname != "")
- {
- try {
- delete key;
- key = 0;
- zap_sig();
-
- /*
- A GTK_UI is a subclass of User_Interface that pops up a dialog that
- asks the user for a passphrase. It actually works quite well,
- though the fixed upper limit on the passphrase size is not
- ideal. Feel free to use it as-is or modify it however you like
- (gtk_ui.* is public domain).
- */
- GTK_UI ui;
- Botan::PKCS8_PrivateKey* p8_key =
- Botan::PKCS8::load_key(fsname, *rng, ui);
-
- key = dynamic_cast<Botan::DSA_PrivateKey*>(p8_key);
- if(!key)
- show_dialog("The key in " + fsname + " is not a DSA key",
- "Failure");
- }
- catch(std::exception)
- {
- key = 0; // make sure it's not something random
- show_dialog("Loading the key from " + fsname + " failed.", "Failure");
- }
- }
- }
-
-static void really_sign_buffer()
- {
- /* No key? Ask the user for one. */
- if(key == 0)
- get_key();
- sign_buffer();
- }
-
-/*
-* Clear the text buffer
-*/
-static void new_buffer()
- {
- /*
- In theory, it would be nice to check if this was unsaved text and prompt
- to save it. However, this really isn't supposed to be a GTK+ example, so
- we won't.
- */
- gtk_text_buffer_set_text(buffer, "", -1);
- buffer_source = "";
- }
-
-/*
-* Put the contents of a file into the buffer
-*/
-static void open_buffer()
- {
- std::string filename = get_filename("Select File");
-
- if(filename == "")
- return;
-
- std::ifstream in(filename.c_str());
-
- new_buffer();
- buffer_source = filename;
-
- while(in.good())
- {
- char buf[1024] = { 0 };
-
- in.read(buf, 1024);
- size_t got = in.gcount();
-
- GtkTextIter iter;
- gtk_text_buffer_get_end_iter(buffer, &iter);
- gtk_text_buffer_insert(buffer, &iter, buf, got);
- }
- }
-
-/*
-* Save the signature to a file
-*/
-static void save_sig()
- {
- std::string sig_file = buffer_source;
-
- /* No sig, nothing to save */
- const gchar* sig = gtk_entry_get_text(GTK_ENTRY(sig_view));
- if(strlen(sig) == 0)
- return;
-
- if(sig_file == "")
- sig_file = get_filename("Select Signature Output File");
- else
- sig_file += ".sig";
-
- std::ofstream out(sig_file.c_str());
- out << sig << std::endl;
- }
-
-/*
-* Save the current key
-*/
-static void save_key()
- {
- do_save_key("Save Current Key");
- }
-
-/*
-* Common case of Save/Save As
-*/
-static void do_save(const std::string& filename)
- {
- std::ofstream out(filename.c_str());
-
- GtkTextIter start, end;
- gtk_text_buffer_get_bounds(buffer, &start, &end);
- gchar* bits = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
- out.write(bits, strlen(bits));
- g_free(bits);
- buffer_source = filename;
- }
-
-/*
-* Save the buffer
-*/
-static void save_buffer_as()
- {
- std::string filename = get_filename("Select Output File");
- if(filename != "")
- do_save(filename);
- }
-
-/*
-* Save the buffer
-*/
-static void save_buffer()
- {
- if(buffer_source != "")
- do_save(buffer_source);
- else
- save_buffer_as();
- }
-
-/*
-* Make a menubar for the app
-*/
-static GtkWidget* make_menubar(GtkWidget *window)
- {
- static GtkItemFactoryEntry menu_items[] = {
- { "/_File", NULL, NULL, 0, "<Branch>", NULL },
- { "/File/_New", "<control>N", new_buffer, 0, NULL, NULL },
- { "/File/_Open", "<control>O", open_buffer, 0, NULL, NULL },
- { "/File/_Save", "<control>S", save_buffer, 0, NULL, NULL },
- { "/File/Save _As", NULL, save_buffer_as, 0, NULL, NULL },
- { "/File/sep1", NULL, NULL, 0, "<Separator>", NULL },
- { "/File/Save Sig", NULL, save_sig, 0, NULL, NULL },
- { "/File/sep2", NULL, NULL, 0, "<Separator>", NULL },
- { "/File/_Quit", "<control>Q", gtk_main_quit, 0, NULL, NULL },
-
- { "/_Keys", NULL, NULL, 0, "<Branch>", NULL },
- { "/Keys/Open", NULL, get_key, 0, NULL, NULL },
- { "/Keys/_Generate", NULL, gen_key, 0, NULL, NULL },
- { "/Keys/Save Current", NULL, save_key, 0, NULL, NULL },
-
- { "/Signing", NULL, NULL, 0, "<Branch>", NULL },
- { "/Signing/Sign", NULL, really_sign_buffer, 0, NULL, NULL },
-
- { "/_Help", NULL, NULL, 0, "<LastBranch>", NULL },
- { "/Help/Help", NULL, show_help, 0, NULL, NULL },
- { "/Help/sep1", NULL, NULL, 0, "<Separator>", NULL },
- { "/Help/About", NULL, show_about, 0, NULL, NULL },
- };
-
- GtkAccelGroup* accel_group = gtk_accel_group_new();
- GtkItemFactory* item_factory =
- gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", accel_group);
- const gint nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);
- gtk_item_factory_create_items(item_factory, nmenu_items, menu_items, NULL);
- gtk_window_add_accel_group(GTK_WINDOW(window), accel_group);
- return gtk_item_factory_get_widget(item_factory, "<main>");
- }
-
-int main(int argc, char *argv[])
- {
- gtk_init(&argc, &argv);
-
- try {
- Botan::LibraryInitializer init;
-
- rng = new Botan::AutoSeeded_RNG;
-
- /* Create a new top-level window */
- GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- gtk_window_set_title(GTK_WINDOW(window), "DSA Utility");
- gtk_signal_connect(GTK_OBJECT(window), "delete_event",
- gtk_main_quit, NULL);
-
- /* Create the vbox to hold our stuff */
- GtkWidget* vbox = gtk_vbox_new(FALSE, 0);
- gtk_container_border_width(GTK_CONTAINER(vbox), 1);
- gtk_container_add(GTK_CONTAINER(window), vbox);
-
- /* Create the menu bar */
- GtkWidget *menubar = make_menubar(window);
-
- /* Create the entry that holds the signature */
- sig_view = gtk_entry_new();
- gtk_editable_set_editable(GTK_EDITABLE(sig_view), FALSE);
-
- /* Create the text box */
- GtkWidget* view = gtk_text_view_new();
- buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(view));
-
- gtk_widget_set_size_request(view, 640, 480);
- gtk_text_buffer_set_text(buffer, "Some initial contents.", -1);
-
- // Resign it on each change: fast enough, but probably not really useful
- //g_signal_connect(G_OBJECT(buffer), "changed", sign_buffer, 0);
- g_signal_connect(G_OBJECT(buffer), "changed", zap_sig, 0);
-
- gtk_container_add(GTK_CONTAINER(vbox), menubar);
- gtk_container_add(GTK_CONTAINER(vbox), view);
- gtk_container_add(GTK_CONTAINER(vbox), sig_view);
-
- gtk_widget_show_all(window);
-
- gtk_main();
- }
- catch(std::exception& e)
- {
- std::cout << e.what() << std::endl;
- }
- return 0;
- }
diff --git a/doc/examples/gtk/gtk_ui.cpp b/doc/examples/gtk/gtk_ui.cpp
deleted file mode 100644
index d4e9cd238..000000000
--- a/doc/examples/gtk/gtk_ui.cpp
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
-* GTK+ User Interface Source File
-*/
-
-#include "gtk_ui.h"
-#include <cstring>
-
-/*
-* GTK+ Callback *
-*/
-void GTK_UI::callback(GtkWidget* entry, gpointer passphrase_ptr)
- {
- const gchar *entry_text = gtk_entry_get_text(GTK_ENTRY(entry));
- char* passphrase = (char*)passphrase_ptr;
- std::strcpy(passphrase, entry_text);
- }
-
-/*
-* Get a passphrase from the user
-*/
-std::string GTK_UI::get_passphrase(const std::string& what,
- const std::string& source,
- UI_Result& result) const
- {
- std::string msg = "A passphrase is needed to access the " + what;
- if(source != "") msg += "\nin " + source;
- return get_passphrase(msg, result);
- }
-
-/*
-* Get a passphrase from the user
-*/
-std::string GTK_UI::get_passphrase(const std::string& label_text,
- UI_Result& result) const
- {
- const int MAX_PASSPHRASE = 64;
-
- GtkDialogFlags flags =
- (GtkDialogFlags)(GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL);
-
- GtkWidget* dialog = gtk_dialog_new_with_buttons(
- "Enter Passphrase",
- NULL, flags,
- GTK_STOCK_OK, GTK_RESPONSE_OK,
- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- NULL);
-
- gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK);
-
- GtkWidget* label = gtk_label_new(label_text.c_str());
-
- GtkWidget* entry = gtk_entry_new();
- gtk_entry_set_visibility(GTK_ENTRY(entry), 0);
- gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE);
- gtk_entry_set_max_length(GTK_ENTRY(entry), MAX_PASSPHRASE);
-
- char passphrase_buf[MAX_PASSPHRASE + 1] = { 0 };
-
- gtk_signal_connect(GTK_OBJECT(entry), "activate",
- GTK_SIGNAL_FUNC(callback), passphrase_buf);
-
- GtkWidget* vbox = gtk_vbox_new(FALSE, 0);
- gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
- gtk_box_pack_start(GTK_BOX(vbox), entry, FALSE, FALSE, 0);
-
- gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), vbox, TRUE, TRUE, 0);
- gtk_widget_show_all(vbox);
-
- /* Block until we get something back */
- result = CANCEL_ACTION;
- if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
- result = OK;
-
- gtk_widget_destroy(dialog);
-
- if(result == OK)
- return std::string(passphrase_buf);
- return "";
- }
diff --git a/doc/examples/gtk/gtk_ui.h b/doc/examples/gtk/gtk_ui.h
deleted file mode 100644
index 065a4f76b..000000000
--- a/doc/examples/gtk/gtk_ui.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
-* (C) 2006 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-#ifndef BOTAN_EXT_GTK_UI__
-#define BOTAN_EXT_GTK_UI__
-
-#include <botan/ui.h>
-#include <gtk/gtk.h>
-
-/*
-* GTK+ Passphrase Callback Object
-*/
-class GTK_UI : public Botan::User_Interface
- {
- public:
- std::string get_passphrase(const std::string&, const std::string&,
- UI_Result&) const;
-
- std::string get_passphrase(const std::string&, UI_Result&) const;
-
- static void callback(GtkWidget*, gpointer);
- };
-
-#endif
diff --git a/doc/examples/gtk/readme.txt b/doc/examples/gtk/readme.txt
deleted file mode 100644
index 4f3691166..000000000
--- a/doc/examples/gtk/readme.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-
-This is an example of how to use Botan in a GUI. You need at least
-Botan 1.6.0.
-
-You'll also need GTK+ 2.x (tested with GTK+ 2.10; should work with
-most versions). Keep in mind that I was learning GTK as I was writing
-this code, so it is not exactly the best GTK code you're likely to
-see.
-
-dsa.cpp is the main GTK+ driver. It has some comments at the top which
-point out major areas of interest.
-
-gtk_ui.* implement a User_Interface object that opens up a GTK+ dialog
-box that asks the user for their passphrase. It works pretty well, the
-only major deficiency is a fixed upper limit on the size of the
-passphrase (currently 64). You may want to use this in your own code,
-assuming you use GTK. If not, it should at least provide an outline
-for writing a version for your favorite windowing system.