/* * Copyright 2012, Michael Lotz, mmlr@mlotz.ch. All Rights Reserved. * Distributed under the terms of the MIT License. */ #include "KeyRequestWindow.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #undef B_TRANSLATION_CONTEXT #define B_TRANSLATION_CONTEXT "KeyRequestWindow" static const uint32 kMessageCancel = 'btcl'; static const uint32 kMessageUnlock = 'btul'; class KeyRequestView : public BView { public: KeyRequestView() : BView("KeyRequestView", B_WILL_DRAW), fPassword(NULL) { SetViewUIColor(B_PANEL_BACKGROUND_COLOR); BGroupLayout* rootLayout = new(std::nothrow) BGroupLayout(B_VERTICAL); if (rootLayout == NULL) return; SetLayout(rootLayout); BGridView* controls = new(std::nothrow) BGridView(); if (controls == NULL) return; BGridLayout* layout = controls->GridLayout(); float inset = ceilf(be_plain_font->Size() * 0.7); rootLayout->SetInsets(inset, inset, inset, inset); rootLayout->SetSpacing(inset); layout->SetSpacing(inset, inset); BStringView* label = new(std::nothrow) BStringView("keyringLabel", B_TRANSLATE("Keyring:")); if (label == NULL) return; int32 row = 0; layout->AddView(label, 0, row); fKeyringName = new(std::nothrow) BStringView("keyringName", ""); if (fKeyringName == NULL) return; layout->AddView(fKeyringName, 1, row++); fPassword = new(std::nothrow) BTextControl(B_TRANSLATE("Password:"), "", NULL); if (fPassword == NULL) return; BLayoutItem* layoutItem = fPassword->CreateTextViewLayoutItem(); layoutItem->SetExplicitMinSize(BSize(fPassword->StringWidth( "0123456789012345678901234567890123456789") + inset, B_SIZE_UNSET)); layout->AddItem(fPassword->CreateLabelLayoutItem(), 0, row); layout->AddItem(layoutItem, 1, row++); BGroupView* buttons = new(std::nothrow) BGroupView(B_HORIZONTAL); if (buttons == NULL) return; fCancelButton = new(std::nothrow) BButton(B_TRANSLATE("Cancel"), new BMessage(kMessageCancel)); buttons->GroupLayout()->AddView(fCancelButton); buttons->GroupLayout()->AddItem(BSpaceLayoutItem::CreateGlue()); fUnlockButton = new(std::nothrow) BButton(B_TRANSLATE("Unlock"), new BMessage(kMessageUnlock)); buttons->GroupLayout()->AddView(fUnlockButton); BTextView* message = new(std::nothrow) BTextView("message"); message->SetText(B_TRANSLATE("An application wants to access the " "keyring below, but it is locked with a passphrase. Please enter " "the passphrase to unlock the keyring.\n" "If you unlock the keyring, it stays unlocked until the system is " "shut down or the keyring is manually locked again.\n" "If you cancel this dialog the keyring will remain locked.")); message->SetViewUIColor(B_PANEL_BACKGROUND_COLOR); rgb_color textColor = ui_color(B_PANEL_TEXT_COLOR); message->SetFontAndColor(be_plain_font, B_FONT_ALL, &textColor); message->MakeEditable(false); message->MakeSelectable(false); message->SetWordWrap(true); rootLayout->AddView(message); rootLayout->AddView(controls); rootLayout->AddView(buttons); } virtual void AttachedToWindow() { fCancelButton->SetTarget(Window()); fUnlockButton->SetTarget(Window()); fUnlockButton->MakeDefault(true); fPassword->MakeFocus(); } void SetUp(const BString& keyringName) { fKeyringName->SetText(keyringName); } status_t Complete(BMessage& keyMessage) { BPasswordKey password(fPassword->Text(), B_KEY_PURPOSE_KEYRING, ""); return password.Flatten(keyMessage); } private: BStringView* fKeyringName; BTextControl* fPassword; BButton* fCancelButton; BButton* fUnlockButton; }; KeyRequestWindow::KeyRequestWindow() : BWindow(BRect(50, 50, 100, 100), B_TRANSLATE("Unlock keyring"), B_TITLED_WINDOW, B_NOT_RESIZABLE | B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE | B_NOT_MINIMIZABLE | B_AUTO_UPDATE_SIZE_LIMITS | B_CLOSE_ON_ESCAPE), fRequestView(NULL), fDoneSem(-1), fResult(B_ERROR) { fDoneSem = create_sem(0, "keyring unlock dialog"); if (fDoneSem < 0) return; BLayout* layout = new(std::nothrow) BGroupLayout(B_HORIZONTAL); if (layout == NULL) return; SetLayout(layout); fRequestView = new(std::nothrow) KeyRequestView(); if (fRequestView == NULL) return; layout->AddView(fRequestView); } KeyRequestWindow::~KeyRequestWindow() { if (fDoneSem >= 0) delete_sem(fDoneSem); } bool KeyRequestWindow::QuitRequested() { fResult = B_CANCELED; release_sem(fDoneSem); return false; } void KeyRequestWindow::MessageReceived(BMessage* message) { switch (message->what) { case kMessageCancel: case kMessageUnlock: fResult = message->what == kMessageUnlock ? B_OK : B_CANCELED; release_sem(fDoneSem); return; } BWindow::MessageReceived(message); } status_t KeyRequestWindow::RequestKey(const BString& keyringName, BMessage& keyMessage) { fRequestView->SetUp(keyringName); ResizeToPreferred(); CenterOnScreen(); Show(); while (acquire_sem(fDoneSem) == B_INTERRUPTED) ; status_t result = fResult; if (result == B_OK) result = fRequestView->Complete(keyMessage); LockLooper(); Quit(); return result; }