[haiku-commits] r38876 - haiku/trunk/src/apps/expander

  • From: korli@xxxxxxxxxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Sun, 3 Oct 2010 21:45:27 +0200 (CEST)

Author: korli
Date: 2010-10-03 21:45:27 +0200 (Sun, 03 Oct 2010)
New Revision: 38876
Changeset: http://dev.haiku-os.org/changeset/38876
Ticket: http://dev.haiku-os.org/ticket/4879

Added:
   haiku/trunk/src/apps/expander/PasswordAlert.cpp
   haiku/trunk/src/apps/expander/PasswordAlert.h
Modified:
   haiku/trunk/src/apps/expander/ExpanderThread.cpp
   haiku/trunk/src/apps/expander/ExpanderThread.h
   haiku/trunk/src/apps/expander/ExpanderWindow.cpp
   haiku/trunk/src/apps/expander/Jamfile
Log:
Added handling of password protected archives (bug #4879), only tested with zip 
archives.
* switch stdin to a tty in ExpanderThread (had to use fork() and execv)
* anytime an error message contains the word "password", an alert with a 
textcontrol is presented to the user.


Modified: haiku/trunk/src/apps/expander/ExpanderThread.cpp
===================================================================
--- haiku/trunk/src/apps/expander/ExpanderThread.cpp    2010-10-03 16:34:36 UTC 
(rev 38875)
+++ haiku/trunk/src/apps/expander/ExpanderThread.cpp    2010-10-03 19:45:27 UTC 
(rev 38876)
@@ -3,16 +3,21 @@
  * Distributed under the terms of the MIT License.
  * Original code from ZipOMatic by jonas.sundstrom@xxxxxxxxxxx
  */
-#include <Messenger.h>
-#include <Path.h>
 #include "ExpanderThread.h"
+
+#include <errno.h>
 #include <image.h>
 #include <signal.h>
+#include <termios.h>
 #include <unistd.h>
-#include <errno.h>
 
-const char * ExpanderThreadName        =       "ExpanderThread";
+#include <Messenger.h>
+#include <Path.h>
 
+
+const char * ExpanderThreadName = "ExpanderThread";
+
+
 ExpanderThread::ExpanderThread(BMessage * refs_message, BMessenger * messenger)
        :       GenericThread(ExpanderThreadName, B_NORMAL_PRIORITY, 
refs_message),
        fWindowMessenger(messenger),
@@ -84,7 +89,7 @@
        flags = fcntl(fStdErr, F_GETFL, 0);
        flags |= O_NONBLOCK;
        fcntl(fStdErr, F_SETFL, flags);
-
+       
        fExpanderOutput = fdopen(fStdOut, "r");
        fExpanderError = fdopen(fStdErr, "r");
                
@@ -127,6 +132,14 @@
 }
 
 
+void
+ExpanderThread::PushInput(BString text)
+{
+       text += "\n";
+       write(fStdIn, text.String(), text.Length());
+}
+
+
 status_t
 ExpanderThread::ThreadShutdown(void)
 {
@@ -184,32 +197,60 @@
        // http://www.abisoft.com/faq/BeDevTalk_FAQ.html#FAQ-209
 
        // Save current FDs
-       int old_in  =  dup(0);
-       int old_out  =  dup(1);
-       int old_err  =  dup(2);
+       int old_out = dup(1);
+       int old_err = dup(2);
 
        int filedes[2];
        
-       /* Create new pipe FDs as stdin, stdout, stderr */
-       pipe(filedes);  dup2(filedes[0], 0); close(filedes[0]);
-       in = filedes[1];  // Write to in, appears on cmd's stdin
+       /* Create new pipe FDs as stdout, stderr */
        pipe(filedes);  dup2(filedes[1], 1); close(filedes[1]);
        out = filedes[0]; // Read from out, taken from cmd's stdout
        pipe(filedes);  dup2(filedes[1], 2); close(filedes[1]);
        err = filedes[0]; // Read from err, taken from cmd's stderr
 
-       // "load" command.
-       thread_id ret  =  load_image(argc, argv, envp);
+       // taken from pty.cpp
+       // Create a tty for stdin, as utilities don't generally use stdin
+       int master = posix_openpt(O_RDWR);
+       if (master < 0)
+       return -1;
 
-       if (ret < B_OK)
-               return ret;
+       int slave;
+       const char *ttyName;
+       if (grantpt(master) != 0 || unlockpt(master) != 0
+               || (ttyName = ptsname(master)) == NULL
+               || (slave = open(ttyName, O_RDWR | O_NOCTTY)) < 0) {
+               close(master);
+               return -1;
+       }
+       
+       int pid = fork();
+       if (pid < 0) {
+               close(master);
+               close(slave);
+               return -1;
+       }
+       // child
+       if (pid == 0) {
+               close(master);
+               
+               setsid();
+               if (ioctl(slave, TIOCSCTTY, NULL) != 0)
+                       return -1;
+               dup2(slave, 0); 
+               close(slave);
+               
+               // "load" command.
+               execv(argv[0], (char *const *)argv);
 
-       // thread ret is now suspended.
+               // shouldn't return
+               return -1;
+       }
 
-       setpgid(ret, ret);
-
+       // parent
+       close (slave);
+       in = master;
+               
        // Restore old FDs
-       close(0); dup(old_in); close(old_in);
        close(1); dup(old_out); close(old_out);
        close(2); dup(old_err); close(old_err);
 
@@ -217,7 +258,7 @@
           the calls aren't very likely to fail, and that would 
           muddy up the example quite a bit.  YMMV. */
 
-       return ret;
+       return pid;
 }
 
 

Modified: haiku/trunk/src/apps/expander/ExpanderThread.h
===================================================================
--- haiku/trunk/src/apps/expander/ExpanderThread.h      2010-10-03 16:34:36 UTC 
(rev 38875)
+++ haiku/trunk/src/apps/expander/ExpanderThread.h      2010-10-03 19:45:27 UTC 
(rev 38876)
@@ -28,6 +28,7 @@
                status_t ResumeExternalExpander();
                status_t InterruptExternalExpander();
                status_t WaitOnExternalExpander();
+               void PushInput(BString text);
 
        private:
 

Modified: haiku/trunk/src/apps/expander/ExpanderWindow.cpp
===================================================================
--- haiku/trunk/src/apps/expander/ExpanderWindow.cpp    2010-10-03 16:34:36 UTC 
(rev 38875)
+++ haiku/trunk/src/apps/expander/ExpanderWindow.cpp    2010-10-03 19:45:27 UTC 
(rev 38876)
@@ -5,14 +5,9 @@
  */
 
 
-#include "ExpanderApp.h"
 #include "ExpanderWindow.h"
-#include "ExpanderThread.h"
-#include "ExpanderPreferences.h"
 
-
 #include <Alert.h>
-#include <Application.h>
 #include <Box.h>
 #include <Button.h>
 #include <Catalog.h>
@@ -32,7 +27,12 @@
 #include <StringView.h>
 #include <TextView.h>
 
+#include "ExpanderApp.h"
+#include "ExpanderThread.h"
+#include "ExpanderPreferences.h"
+#include "PasswordAlert.h"
 
+
 const uint32 MSG_SOURCE                        = 'mSOU';
 const uint32 MSG_DEST                  = 'mDES';
 const uint32 MSG_EXPAND                        = 'mEXP';
@@ -344,14 +344,22 @@
                        if (msg->FindString("error", &string) == B_OK
                                && fExpandingStarted) {
                                fExpandingThread->SuspendExternalExpander();
-                               BAlert* alert = new BAlert("stopAlert", string,
-                                       B_TRANSLATE("Stop"), 
B_TRANSLATE("Continue"), NULL,
-                                       B_WIDTH_AS_USUAL, B_EVEN_SPACING, 
B_WARNING_ALERT);
-                               if (alert->Go() == 0) {
+                               if (strstr(string.String(), "password") != 
NULL) {
+                                       BString password;
+                                       PasswordAlert* alert = new 
PasswordAlert("passwordAlert", string);
+                                       alert->Go(password);
                                        
fExpandingThread->ResumeExternalExpander();
-                                       StopExpanding();
-                               } else
-                                       
fExpandingThread->ResumeExternalExpander();
+                                       fExpandingThread->PushInput(password);
+                               } else {
+                                       BAlert* alert = new BAlert("stopAlert", 
string,
+                                               B_TRANSLATE("Stop"), 
B_TRANSLATE("Continue"), NULL,
+                                               B_WIDTH_AS_USUAL, 
B_EVEN_SPACING, B_WARNING_ALERT);
+                                       if (alert->Go() == 0) {
+                                               
fExpandingThread->ResumeExternalExpander();
+                                                       StopExpanding();
+                                       } else
+                                               
fExpandingThread->ResumeExternalExpander();
+                               }
                        }
                        break;
                }

Modified: haiku/trunk/src/apps/expander/Jamfile
===================================================================
--- haiku/trunk/src/apps/expander/Jamfile       2010-10-03 16:34:36 UTC (rev 
38875)
+++ haiku/trunk/src/apps/expander/Jamfile       2010-10-03 19:45:27 UTC (rev 
38876)
@@ -1,5 +1,7 @@
 SubDir HAIKU_TOP src apps expander ;
 
+UseLibraryHeaders icon ;
+
 Application Expander : 
        ExpanderApp.cpp
        ExpanderWindow.cpp
@@ -9,6 +11,7 @@
        ExpanderPreferences.cpp
        DirectoryFilePanel.cpp
        ExpanderRules.cpp
+       PasswordAlert.cpp
        : be tracker $(HAIKU_LOCALE_LIBS) $(TARGET_LIBSUPC++)
        : Expander.rdef
 ;

Added: haiku/trunk/src/apps/expander/PasswordAlert.cpp
===================================================================
--- haiku/trunk/src/apps/expander/PasswordAlert.cpp                             
(rev 0)
+++ haiku/trunk/src/apps/expander/PasswordAlert.cpp     2010-10-03 19:45:27 UTC 
(rev 38876)
@@ -0,0 +1,212 @@
+/*
+ * Copyright 2003-2010 Haiku Inc.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             Jérôme Duval
+ */
+
+
+#include "PasswordAlert.h"
+
+#include <string.h>
+
+#include <File.h>
+#include <FindDirectory.h>
+#include <IconUtils.h>
+#include <Path.h>
+#include <Resources.h>
+#include <Screen.h>
+#include <View.h>
+
+
+static const int kWindowIconOffset = 27;
+static const int kIconStripeWidth = 30;
+static const int kTextIconOffset = kWindowIconOffset + kIconStripeWidth - 2;
+static const int kTextTopOffset = 6;
+static const int kSemTimeOut = 50000;
+
+
+class TAlertView : public BView {
+public:
+                                                       TAlertView(BRect frame);
+                                                       TAlertView(BMessage* 
archive);
+                                                       ~TAlertView();
+
+       virtual void                    Draw(BRect updateRect);
+
+                       void                    SetBitmap(BBitmap* Icon)        
{ fIconBitmap = Icon; }
+                       BBitmap*                Bitmap()                        
                { return fIconBitmap; }
+
+private:
+               BBitmap*                        fIconBitmap;
+};
+
+
+PasswordAlert::PasswordAlert(const char* title, const char* text)
+       :
+       BWindow(BRect(0, 0, 450, 45), title, B_MODAL_WINDOW, B_NOT_CLOSABLE | 
B_NOT_RESIZABLE),
+       fTextControl(NULL),
+       fAlertSem(-1)
+{
+       // Set up the "_master_" view
+       TAlertView* masterView = new TAlertView(Bounds());
+       masterView->SetBitmap(InitIcon());
+       AddChild(masterView);
+
+       // Set up the text view
+       BRect textControlRect(kTextIconOffset, kTextTopOffset,
+               Bounds().right - 5, Bounds().bottom);
+       
+       fTextControl = new BTextControl(textControlRect, "_password_", text, 
NULL, new BMessage('pass'), 
+               B_FOLLOW_ALL);
+       fTextControl->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
+       fTextControl->TextView()->HideTyping(true);
+       fTextControl->SetAlignment(B_ALIGN_RIGHT, B_ALIGN_LEFT);
+       fTextControl->SetDivider(10 + fTextControl->StringWidth(text));
+
+       masterView->AddChild(fTextControl);
+       
+       BRect screenFrame = BScreen(B_MAIN_SCREEN_ID).Frame();
+       BPoint pt;
+       pt.x = screenFrame.Width() / 2 - Bounds().Width() / 2;
+       pt.y = screenFrame.Height() / 2 - Bounds().Height() / 2;
+
+       if (screenFrame.Contains(pt))
+               MoveTo(pt);
+
+       fTextControl->MakeFocus();
+}
+
+
+PasswordAlert::~PasswordAlert()
+{
+}
+
+
+BBitmap*
+PasswordAlert::InitIcon()
+{
+       // The alert icons are in the app_server resources
+       BBitmap* icon = NULL;
+       BPath path;
+       if (find_directory(B_BEOS_SERVERS_DIRECTORY, &path) == B_OK) {
+               path.Append("app_server");
+               BFile file;
+               if (file.SetTo(path.Path(), B_READ_ONLY) == B_OK) {
+                       BResources resources;
+                       if (resources.SetTo(&file) == B_OK) {
+                               // Which icon are we trying to load?
+                               const char* iconName = "warn";
+
+                               // Load the raw icon data
+                               size_t size;
+                               const void* rawIcon =
+                                       
resources.LoadResource(B_VECTOR_ICON_TYPE, iconName, &size);
+
+                               if (rawIcon != NULL) {
+                                       // Now build the bitmap
+                                       icon = new BBitmap(BRect(0, 0, 31, 31), 
B_RGBA32);
+                                       if (BIconUtils::GetVectorIcon((const 
uint8*)rawIcon, size,
+                                                       icon) != B_OK) {
+                                               delete icon;
+                                               return NULL;
+                                       }
+                               }
+                       }
+               }
+       }
+
+       return icon;
+}
+
+
+void
+PasswordAlert::Go(BString &password)
+{
+       fAlertSem = create_sem(0, "AlertSem");
+       if (fAlertSem < B_OK) {
+               Quit();
+               return;
+       }
+
+       // Get the originating window, if it exists
+       BWindow* window =
+               
dynamic_cast<BWindow*>(BLooper::LooperForThread(find_thread(NULL)));
+
+       Show();
+
+       // Heavily modified from TextEntryAlert code; the original didn't let 
the
+       // blocked window ever draw.
+       if (window) {
+               status_t err;
+               for (;;) {
+                       do {
+                               err = acquire_sem_etc(fAlertSem, 1, 
B_RELATIVE_TIMEOUT,
+                                                                         
kSemTimeOut);
+                               // We've (probably) had our time slice taken 
away from us
+                       } while (err == B_INTERRUPTED);
+
+                       if (err == B_BAD_SEM_ID) {
+                               // Semaphore was finally nuked in 
MessageReceived
+                               break;
+                       }
+                       window->UpdateIfNeeded();
+               }
+       } else {
+               // No window to update, so just hang out until we're done.
+               while (acquire_sem(fAlertSem) == B_INTERRUPTED) {
+               }
+       }
+
+       // Have to cache the value since we delete on Quit()
+       password = fTextControl->Text();
+       if (Lock())
+               Quit();
+}
+
+
+void
+PasswordAlert::MessageReceived(BMessage* msg)
+{
+       if (msg->what != 'pass')
+               return BWindow::MessageReceived(msg);
+
+       delete_sem(fAlertSem);
+       fAlertSem = -1;
+}
+
+
+//     #pragma mark - TAlertView
+
+
+TAlertView::TAlertView(BRect frame)
+       :
+       BView(frame, "TAlertView", B_FOLLOW_ALL_SIDES, B_WILL_DRAW),
+       fIconBitmap(NULL)
+{
+       SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
+}
+
+
+TAlertView::~TAlertView()
+{
+       delete fIconBitmap;
+}
+
+
+void
+TAlertView::Draw(BRect updateRect)
+{
+       // Here's the fun stuff
+       if (fIconBitmap) {
+               BRect stripeRect = Bounds();
+               stripeRect.right = kIconStripeWidth;
+               SetHighColor(tint_color(ViewColor(), B_DARKEN_1_TINT));
+               FillRect(stripeRect);
+
+               SetDrawingMode(B_OP_ALPHA);
+               DrawBitmapAsync(fIconBitmap, BPoint(18, 6));
+               SetDrawingMode(B_OP_COPY);
+       }
+}

Added: haiku/trunk/src/apps/expander/PasswordAlert.h
===================================================================
--- haiku/trunk/src/apps/expander/PasswordAlert.h                               
(rev 0)
+++ haiku/trunk/src/apps/expander/PasswordAlert.h       2010-10-03 19:45:27 UTC 
(rev 38876)
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2003-2010 Haiku Inc.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             Jérôme Duval
+ */
+#ifndef        _PASSWORDALERT_H
+#define        _PASSWORDALERT_H
+
+
+#include <Bitmap.h>
+#include <String.h>
+#include <TextControl.h>
+#include <Window.h>
+
+
+class PasswordAlert : public BWindow
+{
+public:
+                                                               
PasswordAlert(const char* title, 
+                                                                       const 
char* text);
+       virtual                                         ~PasswordAlert();
+                       void                            Go(BString &password);
+       virtual void                            MessageReceived(BMessage* msg);
+private:
+                       BBitmap*                        InitIcon();
+                       BTextControl*           fTextControl;
+                       sem_id                          fAlertSem;
+};
+
+#endif // _PASSWORDALERT_H
+


Other related posts:

  • » [haiku-commits] r38876 - haiku/trunk/src/apps/expander - korli