Browse Source

rewrite p3dcert to FLTK

rdb 14 years ago
parent
commit
54c692330a

+ 7 - 2
direct/src/plugin/Sources.pp

@@ -159,12 +159,17 @@
 // red "play" button to approve an unknown certificate.  Considered
 // red "play" button to approve an unknown certificate.  Considered
 // part of the Core API, though it is a separate download.
 // 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 BUILD_TARGET $[and $[HAVE_P3D_PLUGIN],$[HAVE_WX],$[HAVE_OPENSSL]]
   #define USE_PACKAGES wx openssl
   #define USE_PACKAGES wx openssl
+  #define SOURCES p3dCert_wx.cxx p3dCert_wx.h
+#endif
   #define TARGET p3dcert
   #define TARGET p3dcert
 
 
-  #define SOURCES p3dCert.cxx p3dCert.h
   #define OSX_SYS_FRAMEWORKS Carbon
   #define OSX_SYS_FRAMEWORKS Carbon
 
 
 #end bin_target
 #end bin_target

+ 183 - 230
direct/src/plugin/p3dCert.cxx

@@ -1,5 +1,5 @@
 // Filename: p3dCert.cxx
 // Filename: p3dCert.cxx
-// Created by:  drose (11Sep09)
+// Created by:  rdb (08Mar11)
 //
 //
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //
 //
@@ -13,140 +13,103 @@
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 
 
 #include "p3dCert.h"
 #include "p3dCert.h"
-#include "wx/cmdline.h"
-#include "wx/filename.h"
 
 
-#include "ca_bundle_data_src.c"
+#include <Fl/Fl_Box.H>
+#include <Fl/Fl_Button.H>
+#include <Fl/Fl_Return_Button.H>
+#include <Fl/Fl_Text_Display.H>
 
 
-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")
+#include <cassert>
+#include <sys/types.h>
+#include <sys/stat.h>
 
 
-  _T("We recommend you click Cancel to avoid running this application.");
+#define BUTTON_WIDTH 120
+#define BUTTON_SPACE 10
 
 
-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")
+#include "ca_bundle_data_src.c"
 
 
-  _T("We recommend you click Cancel to avoid running this application.");
+#ifdef _WIN32
+#define snprintf sprintf_s
+#endif
 
 
-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")
+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"
 
 
-  _T("If you are unsure about this application, ")
-  _T("you should click Cancel instead.");
+  "We recommend you click Cancel to avoid running this application.";
 
 
-static const wxString
-expired_cert_text =
-  _T("This Panda3D application has been signed by %s, ")
-  _T("but the certificate has expired.\n\n")
+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"
 
 
-  _T("You should check the current date set on your computer's clock ")
-  _T("to make sure it is correct.\n\n")
+  "We recommend you click Cancel to avoid running this application.";
 
 
-  _T("If your computer's date is correct, we recommend ")
-  _T("you click Cancel to avoid running this application.");
+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
-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 you are unsure about this application, "
+  "you should click Cancel instead.";
 
 
-  _T("We recommend you click Cancel to avoid running this application.");
+static const char
+expired_cert_text[] =
+  "This Panda3D application has been signed by %s, "
+  "but the certificate has expired.\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")
+  "You should check the current date set on your computer's clock "
+  "to make sure it is correct.\n\n"
 
 
-  _T("Click Cancel to avoid running this application.");
+  "If your computer's date is correct, we recommend "
+  "you click Cancel to avoid running this application.";
 
 
-// wxWidgets boilerplate macro to define main() and start up the
-// application.
-IMPLEMENT_APP(P3DCertApp)
+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"
 
 
-////////////////////////////////////////////////////////////////////
-//     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;
-  }
+  "We recommend you click Cancel to avoid running this application.";
 
 
-  OpenSSL_add_all_algorithms();
+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"
 
 
-  AuthDialog *dialog = new AuthDialog(_cert_filename, _cert_dir);
-  SetTopWindow(dialog);
-  dialog->Show(true);
-  dialog->SetFocus();
-  dialog->Raise();
+  "Click Cancel to avoid running this application.";
 
 
-  // Return true to enter the main loop and wait for user input.
-  return true;
-}
+int main(int argc, char **argv) {
+  OpenSSL_add_all_algorithms();
 
 
-////////////////////////////////////////////////////////////////////
-//     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();
-}
+  if (argc != 3) {
+    cerr << "usage: p3dcert cert_filename cert_dir\n";
+    return 1;
+  }
 
 
-////////////////////////////////////////////////////////////////////
-//     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;
-}
+  string cert_filename (argv[1]);
+  string cert_dir (argv[2]);
 
 
+  AuthDialog *dialog = new AuthDialog(cert_filename, cert_dir);
+  dialog->show(1, argv);
 
 
-// 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()
+  return Fl::run();
+}
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: AuthDialog::Constructor
 //     Function: AuthDialog::Constructor
 //       Access: Public
 //       Access: Public
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 AuthDialog::
 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)
   _cert_dir(cert_dir)
 {
 {
   _view_cert_dialog = NULL;
   _view_cert_dialog = NULL;
@@ -164,19 +127,19 @@ AuthDialog(const wxString &cert_filename, const wxString &cert_dir) :
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: AuthDialog::Destructor
 //     Function: AuthDialog::Destructor
 //       Access: Public, Virtual
 //       Access: Public, Virtual
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 AuthDialog::
 AuthDialog::
 ~AuthDialog() {
 ~AuthDialog() {
   if (_view_cert_dialog != NULL) {
   if (_view_cert_dialog != NULL) {
-    _view_cert_dialog->Destroy();
+    _view_cert_dialog->hide();
   }
   }
 
 
-  if (_cert != NULL) { 
+  if (_cert != NULL) {
     X509_free(_cert);
     X509_free(_cert);
     _cert = NULL;
     _cert = NULL;
   }
   }
-  if (_stack != NULL) { 
+  if (_stack != NULL) {
     sk_X509_free(_stack);
     sk_X509_free(_stack);
     _stack = NULL;
     _stack = NULL;
   }
   }
@@ -188,8 +151,9 @@ AuthDialog::
 //  Description: The user clicks the "Run" button.
 //  Description: The user clicks the "Run" button.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void AuthDialog::
 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.
 //  Description: The user clicks the "View Certificate" button.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void AuthDialog::
 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.
 //  Description: The user clicks the "Cancel" button.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void AuthDialog::
 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);
   assert(_cert != NULL);
 
 
   // Make sure the directory exists.
   // 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.
   // Look for an unused filename.
-  wxString pathname;
+  string pathname;
   int i = 1;
   int i = 1;
+  char buf [PATH_MAX];
   while (true) {
   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;
       break;
     }
     }
+#endif
     ++i;
     ++i;
   }
   }
 
 
   // Sure, there's a slight race condition right now: another process
   // Sure, there's a slight race condition right now: another process
   // might attempt to create the same filename.  So what.
   // 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) {
   if (fp != NULL) {
     PEM_write_X509(fp, _cert);
     PEM_write_X509(fp, _cert);
     fclose(fp);
     fclose(fp);
   }
   }
-  Destroy();
+  hide();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -259,15 +241,15 @@ approve_cert() {
 //               passed on the command line into _cert and _stack.
 //               passed on the command line into _cert and _stack.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void AuthDialog::
 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) {
   if (fp == NULL) {
-    cerr << "Couldn't read " << cert_filename.mb_str() << "\n";
+    cerr << "Couldn't read " << cert_filename.c_str() << "\n";
     return;
     return;
   }
   }
   _cert = PEM_read_X509(fp, NULL, NULL, (void *)"");
   _cert = PEM_read_X509(fp, NULL, NULL, (void *)"");
   if (_cert == NULL) {
   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);
     fclose(fp);
     return;
     return;
   }
   }
@@ -323,10 +305,10 @@ get_friendly_name() {
             // these incomplete docs.
             // these incomplete docs.
             BIO *mbio = BIO_new(BIO_s_mem());
             BIO *mbio = BIO_new(BIO_s_mem());
             ASN1_STRING_print_ex(mbio, data, ASN1_STRFLGS_RFC2253 & ~ASN1_STRFLGS_ESC_MSB);
             ASN1_STRING_print_ex(mbio, data, ASN1_STRFLGS_RFC2253 & ~ASN1_STRFLGS_ESC_MSB);
-            
+
             char *pp;
             char *pp;
             long pp_size = BIO_get_mem_data(mbio, &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);
             BIO_free(mbio);
             return;
             return;
           }
           }
@@ -371,7 +353,7 @@ verify_cert() {
 
 
   X509_STORE_free(store);
   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";
        << ", verify_result = " << _verify_result << "\n";
 }
 }
 
 
@@ -420,51 +402,45 @@ load_certificates_from_der_ram(X509_STORE *store,
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void AuthDialog::
 void AuthDialog::
 layout() {
 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);
+  get_text(_header, sizeof _header, _text, sizeof _text);
+
+  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) {
   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) {
   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);
-
-  vsizer->Add(bsizer, 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);
 
 
-  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.
 //               dialog box, based on the certificate read so far.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void AuthDialog::
 void AuthDialog::
-get_text(wxString &header, wxString &text) {
+get_text(char *header, size_t hlen, char *text, size_t tlen) {
   switch (_verify_result) {
   switch (_verify_result) {
   case -1:
   case -1:
-    header = _T("No signature!");
-    text = no_cert_text;
+    strncpy(header, "No signature!", hlen);
+    strncpy(text, no_cert_text, tlen);
     break;
     break;
 
 
   case 0:
   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;
     break;
 
 
   case X509_V_ERR_CERT_NOT_YET_VALID:
   case X509_V_ERR_CERT_NOT_YET_VALID:
   case X509_V_ERR_CERT_HAS_EXPIRED:
   case X509_V_ERR_CERT_HAS_EXPIRED:
   case X509_V_ERR_CRL_NOT_YET_VALID:
   case X509_V_ERR_CRL_NOT_YET_VALID:
   case X509_V_ERR_CRL_HAS_EXPIRED:
   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;
     break;
 
 
   case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
   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;
     break;
-      
+
   case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
   case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
   case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
   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;
     break;
 
 
   default:
   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
 //     Function: ViewCertDialog::Constructor
 //       Access: Public
 //       Access: Public
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 ViewCertDialog::
 ViewCertDialog::
 ViewCertDialog(AuthDialog *auth_dialog, X509 *cert) :
 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),
   _auth_dialog(auth_dialog),
   _cert(cert)
   _cert(cert)
 {
 {
@@ -535,7 +504,7 @@ wxDialog(NULL, wxID_ANY, _T("View Certificate"), wxDefaultPosition,
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: ViewCertDialog::Destructor
 //     Function: ViewCertDialog::Destructor
 //       Access: Public, Virtual
 //       Access: Public, Virtual
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 ViewCertDialog::
 ViewCertDialog::
 ~ViewCertDialog() {
 ~ViewCertDialog() {
@@ -550,11 +519,12 @@ ViewCertDialog::
 //  Description: The user clicks the "Run" button.
 //  Description: The user clicks the "Run" button.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void ViewCertDialog::
 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.
 //  Description: The user clicks the "Cancel" button.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void ViewCertDialog::
 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;
   char *pp;
   long pp_size = BIO_get_mem_data(mbio, &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);
   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);
+  Fl_Text_Buffer *buffer = new Fl_Text_Buffer;
+  buffer->append(cert_body.c_str());
 
 
-  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_Text_Display *text = new Fl_Text_Display(20, 20, 565, 320);
+  text->buffer(buffer);
 
 
-  // Create the run / cancel buttons.
-  wxBoxSizer *bsizer = new wxBoxSizer(wxHORIZONTAL);
+  short bx = (w() - BUTTON_WIDTH * 2 - BUTTON_SPACE) / 2;
 
 
-  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, 360, BUTTON_WIDTH, 25, "Run");
+  run_button->callback(this->run_clicked, this);
 
 
-  wxButton *cancel_button = new wxButton(panel, wxID_CANCEL, _T("Cancel"));
-  bsizer->Add(cancel_button, 0, wxALIGN_CENTER | wxALL, 5);
+  bx += BUTTON_WIDTH + BUTTON_SPACE;
 
 
-  vsizer->Add(bsizer, 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);
 
 
-  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();
 }
 }
-

+ 18 - 34
direct/src/plugin/p3dCert.h

@@ -1,5 +1,5 @@
 // Filename: p3dCert.h
 // Filename: p3dCert.h
-// Created by:  drose (11Sep09)
+// Created by:  rdb (08Mar11)
 //
 //
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //
 //
@@ -15,7 +15,8 @@
 #ifndef P3DCERT_H
 #ifndef P3DCERT_H
 #define P3DCERT_H
 #define P3DCERT_H
 
 
-#include "wx/wx.h"
+#include <Fl/Fl.H>
+#include <Fl/Fl_Window.H>
 
 
 #define OPENSSL_NO_KRB5
 #define OPENSSL_NO_KRB5
 #include "openssl/x509.h"
 #include "openssl/x509.h"
@@ -40,21 +41,6 @@ class ViewCertDialog;
   #define sk_X509_new(cmp) sk_new(cmp)
   #define sk_X509_new(cmp) sk_new(cmp)
 #endif
 #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
 //       Class : AuthDialog
 // Description : This is the primary dialog of this application.
 // Description : This is the primary dialog of this application.
@@ -65,39 +51,39 @@ private:
 //               application's signature, and invites the user to
 //               application's signature, and invites the user to
 //               approve the signature or cancel.
 //               approve the signature or cancel.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-class AuthDialog : public wxDialog {
+class AuthDialog : public Fl_Window {
 public:
 public:
-  AuthDialog(const wxString &cert_filename, const wxString &cert_dir);
+  AuthDialog(const string &cert_filename, const string &cert_dir);
   virtual ~AuthDialog();
   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();
   void approve_cert();
 
 
 private:
 private:
-  void read_cert_file(const wxString &cert_filename);
+  void read_cert_file(const string &cert_filename);
   void get_friendly_name();
   void get_friendly_name();
   void verify_cert();
   void verify_cert();
   int load_certificates_from_der_ram(X509_STORE *store,
   int load_certificates_from_der_ram(X509_STORE *store,
                                      const char *data, size_t data_size);
                                      const char *data, size_t data_size);
 
 
   void layout();
   void layout();
-  void get_text(wxString &header, wxString &text);
+  void get_text(char *header, size_t hlen, char *text, size_t tlen);
 
 
 public:
 public:
   ViewCertDialog *_view_cert_dialog;
   ViewCertDialog *_view_cert_dialog;
 
 
 private:
 private:
-  // any class wishing to process wxWidgets events must use this macro
-  DECLARE_EVENT_TABLE()
-
-  wxString _cert_dir;
+  string _cert_dir;
   X509 *_cert;
   X509 *_cert;
   STACK_OF(X509) *_stack;
   STACK_OF(X509) *_stack;
 
 
-  wxString _friendly_name;
+  char _header[32];
+  char _text[512];
+
+  string _friendly_name;
   int _verify_result;
   int _verify_result;
 };
 };
 
 
@@ -106,20 +92,18 @@ private:
 // Description : This is the detailed view of the particular
 // Description : This is the detailed view of the particular
 //               certificate.
 //               certificate.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-class ViewCertDialog : public wxDialog {
+class ViewCertDialog : public Fl_Window {
 public:
 public:
   ViewCertDialog(AuthDialog *auth_dialog, X509 *cert);
   ViewCertDialog(AuthDialog *auth_dialog, X509 *cert);
   virtual ~ViewCertDialog();
   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:
 private:
   void layout();
   void layout();
 
 
 private:
 private:
-  DECLARE_EVENT_TABLE()
-
   AuthDialog *_auth_dialog;
   AuthDialog *_auth_dialog;
   X509 *_cert;
   X509 *_cert;
 };
 };

+ 627 - 0
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));
+}
+

+ 127 - 0
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 <string>
+#include <iostream>
+#include <stdio.h>
+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

+ 22 - 10
dtool/Config.pp

@@ -5,7 +5,7 @@
 // into the various make scripts.  It is processed by ppremake (along
 // into the various make scripts.  It is processed by ppremake (along
 // with the Sources.pp files in each of the various directories) to
 // with the Sources.pp files in each of the various directories) to
 // generate build scripts appropriate to each environment.
 // generate build scripts appropriate to each environment.
-// 
+//
 
 
 // *******************************************************************
 // *******************************************************************
 // NOTE: you should not attempt to copy this file verbatim as your own
 // 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.
 //  unix      - Generate makefiles suitable for most Unix platforms.
 //  msvc      - Generate Visual C++ project files (still a work in progress)
 //  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.
 //              Microsoft's nmake utility.
 //  gmsvc     - Generate makefiles similar to the above, using Microsoft
 //  gmsvc     - Generate makefiles similar to the above, using Microsoft
 //              Visual C++, but uses the Cygwin-supplied GNU make
 //              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
 // 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
 // libraries, or if you want to use some of the more obscure
 // interfaces like libpandaegg and libpandafx.
 // 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
 // Normally, Python source files are copied into the INSTALL_LIB_DIR
 // defined above, along with the compiled C++ library objects, when
 // defined above, along with the compiled C++ library objects, when
@@ -543,7 +543,7 @@
 
 
 // Is Cg installed, and where?
 // Is Cg installed, and where?
 #if $[WINDOWS_PLATFORM]
 #if $[WINDOWS_PLATFORM]
-  #define CG_IPATH 
+  #define CG_IPATH
   #define CG_LPATH
   #define CG_LPATH
   #define CG_LIBS cg.lib
   #define CG_LIBS cg.lib
 #else
 #else
@@ -987,10 +987,10 @@
 #defer FREETYPE_CONFIG $[if $[not $[WINDOWS_PLATFORM]],freetype-config]
 #defer FREETYPE_CONFIG $[if $[not $[WINDOWS_PLATFORM]],freetype-config]
 #defer HAVE_FREETYPE $[or $[libtest $[FREETYPE_LPATH],$[FREETYPE_LIBS]],$[bintest $[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_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
 // Define this true to compile in a default font, so every TextNode
 // will always have a font available without requiring the user to
 // 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 WX_CONFIG $[if $[not $[WINDOWS_PLATFORM]],wx-config]
 #defer HAVE_WX $[or $[libtest $[WX_LPATH],$[WX_LIBS]],$[bintest $[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_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.
 // Is Maya installed?  This matters only to programs in PANDATOOL.
 
 

+ 5 - 0
dtool/LocalSetup.pp

@@ -121,6 +121,11 @@
 #else
 #else
 #print - Did not find WxWidgets
 #print - Did not find WxWidgets
 #endif
 #endif
+#if $[HAVE_FLTK]
+#print + FLTK
+#else
+#print - Did not find FLTK
+#endif
 #if $[HAVE_GL]
 #if $[HAVE_GL]
 #print + OpenGL
 #print + OpenGL
 #else
 #else

+ 18 - 0
dtool/Package.pp

@@ -340,6 +340,13 @@
 #set WX_LPATH $[unixfilename $[WX_LPATH]]
 #set WX_LPATH $[unixfilename $[WX_LPATH]]
 #set WX_LIBS $[WX_LIBS]
 #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 MAYA_LOCATION $[unixfilename $[MAYA_LOCATION]]
 #set HAVE_MAYA $[HAVE_MAYA]
 #set HAVE_MAYA $[HAVE_MAYA]
@@ -389,6 +396,17 @@
   #define WX_LIBS $[patsubst -l%,%,$[filter -l%,$[libs]]]
   #define WX_LIBS $[patsubst -l%,%,$[filter -l%,$[libs]]]
 #endif
 #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]
 #if $[HAVE_PHYSX]
   #define GENPYCODE_LIBS $[GENPYCODE_LIBS] libpandaphysx
   #define GENPYCODE_LIBS $[GENPYCODE_LIBS] libpandaphysx
 #endif
 #endif

+ 9 - 0
dtool/pptempl/Global.pp

@@ -401,6 +401,15 @@
   #define wx_framework $[WX_FRAMEWORK]
   #define wx_framework $[WX_FRAMEWORK]
 #endif
 #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]]
 #if $[and $[HAVE_MAYA],$[MAYA_LOCATION]]
   #define maya_ipath $[MAYA_LOCATION]/include
   #define maya_ipath $[MAYA_LOCATION]/include
   #define maya_lpath $[MAYA_LOCATION]/lib
   #define maya_lpath $[MAYA_LOCATION]/lib

+ 18 - 7
makepanda/makepanda.py

@@ -68,7 +68,7 @@ PkgListSet(["PYTHON", "DIRECT",                        # Python support
   "FFTW", "SWSCALE",                                   # Algorithm helpers
   "FFTW", "SWSCALE",                                   # Algorithm helpers
   "ARTOOLKIT", "OPENCV", "DIRECTCAM",                  # Augmented Reality
   "ARTOOLKIT", "OPENCV", "DIRECTCAM",                  # Augmented Reality
   "NPAPI", "AWESOMIUM",                                # Browser embedding
   "NPAPI", "AWESOMIUM",                                # Browser embedding
-  "GTK2", "WX",                                        # Toolkit support
+  "GTK2", "WX", "FLTK",                                # Toolkit support
   "OSMESA", "X11", "XF86DGA", "XRANDR", "XCURSOR",     # Unix platform support
   "OSMESA", "X11", "XF86DGA", "XRANDR", "XCURSOR",     # Unix platform support
   "PANDATOOL", "PVIEW", "DEPLOYTOOLS",                 # Toolchain
   "PANDATOOL", "PVIEW", "DEPLOYTOOLS",                 # Toolchain
   "CONTRIB"                                            # Experimental
   "CONTRIB"                                            # Experimental
@@ -276,8 +276,8 @@ if (INSTALLER) and (PkgSkip("PYTHON")) and (not RUNTIME):
 if (RTDIST) and (PkgSkip("JPEG")):
 if (RTDIST) and (PkgSkip("JPEG")):
     exit("Cannot build rtdist without 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):
 if (RUNTIME):
     SetLinkAllStatic(True)
     SetLinkAllStatic(True)
@@ -455,6 +455,8 @@ if (COMPILER=="MSVC"):
         DefSymbol("WX",     "__WXMSW__", "")
         DefSymbol("WX",     "__WXMSW__", "")
         DefSymbol("WX",     "_UNICODE", "")
         DefSymbol("WX",     "_UNICODE", "")
         DefSymbol("WX",     "UNICODE", "")
         DefSymbol("WX",     "UNICODE", "")
+    if (PkgSkip("FLTK")==0):
+        LibName("FLTK",     GetThirdpartyDir() + "fltk/lib/fltk.lib")
     for pkg in MAYAVERSIONS:
     for pkg in MAYAVERSIONS:
         if (PkgSkip(pkg)==0):
         if (PkgSkip(pkg)==0):
             LibName(pkg, '"' + SDK[pkg] + '/lib/Foundation.lib"')
             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")
         SmartPkgEnable("PYTHON",    "", SDK["PYTHONVERSION"], (SDK["PYTHONVERSION"], SDK["PYTHONVERSION"] + "/Python.h"), tool = SDK["PYTHONVERSION"] + "-config", framework = "Python")
     if (RTDIST):
     if (RTDIST):
         SmartPkgEnable("WX",    tool = "wx-config")
         SmartPkgEnable("WX",    tool = "wx-config")
+        SmartPkgEnable("FLTK",  tool = "fltk-config")
     if (RUNTIME):
     if (RUNTIME):
         if (sys.platform.startswith("freebsd")):
         if (sys.platform.startswith("freebsd")):
             SmartPkgEnable("NPAPI", "mozilla-plugin", (), ("xulrunner", "nspr*/prtypes.h", "nspr*"))
             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'])
       TargetAdd('p3dpythonw.exe', opts=['SUBSYSTEM:WINDOWS', 'PYTHON', 'WINUSER'])
 
 
   if (PkgSkip("OPENSSL")==0 and RTDIST):
   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']
     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']
     if (sys.platform=="darwin"): OPTS += ['OPT:2']
     TargetAdd('p3dcert.exe', opts=OPTS)
     TargetAdd('p3dcert.exe', opts=OPTS)