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. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@38876 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
1d2ce8b8dc
commit
e8c006b9ac
@ -3,15 +3,20 @@
|
||||
* Distributed under the terms of the MIT License.
|
||||
* Original code from ZipOMatic by jonas.sundstrom@kirilla.com
|
||||
*/
|
||||
#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),
|
||||
@ -84,7 +89,7 @@ ExpanderThread::ThreadStartup()
|
||||
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 @@ ExpanderThread::ExecuteUnit(void)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ExpanderThread::PushInput(BString text)
|
||||
{
|
||||
text += "\n";
|
||||
write(fStdIn, text.String(), text.Length());
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ExpanderThread::ThreadShutdown(void)
|
||||
{
|
||||
@ -184,32 +197,60 @@ ExpanderThread::PipeCommand(int argc, const char **argv, int &in, int &out, int
|
||||
// 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.
|
||||
|
||||
setpgid(ret, ret);
|
||||
// shouldn't return
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 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 @@ ExpanderThread::PipeCommand(int argc, const char **argv, int &in, int &out, int
|
||||
the calls aren't very likely to fail, and that would
|
||||
muddy up the example quite a bit. YMMV. */
|
||||
|
||||
return ret;
|
||||
return pid;
|
||||
}
|
||||
|
||||
|
||||
|
@ -28,6 +28,7 @@ class ExpanderThread : public GenericThread
|
||||
status_t ResumeExternalExpander();
|
||||
status_t InterruptExternalExpander();
|
||||
status_t WaitOnExternalExpander();
|
||||
void PushInput(BString text);
|
||||
|
||||
private:
|
||||
|
||||
|
@ -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,6 +27,11 @@
|
||||
#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';
|
||||
@ -344,14 +344,22 @@ ExpanderWindow::MessageReceived(BMessage* msg)
|
||||
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) {
|
||||
fExpandingThread->ResumeExternalExpander();
|
||||
StopExpanding();
|
||||
} else
|
||||
if (strstr(string.String(), "password") != NULL) {
|
||||
BString password;
|
||||
PasswordAlert* alert = new PasswordAlert("passwordAlert", string);
|
||||
alert->Go(password);
|
||||
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;
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
SubDir HAIKU_TOP src apps expander ;
|
||||
|
||||
UseLibraryHeaders icon ;
|
||||
|
||||
Application Expander :
|
||||
ExpanderApp.cpp
|
||||
ExpanderWindow.cpp
|
||||
@ -9,6 +11,7 @@ Application Expander :
|
||||
ExpanderPreferences.cpp
|
||||
DirectoryFilePanel.cpp
|
||||
ExpanderRules.cpp
|
||||
PasswordAlert.cpp
|
||||
: be tracker $(HAIKU_LOCALE_LIBS) $(TARGET_LIBSUPC++)
|
||||
: Expander.rdef
|
||||
;
|
||||
|
212
src/apps/expander/PasswordAlert.cpp
Normal file
212
src/apps/expander/PasswordAlert.cpp
Normal file
@ -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);
|
||||
}
|
||||
}
|
33
src/apps/expander/PasswordAlert.h
Normal file
33
src/apps/expander/PasswordAlert.h
Normal file
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user