From 54c692330a98dc29023ec370a664b5adae621c89 Mon Sep 17 00:00:00 2001 From: rdb Date: Wed, 9 Mar 2011 11:16:20 +0000 Subject: [PATCH] rewrite p3dcert to FLTK --- direct/src/plugin/Sources.pp | 9 +- direct/src/plugin/p3dCert.cxx | 415 +++++++++----------- direct/src/plugin/p3dCert.h | 52 +-- direct/src/plugin/p3dCert_wx.cxx | 627 +++++++++++++++++++++++++++++++ direct/src/plugin/p3dCert_wx.h | 127 +++++++ dtool/Config.pp | 32 +- dtool/LocalSetup.pp | 5 + dtool/Package.pp | 18 + dtool/pptempl/Global.pp | 9 + makepanda/makepanda.py | 25 +- 10 files changed, 1035 insertions(+), 284 deletions(-) create mode 100644 direct/src/plugin/p3dCert_wx.cxx create mode 100644 direct/src/plugin/p3dCert_wx.h diff --git a/direct/src/plugin/Sources.pp b/direct/src/plugin/Sources.pp index dad051c6d1..937e9efabe 100644 --- a/direct/src/plugin/Sources.pp +++ b/direct/src/plugin/Sources.pp @@ -159,12 +159,17 @@ // red "play" button to approve an unknown certificate. Considered // part of the Core API, though it is a separate download. // - +#if $[HAVE_FLTK] + #define BUILD_TARGET $[and $[HAVE_P3D_PLUGIN],$[HAVE_FLTK],$[HAVE_OPENSSL]] + #define USE_PACKAGES fltk openssl + #define SOURCES p3dCert.cxx p3dCert.h +#else #define BUILD_TARGET $[and $[HAVE_P3D_PLUGIN],$[HAVE_WX],$[HAVE_OPENSSL]] #define USE_PACKAGES wx openssl + #define SOURCES p3dCert_wx.cxx p3dCert_wx.h +#endif #define TARGET p3dcert - #define SOURCES p3dCert.cxx p3dCert.h #define OSX_SYS_FRAMEWORKS Carbon #end bin_target diff --git a/direct/src/plugin/p3dCert.cxx b/direct/src/plugin/p3dCert.cxx index cc552a4a2e..1b374a273d 100644 --- a/direct/src/plugin/p3dCert.cxx +++ b/direct/src/plugin/p3dCert.cxx @@ -1,5 +1,5 @@ // Filename: p3dCert.cxx -// Created by: drose (11Sep09) +// Created by: rdb (08Mar11) // //////////////////////////////////////////////////////////////////// // @@ -13,140 +13,103 @@ //////////////////////////////////////////////////////////////////// #include "p3dCert.h" -#include "wx/cmdline.h" -#include "wx/filename.h" + +#include +#include +#include +#include + +#include +#include +#include + +#define BUTTON_WIDTH 120 +#define BUTTON_SPACE 10 #include "ca_bundle_data_src.c" -static const wxString -self_signed_cert_text = - _T("This Panda3D application uses a self-signed certificate. ") - _T("This means the author's name can't be verified, and you have ") - _T("no way of knowing for sure who wrote it.\n\n") +#ifdef _WIN32 +#define snprintf sprintf_s +#endif - _T("We recommend you click Cancel to avoid running this application."); +static const char +self_signed_cert_text[] = + "This Panda3D application uses a self-signed certificate. " + "This means the author's name can't be verified, and you have " + "no way of knowing for sure who wrote it.\n\n" -static const wxString -unknown_auth_cert_text = - _T("This Panda3D application has been signed, but we don't recognize ") - _T("the authority that verifies the signature. This means the author's ") - _T("name can't be trusted, and you have no way of knowing ") - _T("for sure who wrote it.\n\n") + "We recommend you click Cancel to avoid running this application."; - _T("We recommend you click Cancel to avoid running this application."); +static const char +unknown_auth_cert_text[] = + "This Panda3D application has been signed, but we don't recognize " + "the authority that verifies the signature. This means the author's " + "name can't be trusted, and you have no way of knowing " + "for sure who wrote it.\n\n" -static const wxString -verified_cert_text = - _T("This Panda3D application has been signed by %s. ") - _T("If you trust %s, then click the Run button below ") - _T("to run this application on your computer. This will also ") - _T("automatically approve this and any other applications signed by ") - _T("%s in the future.\n\n") + "We recommend you click Cancel to avoid running this application."; - _T("If you are unsure about this application, ") - _T("you should click Cancel instead."); +static const char +verified_cert_text[] = + "This Panda3D application has been signed by %s. " + "If you trust %s, then click the Run button below " + "to run this application on your computer. This will also " + "automatically approve this and any other applications signed by " + "%s in the future.\n\n" -static const wxString -expired_cert_text = - _T("This Panda3D application has been signed by %s, ") - _T("but the certificate has expired.\n\n") + "If you are unsure about this application, " + "you should click Cancel instead."; - _T("You should check the current date set on your computer's clock ") - _T("to make sure it is correct.\n\n") +static const char +expired_cert_text[] = + "This Panda3D application has been signed by %s, " + "but the certificate has expired.\n\n" - _T("If your computer's date is correct, we recommend ") - _T("you click Cancel to avoid running this application."); + "You should check the current date set on your computer's clock " + "to make sure it is correct.\n\n" -static const wxString -generic_error_cert_text = - _T("This Panda3D application has been signed, but there is a problem ") - _T("with the certificate (OpenSSL error code %d).\n\n") + "If your computer's date is correct, we recommend " + "you click Cancel to avoid running this application."; - _T("We recommend you click Cancel to avoid running this application."); +static const char +generic_error_cert_text[] = + "This Panda3D application has been signed, but there is a problem " + "with the certificate (OpenSSL error code %d).\n\n" -static const wxString -no_cert_text = - _T("This Panda3D application has not been signed. This means you have ") - _T("no way of knowing for sure who wrote it.\n\n") + "We recommend you click Cancel to avoid running this application."; - _T("Click Cancel to avoid running this application."); +static const char +no_cert_text[] = + "This Panda3D application has not been signed. This means you have " + "no way of knowing for sure who wrote it.\n\n" -// wxWidgets boilerplate macro to define main() and start up the -// application. -IMPLEMENT_APP(P3DCertApp) - -//////////////////////////////////////////////////////////////////// -// Function: P3DCertApp::OnInit -// Access: Public, Virtual -// Description: The "main" of a wx application. This is the first -// entry point. -//////////////////////////////////////////////////////////////////// -bool P3DCertApp:: -OnInit() { - // call the base class initialization method, currently it only parses a - // few common command-line options but it could be do more in the future - if (!wxApp::OnInit()) { - return false; - } + "Click Cancel to avoid running this application."; +int main(int argc, char **argv) { OpenSSL_add_all_algorithms(); - AuthDialog *dialog = new AuthDialog(_cert_filename, _cert_dir); - SetTopWindow(dialog); - dialog->Show(true); - dialog->SetFocus(); - dialog->Raise(); + if (argc != 3) { + cerr << "usage: p3dcert cert_filename cert_dir\n"; + return 1; + } - // Return true to enter the main loop and wait for user input. - return true; + string cert_filename (argv[1]); + string cert_dir (argv[2]); + + AuthDialog *dialog = new AuthDialog(cert_filename, cert_dir); + dialog->show(1, argv); + + return Fl::run(); } -//////////////////////////////////////////////////////////////////// -// Function: P3DCertApp::OnInitCmdLine -// Access: Public, Virtual -// Description: A callback to initialize the parser with the command -// line options. -//////////////////////////////////////////////////////////////////// -void P3DCertApp:: -OnInitCmdLine(wxCmdLineParser &parser) { - parser.AddParam(); - parser.AddParam(); -} - -//////////////////////////////////////////////////////////////////// -// Function: P3DCertApp::OnCmdLineParsed -// Access: Public, Virtual -// Description: A callback after the successful parsing of the -// command line. -//////////////////////////////////////////////////////////////////// -bool P3DCertApp:: -OnCmdLineParsed(wxCmdLineParser &parser) { - _cert_filename = parser.GetParam(0); - _cert_dir = parser.GetParam(1); - return true; -} - - -// The event table for AuthDialog. -#define VIEW_CERT_BUTTON (wxID_HIGHEST + 1) -BEGIN_EVENT_TABLE(AuthDialog, wxDialog) - EVT_BUTTON(wxID_OK, AuthDialog::run_clicked) - EVT_BUTTON(VIEW_CERT_BUTTON, AuthDialog::view_cert_clicked) - EVT_BUTTON(wxID_CANCEL, AuthDialog::cancel_clicked) -END_EVENT_TABLE() - //////////////////////////////////////////////////////////////////// // Function: AuthDialog::Constructor // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// AuthDialog:: -AuthDialog(const wxString &cert_filename, const wxString &cert_dir) : - // I hate stay-on-top dialogs, but if we don't set this flag, it - // doesn't come to the foreground on OSX, and might be lost behind - // the browser window. - wxDialog(NULL, wxID_ANY, _T("New Panda3D Application"), wxDefaultPosition, - wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxSTAY_ON_TOP), +AuthDialog(const string &cert_filename, const string &cert_dir) : + Fl_Window(435, 242, "New Panda3D Application"), _cert_dir(cert_dir) { _view_cert_dialog = NULL; @@ -164,19 +127,19 @@ AuthDialog(const wxString &cert_filename, const wxString &cert_dir) : //////////////////////////////////////////////////////////////////// // Function: AuthDialog::Destructor // Access: Public, Virtual -// Description: +// Description: //////////////////////////////////////////////////////////////////// AuthDialog:: ~AuthDialog() { if (_view_cert_dialog != NULL) { - _view_cert_dialog->Destroy(); + _view_cert_dialog->hide(); } - if (_cert != NULL) { + if (_cert != NULL) { X509_free(_cert); _cert = NULL; } - if (_stack != NULL) { + if (_stack != NULL) { sk_X509_free(_stack); _stack = NULL; } @@ -188,8 +151,9 @@ AuthDialog:: // Description: The user clicks the "Run" button. //////////////////////////////////////////////////////////////////// void AuthDialog:: -run_clicked(wxCommandEvent &event) { - approve_cert(); +run_clicked(Fl_Widget *w, void *data) { + AuthDialog *dlg = (AuthDialog *) data; + dlg->approve_cert(); } //////////////////////////////////////////////////////////////////// @@ -198,13 +162,15 @@ run_clicked(wxCommandEvent &event) { // Description: The user clicks the "View Certificate" button. //////////////////////////////////////////////////////////////////// void AuthDialog:: -view_cert_clicked(wxCommandEvent &event) { - if (_view_cert_dialog != NULL) { - _view_cert_dialog->Destroy(); +view_cert_clicked(Fl_Widget *w, void *data) { + AuthDialog *dlg = (AuthDialog *) data; + + if (dlg->_view_cert_dialog != NULL) { + dlg->_view_cert_dialog->hide(); } - Hide(); - _view_cert_dialog = new ViewCertDialog(this, _cert); - _view_cert_dialog->Show(); + dlg->hide(); + dlg->_view_cert_dialog = new ViewCertDialog(dlg, dlg->_cert); + dlg->_view_cert_dialog->show(); } //////////////////////////////////////////////////////////////////// @@ -213,8 +179,9 @@ view_cert_clicked(wxCommandEvent &event) { // Description: The user clicks the "Cancel" button. //////////////////////////////////////////////////////////////////// void AuthDialog:: -cancel_clicked(wxCommandEvent &event) { - Destroy(); +cancel_clicked(Fl_Widget *w, void *data) { + AuthDialog *dlg = (AuthDialog *) data; + dlg->hide(); } //////////////////////////////////////////////////////////////////// @@ -229,27 +196,42 @@ approve_cert() { assert(_cert != NULL); // Make sure the directory exists. - wxFileName::Mkdir(_cert_dir, 0777, wxPATH_MKDIR_FULL); +#ifdef _WIN32 + mkdir(_cert_dir.c_str()); +#else + mkdir(_cert_dir.c_str(), 0755); +#endif // Look for an unused filename. - wxString pathname; + string pathname; int i = 1; + char buf [PATH_MAX]; while (true) { - pathname.Printf(wxT("%s/p%d.crt"), _cert_dir.c_str(), i); - if (!wxFileName::FileExists(pathname)) { + sprintf(buf, "%s/p%d.crt", _cert_dir.c_str(), i); + + // Check if it already exists. If not, take it. +#ifdef _WIN32 + DWORD results = GetFileAttributes(buf); + if (results == -1) { break; } +#else + struct stat statbuf; + if (stat(pathname.c_str(), &statbuf) != 0) { + break; + } +#endif ++i; } // Sure, there's a slight race condition right now: another process // might attempt to create the same filename. So what. - FILE *fp = fopen(pathname.mb_str(), "w"); + FILE *fp = fopen(pathname.c_str(), "w"); if (fp != NULL) { PEM_write_X509(fp, _cert); fclose(fp); } - Destroy(); + hide(); } //////////////////////////////////////////////////////////////////// @@ -259,15 +241,15 @@ approve_cert() { // passed on the command line into _cert and _stack. //////////////////////////////////////////////////////////////////// void AuthDialog:: -read_cert_file(const wxString &cert_filename) { - FILE *fp = fopen(cert_filename.mb_str(), "r"); +read_cert_file(const string &cert_filename) { + FILE *fp = fopen(cert_filename.c_str(), "r"); if (fp == NULL) { - cerr << "Couldn't read " << cert_filename.mb_str() << "\n"; + cerr << "Couldn't read " << cert_filename.c_str() << "\n"; return; } _cert = PEM_read_X509(fp, NULL, NULL, (void *)""); if (_cert == NULL) { - cerr << "Could not read certificate in " << cert_filename.mb_str() << ".\n"; + cerr << "Could not read certificate in " << cert_filename.c_str() << ".\n"; fclose(fp); return; } @@ -323,10 +305,10 @@ get_friendly_name() { // these incomplete docs. BIO *mbio = BIO_new(BIO_s_mem()); ASN1_STRING_print_ex(mbio, data, ASN1_STRFLGS_RFC2253 & ~ASN1_STRFLGS_ESC_MSB); - + char *pp; long pp_size = BIO_get_mem_data(mbio, &pp); - _friendly_name = wxString(pp, wxConvUTF8, pp_size); + _friendly_name = string(pp, pp_size); BIO_free(mbio); return; } @@ -371,7 +353,7 @@ verify_cert() { X509_STORE_free(store); - cerr << "Got certificate from " << _friendly_name.mb_str() + cerr << "Got certificate from " << _friendly_name.c_str() << ", verify_result = " << _verify_result << "\n"; } @@ -420,51 +402,45 @@ load_certificates_from_der_ram(X509_STORE *store, //////////////////////////////////////////////////////////////////// void AuthDialog:: layout() { - wxString header, text; - get_text(header, text); + get_text(_header, sizeof _header, _text, sizeof _text); - wxPanel *panel = new wxPanel(this); - wxBoxSizer *vsizer = new wxBoxSizer(wxVERTICAL); - - wxFont font = panel->GetFont(); - wxFont *bold_font = wxTheFontList->FindOrCreateFont - ((int)(font.GetPointSize() * 1.5), - font.GetFamily(), font.GetStyle(), wxFONTWEIGHT_BOLD); - - if (!header.IsEmpty()) { - wxStaticText *text0 = new wxStaticText - (panel, wxID_ANY, header, wxDefaultPosition, wxDefaultSize, - wxALIGN_CENTER); - text0->SetFont(*bold_font); - vsizer->Add(text0, 0, wxCENTER | wxALL, 10); + if (strlen(_header) > 0) { + Fl_Box *text0 = new Fl_Box(w() / 2, 35, 0, 25, _header); + text0->align(FL_ALIGN_TOP | FL_ALIGN_CENTER); + text0->labelfont(FL_BOLD); + text0->labelsize(text0->labelsize() * 1.5); } - wxStaticText *text1 = new wxStaticText - (panel, wxID_ANY, text, wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER); - text1->Wrap(400); - vsizer->Add(text1, 0, wxCENTER | wxALL, 10); + Fl_Box *text1 = new Fl_Box(17, 55, 400, 120, _text); + text1->align(FL_ALIGN_TOP | FL_ALIGN_INSIDE | FL_ALIGN_WRAP); - // Create the run / cancel buttons. - wxBoxSizer *bsizer = new wxBoxSizer(wxHORIZONTAL); + short nbuttons = 1; + if (_cert != NULL) { + nbuttons++; + if (_verify_result == 0) { + nbuttons++; + } + } + short bx = (w() - nbuttons * BUTTON_WIDTH - (nbuttons - 1) * BUTTON_SPACE) / 2; if (_verify_result == 0 && _cert != NULL) { - wxButton *run_button = new wxButton(panel, wxID_OK, _T("Run")); - bsizer->Add(run_button, 0, wxALIGN_CENTER | wxALL, 5); + Fl_Return_Button *run_button = new Fl_Return_Button(bx, 200, BUTTON_WIDTH, 25, "Run"); + run_button->callback(this->run_clicked, this); + bx += BUTTON_WIDTH + BUTTON_SPACE; } if (_cert != NULL) { - wxButton *view_button = new wxButton(panel, VIEW_CERT_BUTTON, _T("View Certificate")); - bsizer->Add(view_button, 0, wxALIGN_CENTER | wxALL, 5); + Fl_Button *view_button = new Fl_Button(bx, 200, BUTTON_WIDTH, 25, "View Certificate"); + view_button->callback(this->view_cert_clicked, this); + bx += BUTTON_WIDTH + BUTTON_SPACE; } - wxButton *cancel_button = new wxButton(panel, wxID_CANCEL, _T("Cancel")); - bsizer->Add(cancel_button, 0, wxALIGN_CENTER | wxALL, 5); + Fl_Button *cancel_button; + cancel_button = new Fl_Button(bx, 200, BUTTON_WIDTH, 25, "Cancel"); + cancel_button->callback(this->cancel_clicked, this); - vsizer->Add(bsizer, 0, wxALIGN_CENTER | wxALL, 5); - - panel->SetSizer(vsizer); - panel->SetAutoLayout(true); - vsizer->Fit(this); + end(); + set_modal(); } //////////////////////////////////////////////////////////////////// @@ -474,58 +450,51 @@ layout() { // dialog box, based on the certificate read so far. //////////////////////////////////////////////////////////////////// void AuthDialog:: -get_text(wxString &header, wxString &text) { +get_text(char *header, size_t hlen, char *text, size_t tlen) { switch (_verify_result) { case -1: - header = _T("No signature!"); - text = no_cert_text; + strncpy(header, "No signature!", hlen); + strncpy(text, no_cert_text, tlen); break; case 0: - text.Printf(verified_cert_text, _friendly_name.c_str(), _friendly_name.c_str(), _friendly_name.c_str()); + snprintf(text, tlen, verified_cert_text, _friendly_name.c_str(), + _friendly_name.c_str(), _friendly_name.c_str()); break; case X509_V_ERR_CERT_NOT_YET_VALID: case X509_V_ERR_CERT_HAS_EXPIRED: case X509_V_ERR_CRL_NOT_YET_VALID: case X509_V_ERR_CRL_HAS_EXPIRED: - header = _T("Expired signature!"); - text.Printf(expired_cert_text, _friendly_name.c_str()); + strncpy(header, "Expired signature!", hlen); + snprintf(text, tlen, expired_cert_text, _friendly_name.c_str()); break; case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: - header = _T("Unverified signature!"); - text.Printf(unknown_auth_cert_text, _friendly_name.c_str()); + strncpy(header, "Unverified signature!", hlen); + snprintf(text, tlen, unknown_auth_cert_text, _friendly_name.c_str()); break; - + case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: - header = _T("Unverified signature!"); - text = self_signed_cert_text; + strncpy(header, "Unverified signature!", hlen); + strncpy(text, self_signed_cert_text, tlen); break; default: - header = _T("Unverified signature!"); - text.Printf(generic_error_cert_text, _verify_result); + strncpy(header, "Unverified signature!", hlen); + snprintf(text, tlen, generic_error_cert_text, _verify_result); } } - -// The event table for ViewCertDialog. -BEGIN_EVENT_TABLE(ViewCertDialog, wxDialog) - EVT_BUTTON(wxID_OK, ViewCertDialog::run_clicked) - EVT_BUTTON(wxID_CANCEL, ViewCertDialog::cancel_clicked) -END_EVENT_TABLE() - //////////////////////////////////////////////////////////////////// // Function: ViewCertDialog::Constructor // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// ViewCertDialog:: ViewCertDialog(AuthDialog *auth_dialog, X509 *cert) : -wxDialog(NULL, wxID_ANY, _T("View Certificate"), wxDefaultPosition, - wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER), + Fl_Window(600, 400, "View Certificate"), _auth_dialog(auth_dialog), _cert(cert) { @@ -535,7 +504,7 @@ wxDialog(NULL, wxID_ANY, _T("View Certificate"), wxDefaultPosition, //////////////////////////////////////////////////////////////////// // Function: ViewCertDialog::Destructor // Access: Public, Virtual -// Description: +// Description: //////////////////////////////////////////////////////////////////// ViewCertDialog:: ~ViewCertDialog() { @@ -550,11 +519,12 @@ ViewCertDialog:: // Description: The user clicks the "Run" button. //////////////////////////////////////////////////////////////////// void ViewCertDialog:: -run_clicked(wxCommandEvent &event) { - if (_auth_dialog != NULL){ - _auth_dialog->approve_cert(); +run_clicked(Fl_Widget *w, void *data) { + ViewCertDialog *dlg = (ViewCertDialog *) data; + if (dlg->_auth_dialog != NULL){ + dlg->_auth_dialog->approve_cert(); } - Destroy(); + dlg->hide(); } //////////////////////////////////////////////////////////////////// @@ -563,11 +533,12 @@ run_clicked(wxCommandEvent &event) { // Description: The user clicks the "Cancel" button. //////////////////////////////////////////////////////////////////// void ViewCertDialog:: -cancel_clicked(wxCommandEvent &event) { - if (_auth_dialog != NULL){ - _auth_dialog->Destroy(); +cancel_clicked(Fl_Widget *w, void *data) { + ViewCertDialog *dlg = (ViewCertDialog *) data; + if (dlg->_auth_dialog != NULL){ + dlg->_auth_dialog->hide(); } - Destroy(); + dlg->hide(); } //////////////////////////////////////////////////////////////////// @@ -585,43 +556,25 @@ layout() { char *pp; long pp_size = BIO_get_mem_data(mbio, &pp); - wxString cert_body(pp, wxConvUTF8, pp_size); + string cert_body(pp, pp_size); BIO_free(mbio); - wxPanel *panel = new wxPanel(this); - wxBoxSizer *vsizer = new wxBoxSizer(wxVERTICAL); + Fl_Text_Buffer *buffer = new Fl_Text_Buffer; + buffer->append(cert_body.c_str()); - wxScrolledWindow *slwin = new wxScrolledWindow - (panel, -1, wxDefaultPosition, wxDefaultSize, wxVSCROLL | wxHSCROLL | wxBORDER_SUNKEN); - slwin->SetScrollRate(20, 20); + Fl_Text_Display *text = new Fl_Text_Display(20, 20, 565, 320); + text->buffer(buffer); - wxBoxSizer *slsizer = new wxBoxSizer(wxVERTICAL); + short bx = (w() - BUTTON_WIDTH * 2 - BUTTON_SPACE) / 2; - wxStaticText *text1 = new wxStaticText - (slwin, wxID_ANY, cert_body, wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT); - slsizer->Add(text1, 0, wxEXPAND, 0); - slwin->SetSizer(slsizer); - - vsizer->Add(slwin, 1, wxEXPAND | wxALL, 10); + Fl_Return_Button *run_button = new Fl_Return_Button(bx, 360, BUTTON_WIDTH, 25, "Run"); + run_button->callback(this->run_clicked, this); - // Create the run / cancel buttons. - wxBoxSizer *bsizer = new wxBoxSizer(wxHORIZONTAL); + bx += BUTTON_WIDTH + BUTTON_SPACE; - wxButton *run_button = new wxButton(panel, wxID_OK, _T("Run")); - bsizer->Add(run_button, 0, wxALIGN_CENTER | wxALL, 5); + Fl_Button *cancel_button = new Fl_Button(bx, 360, BUTTON_WIDTH, 25, "Cancel"); + cancel_button->callback(this->cancel_clicked, this); - wxButton *cancel_button = new wxButton(panel, wxID_CANCEL, _T("Cancel")); - bsizer->Add(cancel_button, 0, wxALIGN_CENTER | wxALL, 5); - - vsizer->Add(bsizer, 0, wxALIGN_CENTER | wxALL, 5); - - panel->SetSizer(vsizer); - panel->SetAutoLayout(true); - vsizer->Fit(this); - - // Make sure the resulting window is at least a certain size. - int width, height; - GetSize(&width, &height); - SetSize(max(width, 600), max(height, 400)); + end(); + set_modal(); } - diff --git a/direct/src/plugin/p3dCert.h b/direct/src/plugin/p3dCert.h index addb95de17..5215b67a5d 100644 --- a/direct/src/plugin/p3dCert.h +++ b/direct/src/plugin/p3dCert.h @@ -1,5 +1,5 @@ // Filename: p3dCert.h -// Created by: drose (11Sep09) +// Created by: rdb (08Mar11) // //////////////////////////////////////////////////////////////////// // @@ -15,7 +15,8 @@ #ifndef P3DCERT_H #define P3DCERT_H -#include "wx/wx.h" +#include +#include #define OPENSSL_NO_KRB5 #include "openssl/x509.h" @@ -40,21 +41,6 @@ class ViewCertDialog; #define sk_X509_new(cmp) sk_new(cmp) #endif -//////////////////////////////////////////////////////////////////// -// Class : P3DCertApp -// Description : This is the wxApp that drives this application. -//////////////////////////////////////////////////////////////////// -class P3DCertApp : public wxApp { -public: - virtual bool OnInit(); - virtual void OnInitCmdLine(wxCmdLineParser &parser); - virtual bool OnCmdLineParsed(wxCmdLineParser &parser); - -private: - wxString _cert_filename; - wxString _cert_dir; -}; - //////////////////////////////////////////////////////////////////// // Class : AuthDialog // Description : This is the primary dialog of this application. @@ -65,39 +51,39 @@ private: // application's signature, and invites the user to // approve the signature or cancel. //////////////////////////////////////////////////////////////////// -class AuthDialog : public wxDialog { +class AuthDialog : public Fl_Window { public: - AuthDialog(const wxString &cert_filename, const wxString &cert_dir); + AuthDialog(const string &cert_filename, const string &cert_dir); virtual ~AuthDialog(); - void run_clicked(wxCommandEvent &event); - void view_cert_clicked(wxCommandEvent &event); - void cancel_clicked(wxCommandEvent &event); + static void run_clicked(Fl_Widget *w, void *data); + static void view_cert_clicked(Fl_Widget *w, void *data); + static void cancel_clicked(Fl_Widget *w, void *data); void approve_cert(); private: - void read_cert_file(const wxString &cert_filename); + void read_cert_file(const string &cert_filename); void get_friendly_name(); void verify_cert(); int load_certificates_from_der_ram(X509_STORE *store, const char *data, size_t data_size); void layout(); - void get_text(wxString &header, wxString &text); + void get_text(char *header, size_t hlen, char *text, size_t tlen); public: ViewCertDialog *_view_cert_dialog; private: - // any class wishing to process wxWidgets events must use this macro - DECLARE_EVENT_TABLE() - - wxString _cert_dir; + string _cert_dir; X509 *_cert; STACK_OF(X509) *_stack; - wxString _friendly_name; + char _header[32]; + char _text[512]; + + string _friendly_name; int _verify_result; }; @@ -106,20 +92,18 @@ private: // Description : This is the detailed view of the particular // certificate. //////////////////////////////////////////////////////////////////// -class ViewCertDialog : public wxDialog { +class ViewCertDialog : public Fl_Window { public: ViewCertDialog(AuthDialog *auth_dialog, X509 *cert); virtual ~ViewCertDialog(); - void run_clicked(wxCommandEvent &event); - void cancel_clicked(wxCommandEvent &event); + static void run_clicked(Fl_Widget *w, void *data); + static void cancel_clicked(Fl_Widget *w, void *data); private: void layout(); private: - DECLARE_EVENT_TABLE() - AuthDialog *_auth_dialog; X509 *_cert; }; diff --git a/direct/src/plugin/p3dCert_wx.cxx b/direct/src/plugin/p3dCert_wx.cxx new file mode 100644 index 0000000000..e9e7e3c699 --- /dev/null +++ b/direct/src/plugin/p3dCert_wx.cxx @@ -0,0 +1,627 @@ +// Filename: p3dCert.cxx +// Created by: drose (11Sep09) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + +#include "p3dCert_wx.h" +#include "wx/cmdline.h" +#include "wx/filename.h" + +#include "ca_bundle_data_src.c" + +static const wxString +self_signed_cert_text = + _T("This Panda3D application uses a self-signed certificate. ") + _T("This means the author's name can't be verified, and you have ") + _T("no way of knowing for sure who wrote it.\n\n") + + _T("We recommend you click Cancel to avoid running this application."); + +static const wxString +unknown_auth_cert_text = + _T("This Panda3D application has been signed, but we don't recognize ") + _T("the authority that verifies the signature. This means the author's ") + _T("name can't be trusted, and you have no way of knowing ") + _T("for sure who wrote it.\n\n") + + _T("We recommend you click Cancel to avoid running this application."); + +static const wxString +verified_cert_text = + _T("This Panda3D application has been signed by %s. ") + _T("If you trust %s, then click the Run button below ") + _T("to run this application on your computer. This will also ") + _T("automatically approve this and any other applications signed by ") + _T("%s in the future.\n\n") + + _T("If you are unsure about this application, ") + _T("you should click Cancel instead."); + +static const wxString +expired_cert_text = + _T("This Panda3D application has been signed by %s, ") + _T("but the certificate has expired.\n\n") + + _T("You should check the current date set on your computer's clock ") + _T("to make sure it is correct.\n\n") + + _T("If your computer's date is correct, we recommend ") + _T("you click Cancel to avoid running this application."); + +static const wxString +generic_error_cert_text = + _T("This Panda3D application has been signed, but there is a problem ") + _T("with the certificate (OpenSSL error code %d).\n\n") + + _T("We recommend you click Cancel to avoid running this application."); + +static const wxString +no_cert_text = + _T("This Panda3D application has not been signed. This means you have ") + _T("no way of knowing for sure who wrote it.\n\n") + + _T("Click Cancel to avoid running this application."); + +// wxWidgets boilerplate macro to define main() and start up the +// application. +IMPLEMENT_APP(P3DCertApp) + +//////////////////////////////////////////////////////////////////// +// Function: P3DCertApp::OnInit +// Access: Public, Virtual +// Description: The "main" of a wx application. This is the first +// entry point. +//////////////////////////////////////////////////////////////////// +bool P3DCertApp:: +OnInit() { + // call the base class initialization method, currently it only parses a + // few common command-line options but it could be do more in the future + if (!wxApp::OnInit()) { + return false; + } + + OpenSSL_add_all_algorithms(); + + AuthDialog *dialog = new AuthDialog(_cert_filename, _cert_dir); + SetTopWindow(dialog); + dialog->Show(true); + dialog->SetFocus(); + dialog->Raise(); + + // Return true to enter the main loop and wait for user input. + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: P3DCertApp::OnInitCmdLine +// Access: Public, Virtual +// Description: A callback to initialize the parser with the command +// line options. +//////////////////////////////////////////////////////////////////// +void P3DCertApp:: +OnInitCmdLine(wxCmdLineParser &parser) { + parser.AddParam(); + parser.AddParam(); +} + +//////////////////////////////////////////////////////////////////// +// Function: P3DCertApp::OnCmdLineParsed +// Access: Public, Virtual +// Description: A callback after the successful parsing of the +// command line. +//////////////////////////////////////////////////////////////////// +bool P3DCertApp:: +OnCmdLineParsed(wxCmdLineParser &parser) { + _cert_filename = parser.GetParam(0); + _cert_dir = parser.GetParam(1); + return true; +} + + +// The event table for AuthDialog. +#define VIEW_CERT_BUTTON (wxID_HIGHEST + 1) +BEGIN_EVENT_TABLE(AuthDialog, wxDialog) + EVT_BUTTON(wxID_OK, AuthDialog::run_clicked) + EVT_BUTTON(VIEW_CERT_BUTTON, AuthDialog::view_cert_clicked) + EVT_BUTTON(wxID_CANCEL, AuthDialog::cancel_clicked) +END_EVENT_TABLE() + +//////////////////////////////////////////////////////////////////// +// Function: AuthDialog::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +AuthDialog:: +AuthDialog(const wxString &cert_filename, const wxString &cert_dir) : + // I hate stay-on-top dialogs, but if we don't set this flag, it + // doesn't come to the foreground on OSX, and might be lost behind + // the browser window. + wxDialog(NULL, wxID_ANY, _T("New Panda3D Application"), wxDefaultPosition, + wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxSTAY_ON_TOP), + _cert_dir(cert_dir) +{ + _view_cert_dialog = NULL; + + _cert = NULL; + _stack = NULL; + _verify_result = -1; + + read_cert_file(cert_filename); + get_friendly_name(); + verify_cert(); + layout(); +} + +//////////////////////////////////////////////////////////////////// +// Function: AuthDialog::Destructor +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +AuthDialog:: +~AuthDialog() { + if (_view_cert_dialog != NULL) { + _view_cert_dialog->Destroy(); + } + + if (_cert != NULL) { + X509_free(_cert); + _cert = NULL; + } + if (_stack != NULL) { + sk_X509_free(_stack); + _stack = NULL; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: AuthDialog::run_clicked +// Access: Public +// Description: The user clicks the "Run" button. +//////////////////////////////////////////////////////////////////// +void AuthDialog:: +run_clicked(wxCommandEvent &event) { + approve_cert(); +} + +//////////////////////////////////////////////////////////////////// +// Function: AuthDialog::run_clicked +// Access: Public +// Description: The user clicks the "View Certificate" button. +//////////////////////////////////////////////////////////////////// +void AuthDialog:: +view_cert_clicked(wxCommandEvent &event) { + if (_view_cert_dialog != NULL) { + _view_cert_dialog->Destroy(); + } + Hide(); + _view_cert_dialog = new ViewCertDialog(this, _cert); + _view_cert_dialog->Show(); +} + +//////////////////////////////////////////////////////////////////// +// Function: AuthDialog::run_clicked +// Access: Public +// Description: The user clicks the "Cancel" button. +//////////////////////////////////////////////////////////////////// +void AuthDialog:: +cancel_clicked(wxCommandEvent &event) { + Destroy(); +} + +//////////////////////////////////////////////////////////////////// +// Function: AuthDialog::approve_cert +// Access: Public +// Description: Writes the certificate into the _cert_dir, so +// that it will be found by the P3DInstanceManager and +// known to be approved. +//////////////////////////////////////////////////////////////////// +void AuthDialog:: +approve_cert() { + assert(_cert != NULL); + + // Make sure the directory exists. + wxFileName::Mkdir(_cert_dir, 0777, wxPATH_MKDIR_FULL); + + // Look for an unused filename. + wxString pathname; + int i = 1; + while (true) { + pathname.Printf(wxT("%s/p%d.crt"), _cert_dir.c_str(), i); + if (!wxFileName::FileExists(pathname)) { + break; + } + ++i; + } + + // Sure, there's a slight race condition right now: another process + // might attempt to create the same filename. So what. + FILE *fp = fopen(pathname.mb_str(), "w"); + if (fp != NULL) { + PEM_write_X509(fp, _cert); + fclose(fp); + } + Destroy(); +} + +//////////////////////////////////////////////////////////////////// +// Function: AuthDialog::read_cert_file +// Access: Private +// Description: Reads the list of certificates in the pem filename +// passed on the command line into _cert and _stack. +//////////////////////////////////////////////////////////////////// +void AuthDialog:: +read_cert_file(const wxString &cert_filename) { + FILE *fp = fopen(cert_filename.mb_str(), "r"); + if (fp == NULL) { + cerr << "Couldn't read " << cert_filename.mb_str() << "\n"; + return; + } + _cert = PEM_read_X509(fp, NULL, NULL, (void *)""); + if (_cert == NULL) { + cerr << "Could not read certificate in " << cert_filename.mb_str() << ".\n"; + fclose(fp); + return; + } + + // Build up a STACK of the remaining certificates in the file. + _stack = sk_X509_new(NULL); + X509 *c = PEM_read_X509(fp, NULL, NULL, (void *)""); + while (c != NULL) { + sk_X509_push(_stack, c); + c = PEM_read_X509(fp, NULL, NULL, (void *)""); + } + + fclose(fp); +} + +//////////////////////////////////////////////////////////////////// +// Function: AuthDialog::get_friendly_name +// Access: Private +// Description: Extracts the "friendly name" from the certificate: +// the common name or email name. +//////////////////////////////////////////////////////////////////// +void AuthDialog:: +get_friendly_name() { + if (_cert == NULL) { + _friendly_name.clear(); + return; + } + + + static const int nid_choices[] = { + NID_pkcs9_emailAddress, + NID_commonName, + -1, + }; + + // Choose the first NID that exists on the cert. + for (int ni = 0; nid_choices[ni] != -1; ++ni) { + int nid = nid_choices[ni]; + + // A complex OpenSSL interface to extract out the name in utf-8. + X509_NAME *xname = X509_get_subject_name(_cert); + if (xname != NULL) { + int pos = X509_NAME_get_index_by_NID(xname, nid, -1); + if (pos != -1) { + // We just get the first common name. I guess it's possible to + // have more than one; not sure what that means in this context. + X509_NAME_ENTRY *xentry = X509_NAME_get_entry(xname, pos); + if (xentry != NULL) { + ASN1_STRING *data = X509_NAME_ENTRY_get_data(xentry); + if (data != NULL) { + // We use "print" to dump the output to a memory BIO. Is + // there an easier way to decode the ASN1_STRING? Curse + // these incomplete docs. + BIO *mbio = BIO_new(BIO_s_mem()); + ASN1_STRING_print_ex(mbio, data, ASN1_STRFLGS_RFC2253 & ~ASN1_STRFLGS_ESC_MSB); + + char *pp; + long pp_size = BIO_get_mem_data(mbio, &pp); + _friendly_name = wxString(pp, wxConvUTF8, pp_size); + BIO_free(mbio); + return; + } + } + } + } + } +} + +//////////////////////////////////////////////////////////////////// +// Function: AuthDialog::verify_cert +// Access: Private +// Description: Checks whether the certificate is valid by the chain +// and initializes _verify_status accordingly. +//////////////////////////////////////////////////////////////////// +void AuthDialog:: +verify_cert() { + if (_cert == NULL) { + _verify_result = -1; + return; + } + + // Create a new X509_STORE. + X509_STORE *store = X509_STORE_new(); + X509_STORE_set_default_paths(store); + + // Add in the well-known certificate authorities. + load_certificates_from_der_ram(store, (const char *)ca_bundle_data, ca_bundle_data_len); + + // Create the X509_STORE_CTX for verifying the cert and chain. + X509_STORE_CTX *ctx = X509_STORE_CTX_new(); + X509_STORE_CTX_init(ctx, store, _cert, _stack); + X509_STORE_CTX_set_cert(ctx, _cert); + + if (X509_verify_cert(ctx)) { + _verify_result = 0; + } else { + _verify_result = X509_STORE_CTX_get_error(ctx); + } + + X509_STORE_CTX_free(ctx); + + X509_STORE_free(store); + + cerr << "Got certificate from " << _friendly_name.mb_str() + << ", verify_result = " << _verify_result << "\n"; +} + +//////////////////////////////////////////////////////////////////// +// Function: AuthDialog::load_certificates_from_der_ram +// Access: Public +// Description: Reads a chain of trusted certificates from the +// indicated data buffer and adds them to the X509_STORE +// object. The data buffer should be DER-formatted. +// Returns the number of certificates read on success, +// or 0 on failure. +// +// You should call this only with trusted, +// locally-stored certificates; not with certificates +// received from an untrusted source. +//////////////////////////////////////////////////////////////////// +int AuthDialog:: +load_certificates_from_der_ram(X509_STORE *store, + const char *data, size_t data_size) { + int count = 0; + +#if OPENSSL_VERSION_NUMBER >= 0x00908000L + // Beginning in 0.9.8, d2i_X509() accepted a const unsigned char **. + const unsigned char *bp, *bp_end; +#else + // Prior to 0.9.8, d2i_X509() accepted an unsigned char **. + unsigned char *bp, *bp_end; +#endif + + bp = (unsigned char *)data; + bp_end = bp + data_size; + X509 *x509 = d2i_X509(NULL, &bp, bp_end - bp); + while (x509 != NULL) { + X509_STORE_add_cert(store, x509); + ++count; + x509 = d2i_X509(NULL, &bp, bp_end - bp); + } + + return count; +} + +//////////////////////////////////////////////////////////////////// +// Function: AuthDialog::layout +// Access: Private +// Description: Arranges the text and controls within the dialog. +//////////////////////////////////////////////////////////////////// +void AuthDialog:: +layout() { + wxString header, text; + get_text(header, text); + + wxPanel *panel = new wxPanel(this); + wxBoxSizer *vsizer = new wxBoxSizer(wxVERTICAL); + + wxFont font = panel->GetFont(); + wxFont *bold_font = wxTheFontList->FindOrCreateFont + ((int)(font.GetPointSize() * 1.5), + font.GetFamily(), font.GetStyle(), wxFONTWEIGHT_BOLD); + + if (!header.IsEmpty()) { + wxStaticText *text0 = new wxStaticText + (panel, wxID_ANY, header, wxDefaultPosition, wxDefaultSize, + wxALIGN_CENTER); + text0->SetFont(*bold_font); + vsizer->Add(text0, 0, wxCENTER | wxALL, 10); + } + + wxStaticText *text1 = new wxStaticText + (panel, wxID_ANY, text, wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER); + text1->Wrap(400); + vsizer->Add(text1, 0, wxCENTER | wxALL, 10); + + // Create the run / cancel buttons. + wxBoxSizer *bsizer = new wxBoxSizer(wxHORIZONTAL); + + if (_verify_result == 0 && _cert != NULL) { + wxButton *run_button = new wxButton(panel, wxID_OK, _T("Run")); + bsizer->Add(run_button, 0, wxALIGN_CENTER | wxALL, 5); + } + + if (_cert != NULL) { + wxButton *view_button = new wxButton(panel, VIEW_CERT_BUTTON, _T("View Certificate")); + bsizer->Add(view_button, 0, wxALIGN_CENTER | wxALL, 5); + } + + wxButton *cancel_button = new wxButton(panel, wxID_CANCEL, _T("Cancel")); + bsizer->Add(cancel_button, 0, wxALIGN_CENTER | wxALL, 5); + + vsizer->Add(bsizer, 0, wxALIGN_CENTER | wxALL, 5); + + panel->SetSizer(vsizer); + panel->SetAutoLayout(true); + vsizer->Fit(this); +} + +//////////////////////////////////////////////////////////////////// +// Function: AuthDialog::get_text +// Access: Private +// Description: Fills in the text appropriate to display in the +// dialog box, based on the certificate read so far. +//////////////////////////////////////////////////////////////////// +void AuthDialog:: +get_text(wxString &header, wxString &text) { + switch (_verify_result) { + case -1: + header = _T("No signature!"); + text = no_cert_text; + break; + + case 0: + text.Printf(verified_cert_text, _friendly_name.c_str(), _friendly_name.c_str(), _friendly_name.c_str()); + break; + + case X509_V_ERR_CERT_NOT_YET_VALID: + case X509_V_ERR_CERT_HAS_EXPIRED: + case X509_V_ERR_CRL_NOT_YET_VALID: + case X509_V_ERR_CRL_HAS_EXPIRED: + header = _T("Expired signature!"); + text.Printf(expired_cert_text, _friendly_name.c_str()); + break; + + case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: + header = _T("Unverified signature!"); + text.Printf(unknown_auth_cert_text, _friendly_name.c_str()); + break; + + case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: + case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: + header = _T("Unverified signature!"); + text = self_signed_cert_text; + break; + + default: + header = _T("Unverified signature!"); + text.Printf(generic_error_cert_text, _verify_result); + } +} + + +// The event table for ViewCertDialog. +BEGIN_EVENT_TABLE(ViewCertDialog, wxDialog) + EVT_BUTTON(wxID_OK, ViewCertDialog::run_clicked) + EVT_BUTTON(wxID_CANCEL, ViewCertDialog::cancel_clicked) +END_EVENT_TABLE() + +//////////////////////////////////////////////////////////////////// +// Function: ViewCertDialog::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +ViewCertDialog:: +ViewCertDialog(AuthDialog *auth_dialog, X509 *cert) : +wxDialog(NULL, wxID_ANY, _T("View Certificate"), wxDefaultPosition, + wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER), + _auth_dialog(auth_dialog), + _cert(cert) +{ + layout(); +} + +//////////////////////////////////////////////////////////////////// +// Function: ViewCertDialog::Destructor +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +ViewCertDialog:: +~ViewCertDialog() { + if (_auth_dialog != NULL) { + _auth_dialog->_view_cert_dialog = NULL; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: ViewCertDialog::run_clicked +// Access: Public +// Description: The user clicks the "Run" button. +//////////////////////////////////////////////////////////////////// +void ViewCertDialog:: +run_clicked(wxCommandEvent &event) { + if (_auth_dialog != NULL){ + _auth_dialog->approve_cert(); + } + Destroy(); +} + +//////////////////////////////////////////////////////////////////// +// Function: ViewCertDialog::run_clicked +// Access: Public +// Description: The user clicks the "Cancel" button. +//////////////////////////////////////////////////////////////////// +void ViewCertDialog:: +cancel_clicked(wxCommandEvent &event) { + if (_auth_dialog != NULL){ + _auth_dialog->Destroy(); + } + Destroy(); +} + +//////////////////////////////////////////////////////////////////// +// Function: ViewCertDialog::layout +// Access: Private +// Description: Arranges the text and controls within the dialog. +//////////////////////////////////////////////////////////////////// +void ViewCertDialog:: +layout() { + // Format the certificate text for display in the dialog. + assert(_cert != NULL); + + BIO *mbio = BIO_new(BIO_s_mem()); + X509_print(mbio, _cert); + + char *pp; + long pp_size = BIO_get_mem_data(mbio, &pp); + wxString cert_body(pp, wxConvUTF8, pp_size); + BIO_free(mbio); + + wxPanel *panel = new wxPanel(this); + wxBoxSizer *vsizer = new wxBoxSizer(wxVERTICAL); + + wxScrolledWindow *slwin = new wxScrolledWindow + (panel, -1, wxDefaultPosition, wxDefaultSize, wxVSCROLL | wxHSCROLL | wxBORDER_SUNKEN); + slwin->SetScrollRate(20, 20); + + wxBoxSizer *slsizer = new wxBoxSizer(wxVERTICAL); + + wxStaticText *text1 = new wxStaticText + (slwin, wxID_ANY, cert_body, wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT); + slsizer->Add(text1, 0, wxEXPAND, 0); + slwin->SetSizer(slsizer); + + vsizer->Add(slwin, 1, wxEXPAND | wxALL, 10); + + // Create the run / cancel buttons. + wxBoxSizer *bsizer = new wxBoxSizer(wxHORIZONTAL); + + wxButton *run_button = new wxButton(panel, wxID_OK, _T("Run")); + bsizer->Add(run_button, 0, wxALIGN_CENTER | wxALL, 5); + + wxButton *cancel_button = new wxButton(panel, wxID_CANCEL, _T("Cancel")); + bsizer->Add(cancel_button, 0, wxALIGN_CENTER | wxALL, 5); + + vsizer->Add(bsizer, 0, wxALIGN_CENTER | wxALL, 5); + + panel->SetSizer(vsizer); + panel->SetAutoLayout(true); + vsizer->Fit(this); + + // Make sure the resulting window is at least a certain size. + int width, height; + GetSize(&width, &height); + SetSize(max(width, 600), max(height, 400)); +} + diff --git a/direct/src/plugin/p3dCert_wx.h b/direct/src/plugin/p3dCert_wx.h new file mode 100644 index 0000000000..6ae79304d5 --- /dev/null +++ b/direct/src/plugin/p3dCert_wx.h @@ -0,0 +1,127 @@ +// Filename: p3dCert.h +// Created by: drose (11Sep09) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + +#ifndef P3DCERT_WX_H +#define P3DCERT_WX_H + +#include "wx/wx.h" + +#define OPENSSL_NO_KRB5 +#include "openssl/x509.h" +#include "openssl/x509_vfy.h" +#include "openssl/pem.h" + +#include +#include +#include +using namespace std; + +class ViewCertDialog; + +#ifndef STACK_OF + // At some point, presumably in 1.0.0, openssl went to the + // STACK_OF() macro system to typedef the contents of a stack. + // Unfortunately, that new API is different. We define some macros + // here here for backward compatiblity. + #define STACK_OF(type) STACK + #define sk_X509_push(stack, item) sk_push((stack), (char *)(item)) + #define sk_X509_free(stack) sk_free(stack) + #define sk_X509_new(cmp) sk_new(cmp) +#endif + +//////////////////////////////////////////////////////////////////// +// Class : P3DCertApp +// Description : This is the wxApp that drives this application. +//////////////////////////////////////////////////////////////////// +class P3DCertApp : public wxApp { +public: + virtual bool OnInit(); + virtual void OnInitCmdLine(wxCmdLineParser &parser); + virtual bool OnCmdLineParsed(wxCmdLineParser &parser); + +private: + wxString _cert_filename; + wxString _cert_dir; +}; + +//////////////////////////////////////////////////////////////////// +// Class : AuthDialog +// Description : This is the primary dialog of this application. +// +// This dialog is presented to the user when he/she +// clicks on the red authorization button on the splash +// window. It tells the user the status of the +// application's signature, and invites the user to +// approve the signature or cancel. +//////////////////////////////////////////////////////////////////// +class AuthDialog : public wxDialog { +public: + AuthDialog(const wxString &cert_filename, const wxString &cert_dir); + virtual ~AuthDialog(); + + void run_clicked(wxCommandEvent &event); + void view_cert_clicked(wxCommandEvent &event); + void cancel_clicked(wxCommandEvent &event); + + void approve_cert(); + +private: + void read_cert_file(const wxString &cert_filename); + void get_friendly_name(); + void verify_cert(); + int load_certificates_from_der_ram(X509_STORE *store, + const char *data, size_t data_size); + + void layout(); + void get_text(wxString &header, wxString &text); + +public: + ViewCertDialog *_view_cert_dialog; + +private: + // any class wishing to process wxWidgets events must use this macro + DECLARE_EVENT_TABLE() + + wxString _cert_dir; + X509 *_cert; + STACK_OF(X509) *_stack; + + wxString _friendly_name; + int _verify_result; +}; + +//////////////////////////////////////////////////////////////////// +// Class : ViewCertDialog +// Description : This is the detailed view of the particular +// certificate. +//////////////////////////////////////////////////////////////////// +class ViewCertDialog : public wxDialog { +public: + ViewCertDialog(AuthDialog *auth_dialog, X509 *cert); + virtual ~ViewCertDialog(); + + void run_clicked(wxCommandEvent &event); + void cancel_clicked(wxCommandEvent &event); + +private: + void layout(); + +private: + DECLARE_EVENT_TABLE() + + AuthDialog *_auth_dialog; + X509 *_cert; +}; + +#endif diff --git a/dtool/Config.pp b/dtool/Config.pp index 09f1aa123f..2c5b36425b 100644 --- a/dtool/Config.pp +++ b/dtool/Config.pp @@ -5,7 +5,7 @@ // into the various make scripts. It is processed by ppremake (along // with the Sources.pp files in each of the various directories) to // generate build scripts appropriate to each environment. -// +// // ******************************************************************* // NOTE: you should not attempt to copy this file verbatim as your own @@ -70,7 +70,7 @@ // // unix - Generate makefiles suitable for most Unix platforms. // msvc - Generate Visual C++ project files (still a work in progress) -// nmake - Generate makefiles for Microsoft Visual C++, using +// nmake - Generate makefiles for Microsoft Visual C++, using // Microsoft's nmake utility. // gmsvc - Generate makefiles similar to the above, using Microsoft // Visual C++, but uses the Cygwin-supplied GNU make @@ -335,7 +335,7 @@ // genPyCode. You may wish to add to this list to add your own // libraries, or if you want to use some of the more obscure // interfaces like libpandaegg and libpandafx. -#defer GENPYCODE_LIBS libpandaexpress libpanda libpandaphysics libdirect libpandafx libp3vision $[if $[HAVE_ODE],libpandaode] +#defer GENPYCODE_LIBS libpandaexpress libpanda libpandaphysics libdirect libpandafx libp3vision $[if $[HAVE_ODE],libpandaode] // Normally, Python source files are copied into the INSTALL_LIB_DIR // defined above, along with the compiled C++ library objects, when @@ -543,7 +543,7 @@ // Is Cg installed, and where? #if $[WINDOWS_PLATFORM] - #define CG_IPATH + #define CG_IPATH #define CG_LPATH #define CG_LIBS cg.lib #else @@ -987,10 +987,10 @@ #defer FREETYPE_CONFIG $[if $[not $[WINDOWS_PLATFORM]],freetype-config] #defer HAVE_FREETYPE $[or $[libtest $[FREETYPE_LPATH],$[FREETYPE_LIBS]],$[bintest $[FREETYPE_CONFIG]]] -#define FREETYPE_CFLAGS +#define FREETYPE_CFLAGS #define FREETYPE_IPATH -#define FREETYPE_LPATH -#define FREETYPE_LIBS +#define FREETYPE_LPATH +#define FREETYPE_LIBS // Define this true to compile in a default font, so every TextNode // will always have a font available without requiring the user to @@ -1009,10 +1009,22 @@ #defer WX_CONFIG $[if $[not $[WINDOWS_PLATFORM]],wx-config] #defer HAVE_WX $[or $[libtest $[WX_LPATH],$[WX_LIBS]],$[bintest $[WX_CONFIG]]] -#define WX_CFLAGS +#define WX_CFLAGS #define WX_IPATH -#define WX_LPATH -#define WX_LIBS +#define WX_LPATH +#define WX_LIBS + +// We use FLTK--the C++ library, not the Python library--for +// building the application p3dcert, which is needed only when +// building the plugin/runtime system. This uses a fltk-config program, +// similar to freetype, above. +#defer FLTK_CONFIG $[if $[not $[WINDOWS_PLATFORM]],fltk-config] +#defer HAVE_FLTK $[or $[libtest $[FLTK_LPATH],$[FLTK_LIBS]],$[bintest $[FLTK_CONFIG]]] + +#define FLTK_CFLAGS +#define FLTK_IPATH +#define FLTK_LPATH +#define FLTK_LIBS // Is Maya installed? This matters only to programs in PANDATOOL. diff --git a/dtool/LocalSetup.pp b/dtool/LocalSetup.pp index 3c8db69c1f..8998d2108e 100644 --- a/dtool/LocalSetup.pp +++ b/dtool/LocalSetup.pp @@ -121,6 +121,11 @@ #else #print - Did not find WxWidgets #endif +#if $[HAVE_FLTK] +#print + FLTK +#else +#print - Did not find FLTK +#endif #if $[HAVE_GL] #print + OpenGL #else diff --git a/dtool/Package.pp b/dtool/Package.pp index dc97beedd6..27f21b2468 100644 --- a/dtool/Package.pp +++ b/dtool/Package.pp @@ -340,6 +340,13 @@ #set WX_LPATH $[unixfilename $[WX_LPATH]] #set WX_LIBS $[WX_LIBS] +#set FLTK_CONFIG $[FLTK_CONFIG] +#set HAVE_FLTK $[HAVE_FLTK] +#set FLTK_CFLAGS $[FLTK_CFLAGS] +#set FLTK_IPATH $[unixfilename $[FLTK_IPATH]] +#set FLTK_LPATH $[unixfilename $[FLTK_LPATH]] +#set FLTK_LIBS $[FLTK_LIBS] + #set MAYA_LOCATION $[unixfilename $[MAYA_LOCATION]] #set HAVE_MAYA $[HAVE_MAYA] @@ -389,6 +396,17 @@ #define WX_LIBS $[patsubst -l%,%,$[filter -l%,$[libs]]] #endif +#if $[and $[HAVE_FLTK],$[FLTK_CONFIG]] + #define cflags $[shell $[FLTK_CONFIG] --cflags] + #define libs $[shell $[FLTK_CONFIG] --ldflags] + + #define FLTK_CFLAGS $[filter-out -I%,$[cflags]] + #define FLTK_IPATH $[unique $[patsubst -I%,%,$[filter -I%,$[cflags]]]] + #define FLTK_LPATH $[unique $[patsubst -L%,%,$[filter -L%,$[libs]]]] + #define FLTK_LFLAGS $[filter-out -l%,$[libs]] + #define FLTK_LIBS $[patsubst -l%,%,$[filter -l%,$[libs]]] +#endif + #if $[HAVE_PHYSX] #define GENPYCODE_LIBS $[GENPYCODE_LIBS] libpandaphysx #endif diff --git a/dtool/pptempl/Global.pp b/dtool/pptempl/Global.pp index 176be2f960..4d411af6d8 100644 --- a/dtool/pptempl/Global.pp +++ b/dtool/pptempl/Global.pp @@ -401,6 +401,15 @@ #define wx_framework $[WX_FRAMEWORK] #endif +#if $[HAVE_FLTK] + #define fltk_ipath $[wildcard $[FLTK_IPATH]] + #define fltk_lpath $[wildcard $[FLTK_LPATH]] + #define fltk_cflags $[FLTK_CFLAGS] + #define fltk_lflags $[FLTK_LFLAGS] + #define fltk_libs $[FLTK_LIBS] + #define fltk_framework $[FLTK_FRAMEWORK] +#endif + #if $[and $[HAVE_MAYA],$[MAYA_LOCATION]] #define maya_ipath $[MAYA_LOCATION]/include #define maya_lpath $[MAYA_LOCATION]/lib diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index 524dbff88d..90e482f68d 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -68,7 +68,7 @@ PkgListSet(["PYTHON", "DIRECT", # Python support "FFTW", "SWSCALE", # Algorithm helpers "ARTOOLKIT", "OPENCV", "DIRECTCAM", # Augmented Reality "NPAPI", "AWESOMIUM", # Browser embedding - "GTK2", "WX", # Toolkit support + "GTK2", "WX", "FLTK", # Toolkit support "OSMESA", "X11", "XF86DGA", "XRANDR", "XCURSOR", # Unix platform support "PANDATOOL", "PVIEW", "DEPLOYTOOLS", # Toolchain "CONTRIB" # Experimental @@ -276,8 +276,8 @@ if (INSTALLER) and (PkgSkip("PYTHON")) and (not RUNTIME): if (RTDIST) and (PkgSkip("JPEG")): exit("Cannot build rtdist without jpeg") -if (RTDIST) and (PkgSkip("WX")): - exit("Cannot build rtdist without wx") +if (RTDIST) and (PkgSkip("WX") and PkgSkip("FLTK")): + exit("Cannot build rtdist without wx or fltk") if (RUNTIME): SetLinkAllStatic(True) @@ -455,6 +455,8 @@ if (COMPILER=="MSVC"): DefSymbol("WX", "__WXMSW__", "") DefSymbol("WX", "_UNICODE", "") DefSymbol("WX", "UNICODE", "") + if (PkgSkip("FLTK")==0): + LibName("FLTK", GetThirdpartyDir() + "fltk/lib/fltk.lib") for pkg in MAYAVERSIONS: if (PkgSkip(pkg)==0): LibName(pkg, '"' + SDK[pkg] + '/lib/Foundation.lib"') @@ -564,6 +566,7 @@ if (COMPILER=="LINUX"): SmartPkgEnable("PYTHON", "", SDK["PYTHONVERSION"], (SDK["PYTHONVERSION"], SDK["PYTHONVERSION"] + "/Python.h"), tool = SDK["PYTHONVERSION"] + "-config", framework = "Python") if (RTDIST): SmartPkgEnable("WX", tool = "wx-config") + SmartPkgEnable("FLTK", tool = "fltk-config") if (RUNTIME): if (sys.platform.startswith("freebsd")): SmartPkgEnable("NPAPI", "mozilla-plugin", (), ("xulrunner", "nspr*/prtypes.h", "nspr*")) @@ -3810,11 +3813,19 @@ if (RTDIST or RUNTIME): TargetAdd('p3dpythonw.exe', opts=['SUBSYSTEM:WINDOWS', 'PYTHON', 'WINUSER']) if (PkgSkip("OPENSSL")==0 and RTDIST): - OPTS=['DIR:direct/src/plugin', 'DIR:panda/src/express', 'OPENSSL', 'WX'] + OPTS=['DIR:direct/src/plugin', 'DIR:panda/src/express', 'OPENSSL'] if (sys.platform=="darwin"): OPTS += ['OPT:2'] - TargetAdd('plugin_p3dCert.obj', opts=OPTS, input='p3dCert.cxx') - TargetAdd('p3dcert.exe', input='plugin_p3dCert.obj') - OPTS=['NOSTRIP', 'OPENSSL', 'WX', 'CARBON', 'WINOLE', 'WINOLEAUT', 'WINUSER', 'ADVAPI', 'WINSHELL', 'WINCOMCTL', 'WINGDI', 'WINCOMDLG'] + if (PkgSkip("FLTK")==0): + OPTS.append("FLTK") + TargetAdd('plugin_p3dCert.obj', opts=OPTS, input='p3dCert.cxx') + TargetAdd('p3dcert.exe', input='plugin_p3dCert.obj') + OPTS=['NOSTRIP', 'OPENSSL', 'FLTK'] + else: + OPTS.append("WX") + TargetAdd('plugin_p3dCert.obj', opts=OPTS, input='p3dCert_wx.cxx') + TargetAdd('p3dcert.exe', input='plugin_p3dCert.obj') + OPTS=['NOSTRIP', 'OPENSSL', 'WX', 'CARBON', 'WINOLE', 'WINOLEAUT', 'WINUSER', 'ADVAPI', 'WINSHELL', 'WINCOMCTL', 'WINGDI', 'WINCOMDLG'] + if (sys.platform=="darwin"): OPTS += ['OPT:2'] TargetAdd('p3dcert.exe', opts=OPTS)