From 5dd0761042540ecdee7053338a3d82d12781c951 Mon Sep 17 00:00:00 2001 From: John Scipione Date: Fri, 22 Feb 2013 18:11:14 -0500 Subject: [PATCH 001/104] Move BVolumeRoster docs to Haiku Book. With this commit every class in the storage kit is now documented in the Haiku book! Thanks to Ingo, Axel, Vincent Dominguez, Tyler Dauwalder, and everyone who helped document these classes. --- docs/user/storage/VolumeRoster.dox | 131 +++++++++++++++++++++++++++++ headers/os/storage/VolumeRoster.h | 8 ++ src/kits/storage/VolumeRoster.cpp | 109 ++++-------------------- 3 files changed, 155 insertions(+), 93 deletions(-) create mode 100644 docs/user/storage/VolumeRoster.dox diff --git a/docs/user/storage/VolumeRoster.dox b/docs/user/storage/VolumeRoster.dox new file mode 100644 index 0000000000..e29bfba5c4 --- /dev/null +++ b/docs/user/storage/VolumeRoster.dox @@ -0,0 +1,131 @@ +/* + * Copyright 2002-2013 Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Vincent Dominguez + * John Scipione, jscipione@gmail.com + * Ingo Weinhold, bonefish@users.sf.net + * + * Corresponds to: + * headers/os/storage/VolumeRoster.h hrev45306 + * src/kits/storage/VolumeRoster.cpp hrev45306 + */ + + +/*! + \file VolumeRoster.h + \ingroup storage + \ingroup libbe + \brief Provides the BVolumeRoster class. +*/ + + +/*! + \class BVolumeRoster + \ingroup storage + \ingroup libbe + \brief Provides an interface for iterating through available volumes + and watching for mounting/unmounting. + + This class wraps the next_dev() function for iterating through the + list of available volumes and watch_node()/stop_watching() for + watching volumes. +*/ + + +/*! + \fn BVolumeRoster::BVolumeRoster() + \brief Creates a BVolumeRoster object. The object is ready to be used. +*/ + + +/*! + \fn BVolumeRoster::~BVolumeRoster() + \brief Deletes the volume roster and frees all associated resources. + + If a watch was activated (by StartWatching()), it is deactivated. +*/ + + + +/*! + \fn status_t BVolumeRoster::GetNextVolume(BVolume *volume) + \brief Fills out the passed in BVolume object with the next available + volume. + + \param volume A pointer to a pre-allocated BVolume object to be + initialized to the next available volume. + + \return A status code. + \retval B_OK Everything went fine. + \retval B_BAD_VALUE The last volume in the list was already returned. +*/ + + +/*! + \fn void BVolumeRoster::Rewind() + \brief Rewinds the list of available volumes back to the first item. + + The next call to GetNextVolume() will return the first available volume. +*/ + + +/*! + \fn status_t BVolumeRoster::GetBootVolume(BVolume *volume) + \brief Fills out the passed in BVolume object with the boot volume. + + Currently, this method looks for the volume that is mounted at "/boot". + The only way to fool the system into thinking that there is not a boot + volume is to rename "/boot" -- but, please refrain from doing this. + + \param volume A pointer to a pre-allocated BVolume to be initialized to + refer to the boot volume. + + \return A status code, \c B_OK if everything went fine or an error code + otherwise. +*/ + + +/*! + \fn status_t BVolumeRoster::StartWatching(BMessenger messenger) + \brief Starts watching the available volumes for changes. + + Notifications are sent to the specified target whenever a volume is + mounted or unmounted. The format of the notification messages is + described under watch_node(). Actually BVolumeRoster just provides a + more convenient interface for it. + + If StartWatching() has been called before with another target and no + StopWatching() since, StopWatching() is called first, so that the former + target won't receive any notifications anymore. + + When the object is destroyed all watching ends as well. + + \param messenger The target which the notification messages are sent. + + \return A status code. + \retval B_OK Everything went fine. + \retval B_BAD_VALUE The supplied BMessenger was invalid. + \retval B_NO_MEMORY There was insufficient memory to carry out this + operation. + + \see watch_node() +*/ + + +/*! + \fn void BVolumeRoster::StopWatching() + \brief Stops watching volumes initiated by StartWatching(). + + \see stop_watching() +*/ + + +/*! + \fn BMessenger BVolumeRoster::Messenger() const + \brief Returns the messenger currently watching the volume list. + + \return A messenger to the target currently watching the volume list, or + an invalid messenger if not watching. +*/ diff --git a/headers/os/storage/VolumeRoster.h b/headers/os/storage/VolumeRoster.h index 235c06bc78..2f245144f8 100644 --- a/headers/os/storage/VolumeRoster.h +++ b/headers/os/storage/VolumeRoster.h @@ -36,8 +36,16 @@ private: private: int32 fCookie; + // The iteration cookie for next_dev() + // Initialized to 0 BMessenger* fTarget; + // BMessenger referring to the target to + // which the watching notification + // messages are sent. The object is + // allocated and owned by the roster, + // or NULL if not watching. uint32 _reserved[3]; + // FBC }; diff --git a/src/kits/storage/VolumeRoster.cpp b/src/kits/storage/VolumeRoster.cpp index a04bdcd952..3149ab523f 100644 --- a/src/kits/storage/VolumeRoster.cpp +++ b/src/kits/storage/VolumeRoster.cpp @@ -6,10 +6,7 @@ // // Description: BVolumeRoster class // ---------------------------------------------------------------------- -/*! - \file VolumeRoster.cpp - BVolumeRoster implementation. -*/ + #include #include @@ -21,71 +18,32 @@ #include #include + static const char kBootVolumePath[] = "/boot"; using namespace std; + #ifdef USE_OPENBEOS_NAMESPACE namespace OpenBeOS { #endif -/*! - \class BVolumeRoster - \brief A roster of all volumes available in the system - - Provides an interface for iterating through the volumes available in - the system and watching volume mounting/unmounting. - The class wraps the next_dev() function for iterating through the - volume list and the watch_node()/stop_watching() for the watching - features. - - \author Vincent Dominguez - \author Ingo Weinhold - - \version 0.0.0 -*/ - -/*! \var dev_t BVolumeRoster::fCookie - \brief The iteration cookie for next_dev(). Initialized with 0. -*/ - -/*! \var dev_t BVolumeRoster::fTarget - \brief BMessenger referring to the target to which the watching - notification messages are sent. - - The object is allocated and owned by the roster. \c NULL, if not watching. -*/ - -// constructor -/*! \brief Creates a new BVolumeRoster. - - The object is ready to be used. -*/ BVolumeRoster::BVolumeRoster() : fCookie(0), fTarget(NULL) { } -// destructor -/*! \brief Frees all resources associated with this object. - If a watching was activated on (StartWatching()), it is deactived. -*/ +// Deletes the volume roster and frees all associated resources. BVolumeRoster::~BVolumeRoster() { StopWatching(); } -// GetNextVolume -/*! \brief Returns the next volume in the list of available volumes. - \param volume A pointer to a pre-allocated BVolume to be initialized to - refer to the next volume in the list of available volumes. - \return - - \c B_OK: Everything went fine. - - \c B_BAD_VALUE: The last volume in the list has already been returned. -*/ + +// Fills out the passed in BVolume object with the next available volume. status_t BVolumeRoster::GetNextVolume(BVolume *volume) { @@ -104,29 +62,16 @@ BVolumeRoster::GetNextVolume(BVolume *volume) return error; } -// Rewind -/*! \brief Rewinds the list of available volumes such that the next call to - GetNextVolume() will return the first element in the list. -*/ + +// Rewinds the list of available volumes back to the first item. void BVolumeRoster::Rewind() { fCookie = 0; } -// GetBootVolume -/*! \brief Returns the boot volume. - Currently, this function looks for the volume that is mounted at "/boot". - The only way to fool the system into thinking that there is not a boot - volume is to rename "/boot" -- but, please refrain from doing so...(:o( - - \param volume A pointer to a pre-allocated BVolume to be initialized to - refer to the boot volume. - \return - - \c B_OK: Everything went fine. - - an error code otherwise -*/ +// Fills out the passed in BVolume object with the boot volume. status_t BVolumeRoster::GetBootVolume(BVolume *volume) { @@ -145,27 +90,8 @@ BVolumeRoster::GetBootVolume(BVolume *volume) return error; } -// StartWatching -/*! \brief Starts watching the list of volumes available in the system. - Notifications are sent to the specified target whenever a volume is - mounted or unmounted. The format of the notification messages is - described under watch_node(). Actually BVolumeRoster just provides a - more convenient interface for it. - - If StartWatching() has been called before with another target and no - StopWatching() since, StopWatching() is called first, so that the former - target won't receive any notifications anymore. - - When the object is destroyed all watching has an end as well. - - \param messenger The target to which the notification messages shall be - sent. - \return - - \c B_OK: Everything went fine. - - \c B_BAD_VALUE: The supplied BMessenger is invalid. - - \c B_NO_MEMORY: Insufficient memory to carry out this operation. -*/ +// Starts watching the available volumes for changes. status_t BVolumeRoster::StartWatching(BMessenger messenger) { @@ -188,9 +114,8 @@ BVolumeRoster::StartWatching(BMessenger messenger) return error; } -// StopWatching -/*! \brief Stops volume watching initiated with StartWatching() before. -*/ + +// Stops watching volumes initiated by StartWatching(). void BVolumeRoster::StopWatching() { @@ -201,22 +126,20 @@ BVolumeRoster::StopWatching() } } -// Messenger -/*! \brief Returns a messenger to the target currently watching the volume - list. - \return A messenger to the target currently watching the volume list, or - an invalid messenger, if noone is currently watching. -*/ + +// Returns the messenger currently watching the volume list. BMessenger BVolumeRoster::Messenger() const { return (fTarget ? *fTarget : BMessenger()); } + // FBC void BVolumeRoster::_SeveredVRoster1() {} void BVolumeRoster::_SeveredVRoster2() {} + #ifdef USE_OPENBEOS_NAMESPACE } #endif From d45a713ca1a3ce2d34069e1000c66bea75bdcb8c Mon Sep 17 00:00:00 2001 From: Niels Sascha Reedijk Date: Sat, 23 Feb 2013 06:31:58 +0100 Subject: [PATCH 002/104] Update translations from Pootle --- .../add-ons/disk_systems/intel/fi.catkeys | 4 +-- .../add-ons/disk_systems/ntfs/fi.catkeys | 2 ++ .../media-add-ons/multi_audio/fi.catkeys | 34 +++++++++++++++++++ data/catalogs/apps/drivesetup/fi.catkeys | 21 +++++++++++- data/catalogs/apps/firstbootprompt/fi.catkeys | 3 +- data/catalogs/apps/fontdemo/fi.catkeys | 3 +- data/catalogs/apps/terminal/fi.catkeys | 4 ++- data/catalogs/apps/terminal/pl.catkeys | 3 +- data/catalogs/apps/terminal/sv.catkeys | 3 +- data/catalogs/kits/tracker/fi.catkeys | 3 +- .../preferences/notifications/fi.catkeys | 3 +- .../catalogs/preferences/shortcuts/fi.catkeys | 3 +- data/catalogs/preferences/time/fi.catkeys | 6 +++- 13 files changed, 80 insertions(+), 12 deletions(-) create mode 100644 data/catalogs/add-ons/disk_systems/ntfs/fi.catkeys create mode 100644 data/catalogs/add-ons/media/media-add-ons/multi_audio/fi.catkeys diff --git a/data/catalogs/add-ons/disk_systems/intel/fi.catkeys b/data/catalogs/add-ons/disk_systems/intel/fi.catkeys index 35c09615fd..2c731a804c 100644 --- a/data/catalogs/add-ons/disk_systems/intel/fi.catkeys +++ b/data/catalogs/add-ons/disk_systems/intel/fi.catkeys @@ -1,2 +1,2 @@ -1 finnish x-vnd.Haiku-IntelDiskAddOn 4191422532 -Active partition BFS_Creation_Parameter Aktivoi osio +1 finnish x-vnd.Haiku-IntelDiskAddOn 946918966 +Active partition PrimaryPartitionEditor Aktivoi osio diff --git a/data/catalogs/add-ons/disk_systems/ntfs/fi.catkeys b/data/catalogs/add-ons/disk_systems/ntfs/fi.catkeys new file mode 100644 index 0000000000..23e9dc74a1 --- /dev/null +++ b/data/catalogs/add-ons/disk_systems/ntfs/fi.catkeys @@ -0,0 +1,2 @@ +1 finnish x-vnd.Haiku-NTFSDiskAddOn 25755486 +Name: NTFS_Initialize_Parameter Nimi: diff --git a/data/catalogs/add-ons/media/media-add-ons/multi_audio/fi.catkeys b/data/catalogs/add-ons/media/media-add-ons/multi_audio/fi.catkeys new file mode 100644 index 0000000000..1f4e2fb05d --- /dev/null +++ b/data/catalogs/add-ons/media/media-add-ons/multi_audio/fi.catkeys @@ -0,0 +1,34 @@ +1 finnish x-vnd.Haiku-hmulti_audio.media_addon 451057402 +Master MultiAudio Alkuperäisversio +SPDIF MultiAudio SPDIF +Gain MultiAudio Vahvistus +Output 3D center MultiAudio Tulosta 3D-keskus +Extended Setup MultiAudio Laajennettu asetus +CD MultiAudio CD +Tone control MultiAudio Äänensävyn säätö +Phone MultiAudio Puhelin +Aux MultiAudio Aux +Output bass MultiAudio Basso-ulostulo +Headphones MultiAudio Kuulokkeet +Beep MultiAudio Piip +Output mono mix MultiAudio Monomiksaus-ulostulo +Output stereo mix MultiAudio Stereomiksaus-ulostulo +Input MultiAudio Tulo +Output treble MultiAudio Diskantti-ulostulo +Mono mix MultiAudio Monomiksaus +General MultiAudio Yleisasetukset +Input & Output MultiAudio Tulot ja lähdöt +Enhanced Setup MultiAudio Laajennetut asetukset +Stereo mix MultiAudio Stereomiksaus +Output 3D depth MultiAudio Tulosta 3D-syvyys +Volume MultiAudio Äänenvoimakkuus +Output MultiAudio Lähtö +Video MultiAudio Video +Line MultiAudio Linja +Mic MultiAudio Mikrofoni + frequency: MultiAudio taajuus: +Enable MultiAudio Käytössä +Mute MultiAudio Vaimennettu +Wave MultiAudio Aalto +Setup MultiAudio Asetukset +Level MultiAudio Taso diff --git a/data/catalogs/apps/drivesetup/fi.catkeys b/data/catalogs/apps/drivesetup/fi.catkeys index f82947717e..550de47576 100644 --- a/data/catalogs/apps/drivesetup/fi.catkeys +++ b/data/catalogs/apps/drivesetup/fi.catkeys @@ -1,11 +1,14 @@ -1 finnish x-vnd.Haiku-DriveSetup 644135944 +1 finnish x-vnd.Haiku-DriveSetup 3775412465 DriveSetup System name Levyasema-asetukset +Cancel AbstractParametersPanel Peru Delete MainWindow Poista Are you sure you want to write the changes back to disk now?\n\nAll data on the selected partition will be irretrievably lost if you do so! MainWindow Oletko varma, että haluat nyt kirjoittaa muutokset takaisin levylle?\n\nKaikki valitun osion tiedot katoavat palauttamattomasti, jos teet niin! Rescan MainWindow Etsi uudelleen OK MainWindow Valmis Could not aquire partitioning information. MainWindow Ei voitu hakea osiointitietoja. There's no space on the partition where a child partition could be created. MainWindow Osiolla ei ole mitään tilaa, johon olisi voitu luoda tytärosio. +Initialize InitializeParametersPanel Alusta +OK AbstractParametersPanel Valmis PartitionList Unable to find the selected partition by ID. MainWindow Valitun osion löytäminen tunnisteen perusteella epäonnistui. Select a partition from the list below. DiskView Valitse osio alapuolella olevasta luettelosta. @@ -15,6 +18,7 @@ The selected disk is read-only. MainWindow Valittu levy on kirjoitussuojattu. Are you sure you want to format the partition \"%s\"? You will be asked again before changes are written to the disk. MainWindow Oletko varma, että haluat alustaa osion \"%s\"? Samaa kysytään uudelleen ennen muutosten kirjoittamista levylle. Could not mount partition %s. MainWindow Osion %s liittäminen epäonnistui. The partition %s has been successfully formatted.\n MainWindow Osion %s alustus onnistui.\n +Change parameters MainWindow Vaihda parametreja The partition %s is already unmounted. MainWindow Osio %s on jo liitetty. Failed to delete the partition. No changes have been written to disk. MainWindow Osion poistaminen epäonnistui. Mitään muutoksia ei ole kirjoitettu levylle. Could not delete the selected partition. MainWindow Valitun osion poistaminen epäonnistui. @@ -33,38 +37,53 @@ Write changes MainWindow Kirjoita muutokset There was an error preparing the disk for modifications. MainWindow Tapahtui virhe valmisteltaessa levyä muutoksia varten. The partition %s is already mounted. MainWindow Osio %s on jo liitetty. Are you sure you want to format the partition? You will be asked again before changes are written to the disk. MainWindow Oletko varma, että haluat alustaa osion? Samaa kysytään uudelleen ennen muutosten kirjoittamista levylle. +Partition name: ChangeParametersPanel Osionimi: +Change ChangeParametersPanel Vaihda Are you sure you want to write the changes back to disk now?\n\nAll data on the disk %s will be irretrievably lost if you do so! MainWindow Oletko varma, että haluat nyt kirjoittaa muutokset takaisin levylle?\n\nKaikki levyn %s tiedot katoavat palauttamattomasti, jos teet niin! Are you sure you want to delete the selected partition?\n\nAll data on the partition will be irretrievably lost if you do so! MainWindow Oletko varma, että haluat poistaa valitun osion?\n\nKaikki osion tiedot katoavat palauttamattomasti, jos teet niin! Create… MainWindow Luo… Disk system \"%s\"\" not found! MainWindow Levyjärjestelmää ”%s” ei löytynyt! The disk has been successfully initialized.\n MainWindow Levyn alustus onnistui.\n Could not unmount partition %s. MainWindow Osion %s irrottaminen epäonnistui. +Failed to change the parameters of the partition. No changes have been written to disk. MainWindow Osion parametrien vaihtaminen epäonnistui. Levylle ei ole kirjoitettu mitään muutoksia. Failed to format the partition %s!\n MainWindow Osion %s alustus epäonnistui!\n Mount MainWindow Liitä +Partition type PartitionList Osiotyyppi Are you sure you want to format a raw disk? (most people initialize the disk with a partitioning system first) You will be asked again before changes are written to the disk. MainWindow Oletko varma, että haluat alustaa raakalevyn? (useimmat ihmiset alustavat levyn ensin osiointijärjestelmällä) Samaa kysytään uudelleen ennen kuin muutokset kirjoitetaan levylle. +The panel experienced a problem! MainWindow Paneelissa oli pulmia! +Change parameters… MainWindow Vaihda parametreja... Device PartitionList Laite Disk MainWindow Levy Are you sure you want to initialize the selected disk? All data will be lost. You will be asked again before changes are written to the disk.\n MainWindow Oletko varma, etä haluat alustaa valitun levyn? Kaikki olemassaolevat tiedot katoavat. Samaa kysytään uudelleen ennen kuin muutokset kirjoitetaan levylle.\n +Partition size CreateParametersPanel Osiokoko Device DiskView Laite Active PartitionList Aktiivinen Volume name PartitionList Taltionimi Continue MainWindow Jatka Cannot delete the selected partition. MainWindow Valitun osion poistaminen epäonnistui. Mount all MainWindow Liitä kaikki +End: %s Support Loppu: %s +The panel could not return successfully. MainWindow Paluu paneelista epäonnistui. Cancel MainWindow Peru Delete partition MainWindow Poista osio +Are you sure you want to change parameters of the selected partition?\n\nThe partition may no longer be recognized by other operating systems anymore! MainWindow Oletko varma, että haluat vaihtaa valitun osion parametreja?\n\nMuut käyttöjärjestelmät eivät ehkä enää tunnista osiota! Eject MainWindow Poista asemasta Partition MainWindow Osio +Validation of the given parameters failed. MainWindow Annettujen parametrien todentaminen epäonnistui. +Create CreateParametersPanel Luo File system PartitionList Tiedostojärjestelmä Validation of the given creation parameters failed. MainWindow Annettujen luontiparametrien todentaminen epäonnistui. +Partition type: ChangeParametersPanel Osiotyyppi: Size PartitionList Koko Wipe (not implemented) MainWindow Alustus (ei ole toteutettu) Validation of the given initialization parameters failed. MainWindow Annettujen alustusparametrien todentaminen epäonnistui. The selected partition does not contain a partitioning system. MainWindow Valittu osio ei sisällä osiointijärjestelmää. +Offset: %s Support Siirrososoite: %s Are you sure you want to write the changes back to disk now?\n\nAll data on the partition %s will be irretrievably lost if you do so! MainWindow Oletko varma, että haluat nyt kirjoittaa muutokset takaisin levylle?\n\nKaikki osion %s tiedot kadotetaan palauttamattomasti, jos teet niin! The partition %s is currently mounted. MainWindow Osio %s on nykyisin liitetty. Surface test (not implemented) MainWindow Pintatesti (ei toteutettu) Format MainWindow Alusta +Could not change the parameters of the selected partition. MainWindow Valitun osion parametrien vaihtaminen epäonnistui. Parameters PartitionList Parametrit Creation of the partition has failed. MainWindow Osion luominen epäonnistui. The currently selected partition is not empty. MainWindow Nykyinen valittu osio ei ole tyhjä. diff --git a/data/catalogs/apps/firstbootprompt/fi.catkeys b/data/catalogs/apps/firstbootprompt/fi.catkeys index ab081ab1dc..201ee87863 100644 --- a/data/catalogs/apps/firstbootprompt/fi.catkeys +++ b/data/catalogs/apps/firstbootprompt/fi.catkeys @@ -1,5 +1,6 @@ -1 finnish x-vnd.Haiku-FirstBootPrompt 988630706 +1 finnish x-vnd.Haiku-FirstBootPrompt 2649051796 Custom BootPromptWindow Oma +Boot to Desktop BootPromptWindow Alkukäynnistä työpöydälle Thank you for trying out Haiku! We hope you'll like it!\n\nYou can select your preferred language and keyboard layout from the list on the left which will then be used instantly. You can easily change both settings from the Desktop later on on the fly.\n\nDo you wish to run the Installer or continue booting to the Desktop?\n BootPromptWindow For other languages, a note could be added: \"Note: Localization of Haiku applications and other components is an on-going effort. You will frequently encounter untranslated strings, but if you like, you can join in the work at .\" Kiitoksia siitä, että kokeilet Haikua! Toivomme, että pidät siitä!\n\nVoit valita ensisijaisen kielen ja näppäimistöasetuksen vasemmalla näkyvästä luettelosta. Asetukset otetaan käyttöön välittömästi. Voit helposti vaihtaa molempia asetuksia myöhemmin työpöydältäsi.\n\nHaluatko suorittaa asennusohjelman tai jatkaa alkulautausta työpöydälle?\n Huomaa: Ponnistelemme edelleen Haiku-sovellusten ja muiden komponenttien kotoistamiseksi. Kohtaat usein suomentamattomia merkkijonoja, mutta jos haluat, voit liittyä työhön osoitteessa . Language BootPromptWindow Kieli Welcome to Haiku! BootPromptWindow Tervetuloa Haikuun! diff --git a/data/catalogs/apps/fontdemo/fi.catkeys b/data/catalogs/apps/fontdemo/fi.catkeys index 1db9f835ca..0de04588ca 100644 --- a/data/catalogs/apps/fontdemo/fi.catkeys +++ b/data/catalogs/apps/fontdemo/fi.catkeys @@ -1,4 +1,4 @@ -1 finnish x-vnd.Haiku-FontDemo 1300625863 +1 finnish x-vnd.Haiku-FontDemo 3522850500 Outline: ControlView Ääriviiva: Size: 50 ControlView Koko: 50 Stop cycling ControlView Lopeta kierros @@ -14,6 +14,7 @@ Rotation: 0 ControlView Kierto: 0 Drawing mode: ControlView Piirrostila: Haiku, Inc. ControlView Haiku, Inc. Controls FontDemo Ohjaimet +FontDemo System name FontDemo Outline: %d ControlView Ääriviiva: %d Text: ControlView Teksti: Antialiased text ControlView Peitenimetön teksti diff --git a/data/catalogs/apps/terminal/fi.catkeys b/data/catalogs/apps/terminal/fi.catkeys index 8854ac9b93..bff140c840 100644 --- a/data/catalogs/apps/terminal/fi.catkeys +++ b/data/catalogs/apps/terminal/fi.catkeys @@ -1,4 +1,4 @@ -1 finnish x-vnd.Haiku-Terminal 766764238 +1 finnish x-vnd.Haiku-Terminal 2645209895 Not found. Terminal TermWindow Ei löytynyt. Switch Terminals Terminal TermWindow Vaihda pääteikkunoita Change directory Terminal TermView Vaihda hakemistoa @@ -21,6 +21,7 @@ Font: Terminal AppearancePrefView Kirjasintyyppi: Copy here Terminal TermView Kopioi tänne Really close? Terminal TermWindow Suljetaanko todella? Copy Terminal TermWindow Kopioi +Terminal Terminal TermWindow The title for the main window menubar entry related to terminal sessions Pääteikkuna Color scheme: Terminal AppearancePrefView Väriteema: Window title: Terminal TermWindow Ikkunaotsikko: Unrecognized option \"%s\"\n Terminal arguments parsing Tunnistamaton valitsin ”%s”\n @@ -61,6 +62,7 @@ Text not found. Terminal TermWindow Tekstiä ei löydy. Find… Terminal TermWindow Etsi... The process \"%1\" is still running.\nIf you close the Terminal, the process will be killed. Terminal TermWindow Prosessia ”%1” suoritetaan yhä.\nJos suljet Pääteikkunan, prosessi tapetaan. Move here Terminal TermView Siirrä tänne +\t%d\t-\tThe current working directory of the active process in the\n\t\t\tcurrent tab. Optionally the maximum number of path components\n\t\t\tcan be specified. E.g. '%2d' for at most two components.\n\t%T\t-\tThe Terminal application name for the current locale.\n\t%i\t-\tThe index of the window.\n\t%p\t-\tThe name of the active process in the current tab.\n\t%t\t-\tThe title of the current tab.\n\t%%\t-\tThe character '%'. Terminal ToolTips \t%d\t-\tAktiivin prosessin nykyinen työhakemisto on nykyisessä\n\t\t\tvälilehdessä. Valinnaisesti voidaan määritellä polkukomponenttien\n\t\t\tenimmäismäärä. Esim.: '%2d' vähintään kahdelle komponentille.\n\t%T\t-\tPääteikkunan nimi nykyisillä paikallisasetuksilla.\n\t%i\t-\tIkkunaindeksi.\n\t%p\t-\tAktiivin prosessin nimi nykyisessä välilehdessä.\n\t%t\t-\tThe title of the current tab.\n\t%%\t-\tMerkki '%'. Retro Terminal colors scheme Retro Error! Terminal getString Virhe! New tab Terminal TermWindow Uusi välilehti diff --git a/data/catalogs/apps/terminal/pl.catkeys b/data/catalogs/apps/terminal/pl.catkeys index 03b377fbe1..eb7a42351a 100644 --- a/data/catalogs/apps/terminal/pl.catkeys +++ b/data/catalogs/apps/terminal/pl.catkeys @@ -1,4 +1,4 @@ -1 polish x-vnd.Haiku-Terminal 3435701556 +1 polish x-vnd.Haiku-Terminal 2997644674 Not found. Terminal TermWindow Nie znaleziono. Switch Terminals Terminal TermWindow Przełącz Terminal Change directory Terminal TermView Zmień folder @@ -21,6 +21,7 @@ Font: Terminal AppearancePrefView Czcionka: Copy here Terminal TermView Kopiuj tutaj Really close? Terminal TermWindow Na pewno zamknąć? Copy Terminal TermWindow Kopiuj +Terminal Terminal TermWindow The title for the main window menubar entry related to terminal sessions Terminal Color scheme: Terminal AppearancePrefView Schemat kolorów: Window title: Terminal TermWindow Tytuł okna: Unrecognized option \"%s\"\n Terminal arguments parsing Nieznana opcja \"%s\"\n diff --git a/data/catalogs/apps/terminal/sv.catkeys b/data/catalogs/apps/terminal/sv.catkeys index 0daa3e3a83..109c858073 100644 --- a/data/catalogs/apps/terminal/sv.catkeys +++ b/data/catalogs/apps/terminal/sv.catkeys @@ -1,4 +1,4 @@ -1 swedish x-vnd.Haiku-Terminal 328707356 +1 swedish x-vnd.Haiku-Terminal 2645209895 Not found. Terminal TermWindow Hittades ej. Switch Terminals Terminal TermWindow Växla terminal Change directory Terminal TermView Byt katalog @@ -62,6 +62,7 @@ Text not found. Terminal TermWindow Text hittades inte. Find… Terminal TermWindow Sök... The process \"%1\" is still running.\nIf you close the Terminal, the process will be killed. Terminal TermWindow Processen \"%1\" körs fortfarande.\nOm du stänger Terminalen kommer processen att termineras. Move here Terminal TermView Flytta hit +\t%d\t-\tThe current working directory of the active process in the\n\t\t\tcurrent tab. Optionally the maximum number of path components\n\t\t\tcan be specified. E.g. '%2d' for at most two components.\n\t%T\t-\tThe Terminal application name for the current locale.\n\t%i\t-\tThe index of the window.\n\t%p\t-\tThe name of the active process in the current tab.\n\t%t\t-\tThe title of the current tab.\n\t%%\t-\tThe character '%'. Terminal ToolTips \t%d\t-\t Arbetskatalogen till den aktiva processen på den valda tabben\n\t\t\t eller de maximala antal sökvägs komponenter kan bli specificerade.\n\t\t\t E.g. '%2d' för att ange två komponenter.\n\t%T\t-\tTerminal applikationsnamnet för denna översättning.\n\t%i\t-\t Indexet för detta fönster.\n\t%p\t-\tNamnet på den aktiva processen io den valda tabben.\n\t%t\t-\tNamnet på den valda tabben.\n\t%%\t-\t Tecknet '%'. Retro Terminal colors scheme Retro Error! Terminal getString Fel! New tab Terminal TermWindow Ny flik diff --git a/data/catalogs/kits/tracker/fi.catkeys b/data/catalogs/kits/tracker/fi.catkeys index a845ad861d..2987ff7db6 100644 --- a/data/catalogs/kits/tracker/fi.catkeys +++ b/data/catalogs/kits/tracker/fi.catkeys @@ -1,4 +1,4 @@ -1 finnish x-vnd.Haiku-libtracker 3375521561 +1 finnish x-vnd.Haiku-libtracker 4167158175 common B_COMMON_DIRECTORY yhteinen OK WidgetAttributeText Valmis Icon view VolumeWindow Kuvakenäkymä @@ -74,6 +74,7 @@ Arrange by ContainerWindow Järjestä: Mount server error AutoMounterSettings Liittämispalvelinvirhe Search FindPanel Haku Preparing to empty Trash… StatusWindow Valmistaudutaan tyhjentämään roskakori... +You cannot put the selected item(s) into the trash. FSUtils Et voi laittaa valittuja kohteita roskakoriin. Disks Model Levyt Create link ContainerWindow Luo linkki develop B_COMMON_DEVELOP_DIRECTORY kehitys diff --git a/data/catalogs/preferences/notifications/fi.catkeys b/data/catalogs/preferences/notifications/fi.catkeys index 8cd6347683..c231615623 100644 --- a/data/catalogs/preferences/notifications/fi.catkeys +++ b/data/catalogs/preferences/notifications/fi.catkeys @@ -1,4 +1,4 @@ -1 finnish x-vnd.Haiku-Notifications 814394708 +1 finnish x-vnd.Haiku-Notifications 2177286129 An error occurred saving the preferences.\nIt's possible you are running out of disk space. GeneralView Tapahtui virhe tallennettaessa asetuksia.\nOn mahdollista, että levytila on loppunut. Notifications GeneralView Ilmoitukset seconds of inactivity GeneralView joutilaisuussekunnit @@ -17,6 +17,7 @@ Cannot disable notifications because the server can't be reached. GeneralView I Progress NotificationView Edistyminen Last Received NotificationView Viimeksi vastaanotettu General PrefletView Yleistä +Apply PrefletWin Käytä Display PrefletView Näyttö Can't enable notifications at startup time, you probably don't have write permission to the boot settings directory. GeneralView Ilmoitusten ottaminen käyttöön käynnistysaikana epäonnistui. Sinulla ei luultavasti ole kirjoitusoikeutta alkulatausasetushakemistoon. Search: NotificationView Etsintä: diff --git a/data/catalogs/preferences/shortcuts/fi.catkeys b/data/catalogs/preferences/shortcuts/fi.catkeys index 76741a339d..4abbd2e251 100644 --- a/data/catalogs/preferences/shortcuts/fi.catkeys +++ b/data/catalogs/preferences/shortcuts/fi.catkeys @@ -1,4 +1,4 @@ -1 finnish x-vnd.Haiku-Shortcuts 3397621807 +1 finnish x-vnd.Haiku-Shortcuts 341885426 Error, NULL state description?\n ShortcutsSpec Virhe, NULL-tilakuvaus?\n MoveMouse ShortcutsSpec SiirräHiirtä OK ShortcutsWindow Valmis @@ -20,6 +20,7 @@ Shortcuts was couldn't open your KeySet file! ShortcutsWindow Pikanäppäinaset *Multi \"*MoveMouseTo 100% 0\" \"*MouseButton 1\" ShortcutsWindow *Moni ”*SiirräHiiriKohteeseen 100% 0” ”*Hiiripainike 1” SendMessage ShortcutsSpec LähetäViesti MoveMouseTo ShortcutsSpec SiirräHiiriKohteeseen +Option ShortcutsSpec Name for modifier on keyboard Valitsin Save ShortcutsWindow Tallenna *MouseButton 1 ShortcutsWindow *Hiiripainike 1 *MoveMouse +20 +0 ShortcutsWindow *SiirräHiiri +20 +0 diff --git a/data/catalogs/preferences/time/fi.catkeys b/data/catalogs/preferences/time/fi.catkeys index ddfd8ab012..96e2973d03 100644 --- a/data/catalogs/preferences/time/fi.catkeys +++ b/data/catalogs/preferences/time/fi.catkeys @@ -1,4 +1,4 @@ -1 finnish x-vnd.Haiku-Time 3544635877 +1 finnish x-vnd.Haiku-Time 3259467657 GMT (UNIX compatible) Time Greenwichin aika (UNIX-yhteensopiva) OK Time Valmis Asia Time Aasia @@ -11,6 +11,7 @@ Preview time: Time Esikatseluaika: Synchronize Time Synkronoi Revert Time Palauta Pacific Time Tyyni valtameri +Show day of week Time Näytä viikonpäivä Add Time Lisää Date and time Time Päivämäärä ja aika about Time Ohjelmasta @@ -26,6 +27,7 @@ Time Time Aika Indian Time Intia Sending request failed Time Pyynnön lähettäminen epäonnistui Arctic Time Pohjoinen napaseutu +Display time with seconds Time Näytä aika sekunteina Time System name Aika-asetukset America Time Amerikka Reset Time Nollaa @@ -33,6 +35,8 @@ Synchronize at boot Time Synkronoi alkulatauksen yhteydessä Time & Date, written by:\n\n\tAndrew Edward McCall\n\tMike Berg\n\tJulun\n\tPhilippe Saint-Pierre\n\nCopyright 2004-2012, Haiku. Time Time & Date, tekijät:\n\n\tAndrew Edward McCall\n\tMike Berg\n\tJulun\n\tPhilippe Saint-Pierre\n\nCopyright 2004-2012, Haiku. Received invalid time Time Vastaanotettiin virheellinen aika Antarctica Time Etelänapamanner +Show time zone Time Näytä aikavyöhyke +Show clock in Deskbar Time Näytä kello työpöytäpalkissa The following error occured while synchronizing:r\n%s: %s Time Seuraava virhe tapahtui synkronoinnin aikana:r\n%s: %s Time Current time: Time Nykyinen aika: From a2d1b65a85f33469f29aada03646b0aed4a61f92 Mon Sep 17 00:00:00 2001 From: John Scipione Date: Sat, 23 Feb 2013 14:40:26 -0500 Subject: [PATCH 003/104] Silly style fixes --- src/preferences/time/ClockView.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/preferences/time/ClockView.cpp b/src/preferences/time/ClockView.cpp index 8c51c675a1..82085c9f33 100644 --- a/src/preferences/time/ClockView.cpp +++ b/src/preferences/time/ClockView.cpp @@ -6,6 +6,7 @@ * John Scipione */ + #include "ClockView.h" #include @@ -24,9 +25,8 @@ #include "TimeMessages.h" -static const char* kDeskbarSignature = "application/x-vnd.Be-TSKB"; - -static const float kIndentSpacing +static const char* kDeskbarSignature = "application/x-vnd.Be-TSKB"; +static const float kIndentSpacing = be_control_look->DefaultItemSpacing() * 2.3; From ca00f398da7f8cd19698205769fdf8cb6f2bde83 Mon Sep 17 00:00:00 2001 From: John Scipione Date: Sat, 23 Feb 2013 14:41:54 -0500 Subject: [PATCH 004/104] Fix Deskbar clock show/hide when Deskbar is hidden. Bug #9469 happens because I set the showClock checkbox or not based on whether or not the clock is currently hidden. This works most of the time, but if Deskbar is hidden the clock is also considered to be hidden and that isn't what I want in this case. The solution is to override BView's Show(), Hide(), and IsHidden() methods in TimeView to ignore whether or not the window is hidden when considering if the clock is hidden. The commit also deletes some no-longer-used private member variables of TimeView. Fixes #9469 --- src/apps/deskbar/TimeView.cpp | 28 +++++++++++++++++++++++++++- src/apps/deskbar/TimeView.h | 11 ++++++----- 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/src/apps/deskbar/TimeView.cpp b/src/apps/deskbar/TimeView.cpp index 0c6d0c8c10..02e7162017 100644 --- a/src/apps/deskbar/TimeView.cpp +++ b/src/apps/deskbar/TimeView.cpp @@ -37,6 +37,8 @@ All rights reserved. #include "TimeView.h" #include +#include + // for INT16_MIN and INT16_MAX #include #include @@ -69,6 +71,7 @@ TTimeView::TTimeView(float maxWidth, float height) fMaxWidth(maxWidth), fHeight(height), fOrientation(true), + fShowLevel(0), fShowSeconds(false), fShowDayOfWeek(false), fShowTimeZone(false) @@ -116,10 +119,11 @@ status_t TTimeView::Archive(BMessage* data, bool deep) const { BView::Archive(data, deep); + data->AddBool("orientation", fOrientation); + data->AddInt16("showLevel", fShowLevel); data->AddBool("showSeconds", fShowSeconds); data->AddBool("showDayOfWeek", fShowDayOfWeek); data->AddBool("showTimeZone", fShowTimeZone); - data->AddBool("orientation", fOrientation); data->AddInt32("deskbar:private_align", B_ALIGN_RIGHT); return B_OK; @@ -183,6 +187,17 @@ TTimeView::GetPreferredSize(float* width, float* height) } +void +TTimeView::Hide() +{ + // Prevent overflow + if (fShowLevel < INT16_MAX) + ++fShowLevel; + + BView::Hide(); +} + + void TTimeView::MessageReceived(BMessage* message) { @@ -292,6 +307,17 @@ TTimeView::ResizeToPreferred() } +void +TTimeView::Show() +{ + // Prevent underflow + if (fShowLevel > INT16_MIN) + --fShowLevel; + + BView::Show(); +} + + // # pragma mark - Public methods diff --git a/src/apps/deskbar/TimeView.h b/src/apps/deskbar/TimeView.h index 129b2021fb..9f28a1ca04 100644 --- a/src/apps/deskbar/TimeView.h +++ b/src/apps/deskbar/TimeView.h @@ -88,10 +88,13 @@ public: void Draw(BRect update); void FrameMoved(BPoint); void GetPreferredSize(float* width, float* height); + void Hide(); + bool IsHidden() const { return fShowLevel > 0; }; void MessageReceived(BMessage*); void MouseDown(BPoint where); void Pulse(); void ResizeToPreferred(); + void Show(); bool Orientation() const; void SetOrientation(bool o); @@ -133,16 +136,14 @@ private: float fMaxWidth; float fHeight; - bool fOrientation; // vertical = true + bool fOrientation; + // vertical = true + int16 fShowLevel; - bool fOverrideLocale; - bool fUse24HourClock; bool fShowSeconds; bool fShowDayOfWeek; bool fShowTimeZone; - BString fTimeFormat; - BPoint fTimeLocation; BPoint fDateLocation; From 2c765fafc57141bcb456fc0005b4dbf61d12df22 Mon Sep 17 00:00:00 2001 From: John Scipione Date: Sat, 23 Feb 2013 15:51:50 -0500 Subject: [PATCH 005/104] Rename ColorWell to ColorPreview in Appearance prefs. No functional change intended. I'd like to use the name "ColorWell" for a different type of class eventually so I'm making room for it. ColorPreview is arguably a better name for the class anyway. Also did a style cleanup of the ColorWell => ColorPreview class at the same time. --- src/preferences/appearance/APRView.cpp | 18 +-- src/preferences/appearance/APRView.h | 7 +- src/preferences/appearance/ColorPreview.cpp | 153 ++++++++++++++++++++ src/preferences/appearance/ColorPreview.h | 47 ++++++ src/preferences/appearance/ColorWell.cpp | 141 ------------------ src/preferences/appearance/ColorWell.h | 36 ----- src/preferences/appearance/Jamfile | 5 +- 7 files changed, 214 insertions(+), 193 deletions(-) create mode 100644 src/preferences/appearance/ColorPreview.cpp create mode 100644 src/preferences/appearance/ColorPreview.h delete mode 100644 src/preferences/appearance/ColorWell.cpp delete mode 100644 src/preferences/appearance/ColorWell.h diff --git a/src/preferences/appearance/APRView.cpp b/src/preferences/appearance/APRView.cpp index 33b59d5d3a..6b7c1e0873 100644 --- a/src/preferences/appearance/APRView.cpp +++ b/src/preferences/appearance/APRView.cpp @@ -25,9 +25,9 @@ #include "APRWindow.h" #include "defs.h" -#include "ColorWell.h" -#include "ColorWhichItem.h" +#include "ColorPreview.h" #include "ColorSet.h" +#include "ColorWhichItem.h" #undef B_TRANSLATION_CONTEXT @@ -87,8 +87,8 @@ APRView::APRView(const char* name) } BRect wellrect(0, 0, 50, 50); - fColorWell = new ColorWell(wellrect, new BMessage(COLOR_DROPPED), 0); - fColorWell->SetExplicitAlignment(BAlignment(B_ALIGN_HORIZONTAL_CENTER, + fColorPreview = new ColorPreview(wellrect, new BMessage(COLOR_DROPPED), 0); + fColorPreview->SetExplicitAlignment(BAlignment(B_ALIGN_HORIZONTAL_CENTER, B_ALIGN_BOTTOM)); fPicker = new BColorControl(B_ORIGIN, B_CELLS_32x8, 8.0, @@ -100,14 +100,14 @@ APRView::APRView(const char* name) .Add(fScrollView) .Add(BSpaceLayoutItem::CreateVerticalStrut(5)) .Add(BGroupLayoutBuilder(B_HORIZONTAL) - .Add(fColorWell) + .Add(fColorPreview) .Add(BSpaceLayoutItem::CreateHorizontalStrut(5)) .Add(fPicker) ) .SetInsets(10, 10, 10, 10) ); - fColorWell->Parent()->SetExplicitMaxSize( + fColorPreview->Parent()->SetExplicitMaxSize( BSize(B_SIZE_UNSET, fPicker->Bounds().Height())); fAttrList->SetSelectionMessage(new BMessage(ATTRIBUTE_CHOSEN)); } @@ -123,7 +123,7 @@ APRView::AttachedToWindow() { fPicker->SetTarget(this); fAttrList->SetTarget(this); - fColorWell->SetTarget(this); + fColorPreview->SetTarget(this); fAttrList->Select(0); } @@ -257,8 +257,8 @@ APRView::_UpdateControls() } fPicker->SetValue(color); - fColorWell->SetColor(color); - fColorWell->Invalidate(); + fColorPreview->SetColor(color); + fColorPreview->Invalidate(); } diff --git a/src/preferences/appearance/APRView.h b/src/preferences/appearance/APRView.h index 1cfd6003da..41b65cd54d 100644 --- a/src/preferences/appearance/APRView.h +++ b/src/preferences/appearance/APRView.h @@ -31,9 +31,8 @@ #include "ColorSet.h" -class ColorWell; class APRWindow; - +class ColorPreview; class APRView : public BView { public: @@ -65,11 +64,11 @@ private: BScrollView* fScrollView; - ColorWell* fColorWell; + ColorPreview* fColorPreview; ColorSet fCurrentSet; ColorSet fPrevSet; ColorSet fDefaultSet; }; -#endif +#endif // APR_VIEW_H_ diff --git a/src/preferences/appearance/ColorPreview.cpp b/src/preferences/appearance/ColorPreview.cpp new file mode 100644 index 0000000000..81ce2bf201 --- /dev/null +++ b/src/preferences/appearance/ColorPreview.cpp @@ -0,0 +1,153 @@ +/* + * Copyright 2002-2013 Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * DarkWyrm, darkwyrm@earthlink.net + * John Scipione, jscipione@gmail.com + */ + + +#include "ColorPreview.h" + + +ColorPreview::ColorPreview(BRect frame, BMessage* message, + uint32 resizingMode, uint32 flags) + : + BView(frame,"ColorPreview", resizingMode, flags | B_WILL_DRAW) +{ + SetViewColor(B_TRANSPARENT_COLOR); + SetLowColor(0, 0, 0); + invoker = new BInvoker(message, this); + disabledcol.red = 128; + disabledcol.green = 128; + disabledcol.blue = 128; + disabledcol.alpha = 255; + is_enabled = true; + is_rect = true; +} + + +ColorPreview::~ColorPreview(void) +{ + delete invoker; +} + + +void +ColorPreview::Draw(BRect update) +{ + rgb_color color; + if (is_enabled) + color = currentcol; + else + color = disabledcol; + + if (is_rect) { + if (is_enabled) { + BRect r(Bounds()); + SetHighColor(184, 184, 184); + StrokeRect(r); + + SetHighColor(255, 255, 255); + StrokeLine(BPoint(r.right, r.top + 1), r.RightBottom()); + + r.InsetBy(1, 1); + + SetHighColor(216, 216, 216); + StrokeLine(r.RightTop(), r.RightBottom()); + + SetHighColor(96, 96, 96); + StrokeLine(r.LeftTop(), r.RightTop()); + StrokeLine(r.LeftTop(), r.LeftBottom()); + + r.InsetBy(1, 1); + SetHighColor(color); + FillRect(r); + } else { + SetHighColor(color); + FillRect(Bounds()); + } + } else { + // fill background + SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + FillRect(update); + + SetHighColor(color); + FillEllipse(Bounds()); + if (is_enabled) + StrokeEllipse(Bounds(), B_SOLID_LOW); + } +} + + +void +ColorPreview::MessageReceived(BMessage* message) +{ + // If we received a dropped message, see if it contains color data + if (message->WasDropped()) { + rgb_color* col; + uint8* ptr; + ssize_t size; + if (message->FindData("RGBColor", (type_code)'RGBC', + (const void**)&ptr,&size) == B_OK) { + col = (rgb_color*)ptr; + SetHighColor(*col); + } + } + + BView::MessageReceived(message); +} + + +void +ColorPreview::SetEnabled(bool value) +{ + if (is_enabled != value) { + is_enabled = value; + Invalidate(); + } +} + + +void +ColorPreview::SetTarget(BHandler* target) +{ + invoker->SetTarget(target); +} + + +rgb_color +ColorPreview::Color(void) const +{ + return currentcol; +} + + +void +ColorPreview::SetColor(rgb_color col) +{ + SetHighColor(col); + currentcol = col; + Draw(Bounds()); + invoker->Invoke(); +} + + +void +ColorPreview::SetColor(uint8 r,uint8 g, uint8 b) +{ + SetHighColor(r,g,b); + currentcol.red = r; + currentcol.green = g; + currentcol.blue = b; + Draw(Bounds()); + invoker->Invoke(); +} + + +void +ColorPreview::SetMode(bool is_rectangle) +{ + is_rect = is_rectangle; +} diff --git a/src/preferences/appearance/ColorPreview.h b/src/preferences/appearance/ColorPreview.h new file mode 100644 index 0000000000..a293e40ceb --- /dev/null +++ b/src/preferences/appearance/ColorPreview.h @@ -0,0 +1,47 @@ +/* + * Copyright 2002-2013 Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * DarkWyrm, darkwyrm@earthlink.net + * John Scipione, jscipione@gmail.com + */ +#ifndef COLOR_PREVIEW_H_ +#define COLOR_PREVIEW_H_ + + +#include +#include +#include + + +class ColorPreview : public BView +{ +public: + ColorPreview(BRect frame, BMessage *msg, + uint32 resizingMode = B_FOLLOW_LEFT + | B_FOLLOW_TOP, + uint32 flags = B_WILL_DRAW); + ~ColorPreview(void); + + virtual void Draw(BRect update); + virtual void MessageReceived(BMessage* message); + virtual void SetTarget(BHandler* target); + virtual void SetEnabled(bool value); + + rgb_color Color(void) const; + void SetColor(rgb_color col); + void SetColor(uint8 r,uint8 g, uint8 b); + + void SetMode(bool is_rectangle); + +protected: + BInvoker* invoker; + + bool is_enabled; + bool is_rect; + rgb_color disabledcol; + rgb_color currentcol; +}; + +#endif // COLOR_PREVIEW_H_ diff --git a/src/preferences/appearance/ColorWell.cpp b/src/preferences/appearance/ColorWell.cpp deleted file mode 100644 index 2a5e5eab0c..0000000000 --- a/src/preferences/appearance/ColorWell.cpp +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright 2002-2006, Haiku. All rights reserved. - * Distributed under the terms of the MIT License. - * - * Authors: - * DarkWyrm (darkwyrm@earthlink.net) - */ -#include "ColorWell.h" - -ColorWell::ColorWell(BRect frame, BMessage *msg, uint32 resizingMode, uint32 flags) - : BView(frame,"ColorWell", resizingMode, flags | B_WILL_DRAW) -{ - SetViewColor(B_TRANSPARENT_COLOR); - SetLowColor(0,0,0); - invoker=new BInvoker(msg,this); - disabledcol.red=128; - disabledcol.green=128; - disabledcol.blue=128; - disabledcol.alpha=255; - is_enabled=true; - is_rect = true; -} - -ColorWell::~ColorWell(void) -{ - delete invoker; -} - -void -ColorWell::SetTarget(BHandler *tgt) -{ - invoker->SetTarget(tgt); -} - -void -ColorWell::SetColor(rgb_color col) -{ - SetHighColor(col); - currentcol=col; - Draw(Bounds()); - invoker->Invoke(); -} - -void -ColorWell::SetColor(uint8 r,uint8 g, uint8 b) -{ - SetHighColor(r,g,b); - currentcol.red=r; - currentcol.green=g; - currentcol.blue=b; - Draw(Bounds()); - invoker->Invoke(); -} - -void -ColorWell::MessageReceived(BMessage *msg) -{ - // If we received a dropped message, try to see if it has color data - // in it - if(msg->WasDropped()) { - rgb_color *col; - uint8 *ptr; - ssize_t size; - if(msg->FindData("RGBColor",(type_code)'RGBC', - (const void**)&ptr,&size)==B_OK) { - col=(rgb_color*)ptr; - SetHighColor(*col); - } - } - - // The default - BView::MessageReceived(msg); -} - -void -ColorWell::SetEnabled(bool value) -{ - if(is_enabled!=value) { - is_enabled=value; - Invalidate(); - } -} - -void -ColorWell::Draw(BRect update) -{ - rgb_color color; - if (is_enabled) - color = currentcol; - else - color = disabledcol; - - if(is_rect) { - if(is_enabled) { - BRect r(Bounds()); - SetHighColor(184,184,184); - StrokeRect(r); - - SetHighColor(255,255,255); - StrokeLine(BPoint(r.right, r.top+1), r.RightBottom()); - - r.InsetBy(1,1); - - SetHighColor(216,216,216); - StrokeLine(r.RightTop(), r.RightBottom()); - - SetHighColor(96,96,96); - StrokeLine(r.LeftTop(), r.RightTop()); - StrokeLine(r.LeftTop(), r.LeftBottom()); - - r.InsetBy(1, 1); - SetHighColor(color); - FillRect(r); - } else { - SetHighColor(color); - FillRect(Bounds()); - } - } - else { - // fill background - SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR)); - FillRect(update); - - SetHighColor(color); - FillEllipse(Bounds()); - if(is_enabled) - StrokeEllipse(Bounds(),B_SOLID_LOW); - } -} - -rgb_color -ColorWell::Color(void) const -{ - return currentcol; -} - -void -ColorWell::SetMode(bool is_rectangle) -{ - is_rect=is_rectangle; -} diff --git a/src/preferences/appearance/ColorWell.h b/src/preferences/appearance/ColorWell.h deleted file mode 100644 index 92c2ea5f20..0000000000 --- a/src/preferences/appearance/ColorWell.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2002-2006, Haiku. All rights reserved. - * Distributed under the terms of the MIT License. - * - * Authors: - * DarkWyrm (darkwyrm@earthlink.net) - */ -#ifndef COLORWELL_H_ -#define COLORWELL_H_ - -#include -#include -#include - -class ColorWell : public BView -{ -public: - ColorWell(BRect frame, BMessage *msg, - uint32 resizingMode = B_FOLLOW_LEFT | B_FOLLOW_TOP, - uint32 flags = B_WILL_DRAW); - ~ColorWell(void); - void SetColor(rgb_color col); - rgb_color Color(void) const; - void SetColor(uint8 r,uint8 g, uint8 b); - virtual void MessageReceived(BMessage *msg); - virtual void Draw(BRect update); - virtual void SetTarget(BHandler *tgt); - virtual void SetEnabled(bool value); - void SetMode(bool is_rectangle); -protected: - BInvoker *invoker; - bool is_enabled, is_rect; - rgb_color disabledcol, currentcol; -}; - -#endif diff --git a/src/preferences/appearance/Jamfile b/src/preferences/appearance/Jamfile index 1c287a91ac..ca3eb7dcc4 100644 --- a/src/preferences/appearance/Jamfile +++ b/src/preferences/appearance/Jamfile @@ -15,8 +15,8 @@ Preference Appearance : FontView.cpp APRView.cpp APRWindow.cpp + ColorPreview.cpp ColorSet.cpp - ColorWell.cpp ColorWhichItem.cpp # These are currently disabled while everything else is being worked on @@ -38,11 +38,10 @@ DoCatalogs Appearance : AntialiasingSettingsView.cpp APRView.cpp APRWindow.cpp + ColorPreview.cpp ColorSet.cpp - ColorWell.cpp ColorWhichItem.cpp LookAndFeelSettingsView.cpp FontView.cpp FontSelectionView.cpp ; - From 59dc9ee9552e994240a535467e88d15ee279938b Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Sun, 24 Feb 2013 06:32:15 +0000 Subject: [PATCH 006/104] radeon_hd: Fix DVI-I detection once and for all * Reduced the logic down and only use it where possible. * Remove the duplicate gpio pin check. While this is a determining factor... i'd rather get it right while detecting displays vs relying on connector order in the ASIC. This gpio pin check was also severely bugged (missing {}'s) * Should fix #8913 and maybe others --- src/add-ons/accelerants/radeon_hd/display.cpp | 80 ++++++------------- 1 file changed, 24 insertions(+), 56 deletions(-) diff --git a/src/add-ons/accelerants/radeon_hd/display.cpp b/src/add-ons/accelerants/radeon_hd/display.cpp index 3400f083f4..321275c8ac 100644 --- a/src/add-ons/accelerants/radeon_hd/display.cpp +++ b/src/add-ons/accelerants/radeon_hd/display.cpp @@ -241,29 +241,6 @@ detect_crt_ranges(uint32 crtid) } -static void -remove_dup_displays(uint32 displayIndex, uint32 id) -{ - /* hack for both digital and analog interfaces active */ - if ((displayIndex > 0) && gDisplay[displayIndex]->attached) { - if (gConnector[id-1]->encoder.type == VIDEO_ENCODER_TMDS) { - int gpioID1 = gConnector[id-1]->gpioID; - int gpioID2 = gConnector[id]->gpioID; - edid1_info* edid = &gDisplay[displayIndex-1]->edidData; - - if ((gGPIOInfo[gpioID1]->hwPin == gGPIOInfo[gpioID2]->hwPin) && - edid->display.input_type) - // give preference to digital display when both are present - // and other display indicates it is digital - TRACE("%s: skipping connector %" B_PRIu32 - ": giving preference to digital " - "connector %d\n", __func__, id, id-1); - gDisplay[displayIndex]->attached = 0; - } - } -} - - status_t detect_displays() { @@ -332,45 +309,36 @@ detect_displays() gDisplay[displayIndex]->attached = connector_read_edid(id, &gDisplay[displayIndex]->edidData); - // Since DVI-I shows up as two connectors, and there is only one - // edid channel, we have to make *sure* the edid data received is - // valid for the connector. - // Found EDID data? if (gDisplay[displayIndex]->attached) { TRACE("%s: connector(%" B_PRIu32 "): found EDID data.\n", __func__, id); - bool analogEncoder - = gConnector[id]->encoder.type == VIDEO_ENCODER_TVDAC - || gConnector[id]->encoder.type == VIDEO_ENCODER_DAC; + if (gConnector[id]->type == VIDEO_CONNECTOR_DVII + || gConnector[id]->type == VIDEO_CONNECTOR_HDMIB) { + // These connectors can share gpio pins for data + // communication between digital and analog encoders + // (DVI-I is most common) + edid1_info* edid = &gDisplay[displayIndex]->edidData; - edid1_info* edid = &gDisplay[displayIndex]->edidData; - if (!edid->display.input_type && analogEncoder) { - // If non-digital EDID + the encoder is analog... - TRACE("%s: connector(%" B_PRIu32 "): has non-digital EDID " - "and a analog encoder.\n", __func__, id); - gDisplay[displayIndex]->attached - = encoder_analog_load_detect(id); - remove_dup_displays(displayIndex, id); - } else if (edid->display.input_type && !analogEncoder) { - // If EDID is digital, we make an assumption here. - TRACE("%s: connector(%" B_PRIu32 "): has digital EDID " - "and is not a analog encoder.\n", __func__, id); - } else { - // This generally means the monitor is of poor design - // Since we *know* there is no load on the analog encoder - // we assume that it is a digital display. - // This can also occur when a display has both DVI and VGA - // inputs and the graphics board has a DVI-I connector - // (reported as both digital and analog connectors) and the - // analog connection is the one in use. In that case, we - // get here when checking the digital connector and want - // to disable that display in favor of the analog one. - TRACE("%s: connector(%" B_PRIu32 "): Warning: monitor has " - "false digital EDID flag + unloaded analog encoder!\n", - __func__, id); - gDisplay[displayIndex]->attached = false; + bool analogEncoder + = gConnector[id]->encoder.type == VIDEO_ENCODER_TVDAC + || gConnector[id]->encoder.type == VIDEO_ENCODER_DAC; + bool digitalEncoder + = gConnector[id]->encoder.type == VIDEO_ENCODER_TMDS; + + bool digitalEdid = edid->display.input_type ? true : false; + + if (digitalEdid && analogEncoder) { + // Digital EDID + analog encoder? Lets try a load test + gDisplay[displayIndex]->attached + = encoder_analog_load_detect(id); + } else if (!digitalEdid && digitalEncoder) { + // non-digital EDID + digital encoder? Nope. + gDisplay[displayIndex]->attached = false; + } + + // Else... everything aligns as it should and attached = 1 } } } From e8d6e3fe3b85f88fe9506257b0cbbf5341a3a840 Mon Sep 17 00:00:00 2001 From: Fredrik Holmqvist Date: Sun, 24 Feb 2013 08:45:47 +0100 Subject: [PATCH 007/104] Remove fno-tree-vrp compile flag. My tests hasn't shown any problems with removing it. Let me know if there still are. --- build/jam/BuildSetup | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/build/jam/BuildSetup b/build/jam/BuildSetup index fe3340f53f..4c612b0d9a 100644 --- a/build/jam/BuildSetup +++ b/build/jam/BuildSetup @@ -131,14 +131,12 @@ if $(HAIKU_USE_GCC_PIPE) = 1 { # results in some broken code. # TODO: remove the -fno-strict-aliasing option when all code has been # analyzed/fixed with regard to aliasing. -# TODO: retest/remove the -fno-tree-vrp option as soon as we have updated our -# gcc4 compiler. if $(HAIKU_GCC_VERSION[1]) >= 3 { - HAIKU_GCC_BASE_FLAGS += -fno-strict-aliasing -fno-tree-vrp ; + HAIKU_GCC_BASE_FLAGS += -fno-strict-aliasing ; } if $(HOST_GCC_VERSION[1]) >= 3 { - HOST_GCC_BASE_FLAGS += -fno-strict-aliasing -fno-tree-vrp ; + HOST_GCC_BASE_FLAGS += -fno-strict-aliasing ; } # override gcc 2.95.3's header directory -- strictly necessary only when using From da179153e88c93913ca46b8bc4c80646fa23a00b Mon Sep 17 00:00:00 2001 From: John Scipione Date: Sun, 24 Feb 2013 02:00:51 -0500 Subject: [PATCH 008/104] Small whitespace fix in MenuBar.cpp --- src/kits/interface/MenuBar.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/kits/interface/MenuBar.cpp b/src/kits/interface/MenuBar.cpp index b29f9d5ef5..8c7dc13fda 100644 --- a/src/kits/interface/MenuBar.cpp +++ b/src/kits/interface/MenuBar.cpp @@ -340,9 +340,9 @@ BMenuBar::MouseDown(BPoint where) uint32 buttons; GetMouse(&where, &buttons); - - BWindow* window = Window(); - if (!window->IsActive() || !window->IsFront()) { + + BWindow* window = Window(); + if (!window->IsActive() || !window->IsFront()) { if ((mouse_mode() == B_FOCUS_FOLLOWS_MOUSE) || ((mouse_mode() == B_CLICK_TO_FOCUS_MOUSE) && ((buttons & B_SECONDARY_MOUSE_BUTTON) != 0))) { @@ -500,8 +500,8 @@ BMenuBar::StartMenuBar(int32 menuIndex, bool sticky, bool showMenu, fMenuSem = create_sem(0, "window close sem"); _set_menu_sem_(window, fMenuSem); - fTrackingPID = spawn_thread(_TrackTask, "menu_tracking", B_DISPLAY_PRIORITY, - NULL); + fTrackingPID = spawn_thread(_TrackTask, "menu_tracking", + B_DISPLAY_PRIORITY, NULL); if (fTrackingPID >= 0) { menubar_data data; data.menuBar = this; @@ -699,7 +699,6 @@ BMenuBar::_Track(int32* action, int32 startIndex, bool showMenu) *action = fState; return fChosenItem; - } From 88571c92411f8980452f719c6456bd475d7db5a4 Mon Sep 17 00:00:00 2001 From: John Scipione Date: Sun, 24 Feb 2013 02:18:20 -0500 Subject: [PATCH 009/104] Refactor TExpandoMenuBar::MouseDown() style. No functional change intended. * Check for NULL fields in the beginning and return decreasing the indent level of the rest of the method. * Move some comments to next line indented --- src/apps/deskbar/ExpandoMenuBar.cpp | 116 ++++++++++++++-------------- 1 file changed, 58 insertions(+), 58 deletions(-) diff --git a/src/apps/deskbar/ExpandoMenuBar.cpp b/src/apps/deskbar/ExpandoMenuBar.cpp index 310d5ab9d4..21fbcffb02 100644 --- a/src/apps/deskbar/ExpandoMenuBar.cpp +++ b/src/apps/deskbar/ExpandoMenuBar.cpp @@ -337,66 +337,66 @@ TExpandoMenuBar::MouseDown(BPoint where) BMenuItem* menuItem; TTeamMenuItem* item = TeamItemAtPoint(where, &menuItem); - // check for three finger salute, a.k.a. Vulcan Death Grip - if (message != NULL && item != NULL && !fBarView->Dragging()) { - int32 modifiers = 0; - message->FindInt32("modifiers", &modifiers); - - if ((modifiers & B_COMMAND_KEY) != 0 - && (modifiers & B_CONTROL_KEY) != 0 - && (modifiers & B_SHIFT_KEY) != 0) { - const BList* teams = item->Teams(); - int32 teamCount = teams->CountItems(); - - team_id teamID; - for (int32 team = 0; team < teamCount; team++) { - teamID = (addr_t)teams->ItemAt(team); - kill_team(teamID); - // remove the team immediately from display - RemoveTeam(teamID, false); - } - - return; - } - - // control click - show all/hide all shortcut - if ((modifiers & B_CONTROL_KEY) != 0) { - // show/hide item's teams - BMessage showMessage((modifiers & B_SHIFT_KEY) != 0 - ? kMinimizeTeam : kBringTeamToFront); - showMessage.AddInt32("itemIndex", IndexOf(item)); - Window()->PostMessage(&showMessage, this); - return; - } - - // Check the bounds of the expand Team icon - if (fShowTeamExpander && fVertical) { - BRect expanderRect = item->ExpanderBounds(); - if (expanderRect.Contains(where)) { - // Let the update thread wait... - BAutolock locker(sMonLocker); - - // Toggle the item - item->ToggleExpandState(true); - item->Draw(); - - // Absorb the message. - return; - } - } - - // double-click on an item brings the team to front - int32 clicks; - if (message->FindInt32("clicks", &clicks) == B_OK && clicks > 1 - && item == menuItem && item == fLastClickItem) { - // activate this team - be_roster->ActivateApp((addr_t)item->Teams()->ItemAt(0)); - return; - } - - fLastClickItem = item; + if (message == NULL || item == NULL || fBarView->Dragging()) { + BMenuBar::MouseDown(where); + return; } + int32 modifiers = 0; + message->FindInt32("modifiers", &modifiers); + + // check for three finger salute, a.k.a. Vulcan Death Grip + if ((modifiers & B_COMMAND_KEY) != 0 + && (modifiers & B_CONTROL_KEY) != 0 + && (modifiers & B_SHIFT_KEY) != 0) { + const BList* teams = item->Teams(); + int32 teamCount = teams->CountItems(); + team_id teamID; + for (int32 team = 0; team < teamCount; team++) { + teamID = (addr_t)teams->ItemAt(team); + kill_team(teamID); + RemoveTeam(teamID, false); + // remove the team from display immediately + } + return; + // absorb the message + } + + // control click - show all/hide all shortcut + if ((modifiers & B_CONTROL_KEY) != 0) { + // show/hide item's teams + BMessage showMessage((modifiers & B_SHIFT_KEY) != 0 + ? kMinimizeTeam : kBringTeamToFront); + showMessage.AddInt32("itemIndex", IndexOf(item)); + Window()->PostMessage(&showMessage, this); + return; + // absorb the message + } + + // Check the bounds of the expand Team icon + if (fVertical && fShowTeamExpander) { + if (item->ExpanderBounds().Contains(where)) { + BAutolock locker(sMonLocker); + // let the update thread wait... + item->ToggleExpandState(true); + // toggle the item + item->Draw(); + return; + // absorb the message + } + } + + // double-click on an item brings the team to front + int32 clicks; + if (message->FindInt32("clicks", &clicks) == B_OK && clicks > 1 + && item == menuItem && item == fLastClickItem) { + be_roster->ActivateApp((addr_t)item->Teams()->ItemAt(0)); + // activate this team + return; + // absorb the message + } + + fLastClickItem = item; BMenuBar::MouseDown(where); } From 733be65954f85c0c0cd57d0bec95d8a47f9d1f4a Mon Sep 17 00:00:00 2001 From: John Scipione Date: Sun, 24 Feb 2013 04:30:41 -0500 Subject: [PATCH 010/104] Prevent a deadlock condition in Deskbar. Fixes #8539 If the window is locked by the menu_tracking thread Deskbar will wait on the sMonThread thread to exit forever so we have to kill it to prevent a deadlock. This is a workaround of a bigger problem, which is that fExpando gets created and destroyed on each change which is slow allowing these kinds of bugs to exist. The real solution is to live update fExpando but that is a fair amount of work. --- src/apps/deskbar/ExpandoMenuBar.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/apps/deskbar/ExpandoMenuBar.cpp b/src/apps/deskbar/ExpandoMenuBar.cpp index 21fbcffb02..07509971c0 100644 --- a/src/apps/deskbar/ExpandoMenuBar.cpp +++ b/src/apps/deskbar/ExpandoMenuBar.cpp @@ -195,6 +195,14 @@ TExpandoMenuBar::DetachedFromWindow() if (sMonThread != B_ERROR) { sDoMonitor = false; + if (Window()->IsLocked()) { + // If window is locked by the menu_tracking thread kill it + // to prevent a deadlock. See ticket #8539. + thread_id menu_tracking = find_thread("menu_tracking"); + if (menu_tracking != B_NAME_NOT_FOUND) + kill_thread(menu_tracking); + } + status_t returnCode; wait_for_thread(sMonThread, &returnCode); From 2a5c1f12b9c0452aa1c701e235d0d745285f827a Mon Sep 17 00:00:00 2001 From: John Scipione Date: Mon, 25 Feb 2013 11:57:18 -0500 Subject: [PATCH 011/104] Fix #9469 again in a better way. Pass fTime into the IsHidden() method to check the hidden state from the point of view of fTime which will ignore the hidden state. of the window. Remove the Hide(), Show(), and IsHidden() overrides in TimeView as they are no longer needed. Thanks Stippi and Axel. --- src/apps/deskbar/StatusView.cpp | 7 +++++-- src/apps/deskbar/TimeView.cpp | 22 ---------------------- src/apps/deskbar/TimeView.h | 3 --- 3 files changed, 5 insertions(+), 27 deletions(-) diff --git a/src/apps/deskbar/StatusView.cpp b/src/apps/deskbar/StatusView.cpp index 947773f531..b25c7af420 100644 --- a/src/apps/deskbar/StatusView.cpp +++ b/src/apps/deskbar/StatusView.cpp @@ -433,7 +433,9 @@ TReplicantTray::ShowHideTime() if (fTime == NULL) return; - if (fTime->IsHidden()) + // Check from the point of view of fTime because we need to ignore + // whether or not the parent window is hidden. + if (fTime->IsHidden(fTime)) fTime->Show(); else fTime->Hide(); @@ -441,7 +443,8 @@ TReplicantTray::ShowHideTime() RealignReplicants(); AdjustPlacement(); - bool showClock = !fTime->IsHidden(); + // Check from the point of view of fTime ignoring parent's state. + bool showClock = !fTime->IsHidden(fTime); // Update showClock setting that gets saved to disk on quit ((TBarApp*)be_app)->Settings()->showClock = showClock; diff --git a/src/apps/deskbar/TimeView.cpp b/src/apps/deskbar/TimeView.cpp index 02e7162017..18217ebbe5 100644 --- a/src/apps/deskbar/TimeView.cpp +++ b/src/apps/deskbar/TimeView.cpp @@ -187,17 +187,6 @@ TTimeView::GetPreferredSize(float* width, float* height) } -void -TTimeView::Hide() -{ - // Prevent overflow - if (fShowLevel < INT16_MAX) - ++fShowLevel; - - BView::Hide(); -} - - void TTimeView::MessageReceived(BMessage* message) { @@ -307,17 +296,6 @@ TTimeView::ResizeToPreferred() } -void -TTimeView::Show() -{ - // Prevent underflow - if (fShowLevel > INT16_MIN) - --fShowLevel; - - BView::Show(); -} - - // # pragma mark - Public methods diff --git a/src/apps/deskbar/TimeView.h b/src/apps/deskbar/TimeView.h index 9f28a1ca04..ba823dda06 100644 --- a/src/apps/deskbar/TimeView.h +++ b/src/apps/deskbar/TimeView.h @@ -88,13 +88,10 @@ public: void Draw(BRect update); void FrameMoved(BPoint); void GetPreferredSize(float* width, float* height); - void Hide(); - bool IsHidden() const { return fShowLevel > 0; }; void MessageReceived(BMessage*); void MouseDown(BPoint where); void Pulse(); void ResizeToPreferred(); - void Show(); bool Orientation() const; void SetOrientation(bool o); From b37d5096dccf849583d0ce61c891558687b4ede9 Mon Sep 17 00:00:00 2001 From: John Scipione Date: Mon, 25 Feb 2013 12:06:30 -0500 Subject: [PATCH 012/104] Remove this #include directive too --- src/apps/deskbar/TimeView.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/apps/deskbar/TimeView.cpp b/src/apps/deskbar/TimeView.cpp index 18217ebbe5..8559fe8103 100644 --- a/src/apps/deskbar/TimeView.cpp +++ b/src/apps/deskbar/TimeView.cpp @@ -37,8 +37,6 @@ All rights reserved. #include "TimeView.h" #include -#include - // for INT16_MIN and INT16_MAX #include #include From d06f58081ace6aa75f70167c850ddff722574b1f Mon Sep 17 00:00:00 2001 From: John Scipione Date: Mon, 25 Feb 2013 15:53:55 -0500 Subject: [PATCH 013/104] Revert "Prevent a deadlock condition in Deskbar. Fixes #8539" This reverts commit 733be65954f85c0c0cd57d0bec95d8a47f9d1f4a. It didn't fix the bug, will try again. --- src/apps/deskbar/ExpandoMenuBar.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/apps/deskbar/ExpandoMenuBar.cpp b/src/apps/deskbar/ExpandoMenuBar.cpp index 07509971c0..21fbcffb02 100644 --- a/src/apps/deskbar/ExpandoMenuBar.cpp +++ b/src/apps/deskbar/ExpandoMenuBar.cpp @@ -195,14 +195,6 @@ TExpandoMenuBar::DetachedFromWindow() if (sMonThread != B_ERROR) { sDoMonitor = false; - if (Window()->IsLocked()) { - // If window is locked by the menu_tracking thread kill it - // to prevent a deadlock. See ticket #8539. - thread_id menu_tracking = find_thread("menu_tracking"); - if (menu_tracking != B_NAME_NOT_FOUND) - kill_thread(menu_tracking); - } - status_t returnCode; wait_for_thread(sMonThread, &returnCode); From 9e3038ae8eed496cd7ca5a82c9754b9ec62c1750 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Tue, 26 Feb 2013 22:36:20 -0600 Subject: [PATCH 014/104] radeon_hd: Revert a change from hrev45219 * Causes a regression in proper UNIPHY mode setting. * These encoder setup routines do not get performed by any dpms stuff and are required to put the encoder in the correct state for programming. * Resolves #8913 and maybe others * Thanks Justin for testing! --- src/add-ons/accelerants/radeon_hd/encoder.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/add-ons/accelerants/radeon_hd/encoder.cpp b/src/add-ons/accelerants/radeon_hd/encoder.cpp index 4064d2cb01..e8504df8bc 100644 --- a/src/add-ons/accelerants/radeon_hd/encoder.cpp +++ b/src/add-ons/accelerants/radeon_hd/encoder.cpp @@ -324,9 +324,6 @@ encoder_mode_set(uint8 crtcID) case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: - // already handled by virue of setting DPMS_OFF before - // getting here -#if 0 if ((info.chipsetFlags & CHIP_APU) != 0 || info.dceMajor >= 5) { // Setup DIG encoder @@ -359,7 +356,6 @@ encoder_mode_set(uint8 crtcID) transmitter_dig_setup(connectorIndex, pixelClock, 0, 0, ATOM_TRANSMITTER_ACTION_ENABLE); } -#endif break; case ENCODER_OBJECT_ID_INTERNAL_DDI: case ENCODER_OBJECT_ID_INTERNAL_DVO1: From 49126a0e9b1b7a8a148dab17d0c3aa4eb6e798ed Mon Sep 17 00:00:00 2001 From: Tri-Edge AI Date: Thu, 3 Jan 2013 18:02:21 +0200 Subject: [PATCH 015/104] Added ResourceEdit and modified BColumnListView, BRow and BMenu. Signed-off-by: Matt Madia --- data/artwork/icons/App_ResourceEdit | Bin 0 -> 23980 bytes headers/os/interface/Menu.h | 1 + headers/private/interface/ColumnListView.h | 4 +- src/apps/Jamfile | 2 +- src/apps/resourceedit/Constants.h | 42 ++ src/apps/resourceedit/DefaultTypes.cpp | 101 ++++ src/apps/resourceedit/DefaultTypes.h | 66 +++ src/apps/resourceedit/ImageButton.cpp | 67 +++ src/apps/resourceedit/ImageButton.h | 32 ++ src/apps/resourceedit/Jamfile | 23 + src/apps/resourceedit/MainWindow.cpp | 562 +++++++++++++++++++++ src/apps/resourceedit/MainWindow.h | 85 ++++ src/apps/resourceedit/ResourceEdit.cpp | 121 +++++ src/apps/resourceedit/ResourceEdit.h | 42 ++ src/apps/resourceedit/ResourceEdit.rdef | 136 +++++ src/apps/resourceedit/ResourceListView.cpp | 52 ++ src/apps/resourceedit/ResourceListView.h | 26 + src/apps/resourceedit/ResourceRow.cpp | 141 ++++++ src/apps/resourceedit/ResourceRow.h | 43 ++ src/apps/resourceedit/main.cpp | 17 + src/kits/interface/ColumnListView.cpp | 63 ++- src/kits/interface/Menu.cpp | 15 + 22 files changed, 1638 insertions(+), 3 deletions(-) create mode 100644 data/artwork/icons/App_ResourceEdit create mode 100644 src/apps/resourceedit/Constants.h create mode 100644 src/apps/resourceedit/DefaultTypes.cpp create mode 100644 src/apps/resourceedit/DefaultTypes.h create mode 100644 src/apps/resourceedit/ImageButton.cpp create mode 100644 src/apps/resourceedit/ImageButton.h create mode 100644 src/apps/resourceedit/Jamfile create mode 100644 src/apps/resourceedit/MainWindow.cpp create mode 100644 src/apps/resourceedit/MainWindow.h create mode 100644 src/apps/resourceedit/ResourceEdit.cpp create mode 100644 src/apps/resourceedit/ResourceEdit.h create mode 100644 src/apps/resourceedit/ResourceEdit.rdef create mode 100644 src/apps/resourceedit/ResourceListView.cpp create mode 100644 src/apps/resourceedit/ResourceListView.h create mode 100644 src/apps/resourceedit/ResourceRow.cpp create mode 100644 src/apps/resourceedit/ResourceRow.h create mode 100644 src/apps/resourceedit/main.cpp diff --git a/data/artwork/icons/App_ResourceEdit b/data/artwork/icons/App_ResourceEdit new file mode 100644 index 0000000000000000000000000000000000000000..e35ff651ff8057c2c494a0175648b704d98c68be GIT binary patch literal 23980 zcmeHP3vg7`89qyphlsop6?7|5gGC@j9JH2wfV>P3foh$?Ku8v|VUrEX@*Ksjic}O( zlmTBgN(m@bR9aL-LxF*);Gook;sdMWh}ssbR?FyYzwe%V?kji0O)%iVo|(hR{m$c_ z`+xucpL5TDml31J4;wyeXpTVgA*a%$u9JkwLj4(zHn`OK`9w1@Y}oiw9HUn^qH-*s zXl~#ioG(OQ)HOk!6&F2(=yZi_UzVRJst`TV%FC=?=_>E8W~J_`9>RzDa#rn8u>);Y zJ?|p^gt>aT$=m4F3|ZZTgL5E0s(h3)#JCCL2lM)DRv=MSS?D!k^w==__CxM~%)VKo zr41heoMUH+Gi~^-z?$lK-k34kI2>yWvK;3uL7ewx-mT-M`6UqyB}7G0B$Dta;$@;N z9xY7($qowfZAgffA(6Z|EJPdR@nMlHLb(rEYm~E4zZbc4NbBW~mKq(K4C)(tv~9au z9e33X2p6we?dTYvY2NbAyAFo-w+z(k`P}?3L(jGzY4j|JmzG8f5|KjT(-MjD7sTQf zL{|8`5w;x@_DWbgv}LjqMl!OIJ0n{OQ}__zR>BlM6S$Qy;>>H1-3Z&H;~HVDaUltt z8c!tRB?f0TK_QMnKnsyCfdJn`IT@VAkUQX7AeULWQXK}NVcTPLkQ}KV8_;7&+8z#W zY}9<~^F~c~wDU?0CBkH-rX{Y2Bh#R*)F^xka4R(me+Iaf8sf}Zn2#GZopoHJh7Bu< z@(bg${W%6L2SP#=LRO!mjD02UGJZ{WfUJ zWHmhY)yYtnCpi>dKB{<)D@EI!+i|2>fP z)5t6-_r1tXHQ7r~NsstEuo~o*R?pawj*_4H^|bTlu$T2dZ;Tzl!&6d}Dka5)KV7#S zZmv=>;ItQo(~Y_@_B-HijJ*h)bI20*ZO3amZrBSMn;M%LG58`sbbTzdb)GImNw>&r zmaLZ?T3lj7I!eCk*RxK()_LS>Kjh$*ud~pW$<4yJBaw2pZxe?BcjGGw+>Niz#yEDq zUe$4puNJr5YSv=kw`>}^ZYOrJN&KZb|!DtYQB zlbht}^xPz$3*1fe6M?%){tjatyP@2#U zP30faaZT`KxhzuZFNqcw#v=Y)-AyfeAsHG~-XCIGiLAuLlJ2RW>6W}Tr0O55rO5zZ zPK8bNPbUV{KA7T)oPRKAicLyhGH@tp*nqc&ih;U@v@k%eu$~Q^P7IhYq164P#sI~p zBrm;C(qupy$*~$r_h0vrCIdd~L~RVL0pjI7a384i>V@3gKl}1c#OeMOJ{WaYFQo9B zfLpx~ab|T2;}8>HeeULE7&%!C#h&gg(FZK#=94mvey;pAvd9r&Z{!mEA(? zkF*Ls*}RGAjAVnP*1>y6Nlg82X(!5IEE_yhbx;=(#Ys^x;ZK3?wN5_UvI5DvQY+DS z0?xk9lh12_yHRyJa5t)6Hpa29)UWHfMiuwgTreQDShUo93z71Z3$R*d)s~6thNMo2 ztwC<34DY2Vvv;gSBejydb+l4u?`d7x?L94&)js>2=aI51JUzwkg)+CdMvC2!?0jof zc%z-NB%)=03txk`Ee&1z#6^iy7Yzx&apW4E7D}7Qlnd4dxfuPq=JJpl!XjmdkWY&xTt7!vo2c1+ zhliKka8+0?-7JS7_YR*ipfLPNxVL$j=&d0If2@`!0kw{DPx-?{t_zX@{WaqJIl18v zno#aMd>VlKJlsuhlr<=`QSz+5dwB2Bq2W+gPm_;^btFIa?P=%BahO<Y{!h=Yi% zdf9v3f_89anh!x?Eb8Q7fcrg@mRc^@xjy$xQmww?ZJq2iE2We920NE8!$}l zjNlS?PDn*?eTW^YU^lnDh*p~uO9gzdOs_>tL0Jq;znP10lyBi>w07?U?t;WL2C#RS1~ z3mvxuCkt6P^RnVp3n{I0Z1Lzvb-W;!Us0h&+lDC-aLF+)66N`&71QG7CHaYHyi`;b zwU~bMku8Cp?YmWuKlE-O{+GXfy}Z*G)y)Q9Ib?Lt-2rs1To}#^qMS1Nj$9m!P#spM zzDa$S`cGZ4SA+O&!YW6weiJ?B^GkPIZ|mPIrGaqviaSv)51MG-|yiz4Mw#L4Z` z@J;ZjTs0WPt8%GR6*uKlrz%$EdK6>(F-Nx7tbkj#iUh;@dX(5S21CCdLMJc!wE<%_ zhJI1k_~Pc&FNK$&&P~7gg65`Q3xK=n*9sl4r+!uT7_qF!h<{LzY$^F`rnhwb%Ai)6 z4C(r{HT7PqB(=rVtz_WtK1T;>dIfnyi@fU9614V04^5gPQ)W*Q;L_D;F;K=N#bo!Q zd@&=g=@0qV7eGUEmW}hM={xbDUNv3C5Zz{^Vu(&nzrZ?EN9<3|HuYIE(~oBK-0oBz z4y?4GrEkWhZGq3j*BltN_@2OqM3dWsd5=}kSlZKQSkj~A>8e7Ip_{Op}o)e|?*yKU3Loz$tVpR^7IQ673Y9@KSe^Si0k zCH^me1f3e=QKz=oL#I?M)=j6lUK4lf6t~92HJ!4?P^C)!x41Z?QXW+*IfW$Kj> z+nV2UO1+U<^s2w^ufBdNvr~s27>68n?W#o6P}`=Vy_&m0A4fW(F-#l1{yP_-Hcq-O-fNE2(r1IzhYM z<8J-6M%=CQc(&GVUE5kAny+uI{=ULgsm$SQoren7pSPgpo{bBu%XhTjwyJ7t^{lxU zPk!cy?Sbq6Id1*eiMy+zEy1<({6Umc_TQSVFM+9ly`^ofSXvHeBlooqTzJ#ihAf5r zHqXl;njh_;g`N)4yd2INhp<#3BbF!i2oZ_pKiQ)+bH2LPfAN0O)cVX(TAf-icFpLz zYlaqjfG#jbqI}$Ka5<>>0gw4OjOYxsa8(A2V!XkxCvq98veBUB~% zbKEMD!I6-x7h;BD>J%)6#H5I!Fr?t>CPoR4#E@VsF;p2YrzF{jD58pjEc1!Q70*|uS|O(OgBf@ zMt59U!cJM2G(CS|m=bljkHM`j!6mX2S0yLq}d(|EdeX*}9_Y4F^-J)PRI(y3}5kI%sHeP&~q z+1RCfO*&EUukl*LnoKMx7fi(}BB*pRb{A_+lM5Y2mVB&|<7HTxUrO|4W3E$I9vZdP-d|SmEYGGZq@I zd4}!pe|*&7|Lke_Io#>Hz-T1!SJymmrV7ax&DUHI~MUDezs!poToTQB!Nvma!V+N1BaC4ZWv94S8~- zCif&-&FT9B$_3M)hCFH1XoTq>{~KE}c{F_j4Q8pwg?|;M-B=4hwKd(s-wSna3x5%C nw}pR38hnwCn+rbxlNCOi#tQGH{nvYqO3C(b)(%Sh0m%OW090~% literal 0 HcmV?d00001 diff --git a/headers/os/interface/Menu.h b/headers/os/interface/Menu.h index e5ab621649..60ba113883 100644 --- a/headers/os/interface/Menu.h +++ b/headers/os/interface/Menu.h @@ -122,6 +122,7 @@ public: float MaxContentWidth() const; BMenuItem* FindMarked(); + int32 FindMarkedIndex(); BMenu* Supermenu() const; BMenuItem* Superitem() const; diff --git a/headers/private/interface/ColumnListView.h b/headers/private/interface/ColumnListView.h index 2acbbdbb6c..027154b98b 100644 --- a/headers/private/interface/ColumnListView.h +++ b/headers/private/interface/ColumnListView.h @@ -133,6 +133,7 @@ public: float Height() const; bool IsExpanded() const; + bool IsSelected() const; private: // Blows up into the debugger if the validation fails. @@ -326,8 +327,9 @@ public: // Does not delete row or children at this time. // todo: Make delete row and children void RemoveRow(BRow* row); - void UpdateRow(BRow* row); + bool SwapRows(int32 index1, int32 index2, BRow* + parentRow1 = NULL, BRow* parentRow2 = NULL); void Clear(); // Appearance (DEPRECATED) diff --git a/src/apps/Jamfile b/src/apps/Jamfile index 7cd5efc724..6c3a8fc0ea 100644 --- a/src/apps/Jamfile +++ b/src/apps/Jamfile @@ -48,7 +48,7 @@ HaikuSubInclude powerstatus ; HaikuSubInclude processcontroller ; HaikuSubInclude pulse ; HaikuSubInclude remotedesktop ; -HaikuSubInclude resedit ; +HaikuSubInclude resourceedit ; HaikuSubInclude screenshot ; HaikuSubInclude serialconnect ; HaikuSubInclude showimage ; diff --git a/src/apps/resourceedit/Constants.h b/src/apps/resourceedit/Constants.h new file mode 100644 index 0000000000..4a9766e7d7 --- /dev/null +++ b/src/apps/resourceedit/Constants.h @@ -0,0 +1,42 @@ +/* + * Copyright 2012-2013 Tri-Edge AI + * All rights reserved. Distributed under the terms of the MIT license. + */ +#ifndef CONSTANTS_H +#define CONSTANTS_H + + +#define MSG_NEW 'm000' +#define MSG_OPEN 'm001' +#define MSG_OPEN_DONE 'm002' +#define MSG_CLOSE 'm003' +#define MSG_SAVE 'm004' +#define MSG_SAVEAS 'm005' +#define MSG_SAVEAS_DONE 'm006' +#define MSG_SAVEALL 'm007' +#define MSG_MERGEWITH 'm008' +#define MSG_QUIT 'm009' + +#define MSG_UNDO 'm010' +#define MSG_REDO 'm011' +#define MSG_CUT 'm012' +#define MSG_COPY 'm013' +#define MSG_PASTE 'm014' +#define MSG_CLEAR 'm015' +#define MSG_SELECTALL 'm016' + +#define MSG_ADD 'm020' +#define MSG_REMOVE 'm021' +#define MSG_MOVEUP 'm022' +#define MSG_MOVEDOWN 'm023' + +#define MSG_SELECTION 'm030' + + +// TODO: Remove prior to release. +#define DEBUG 1 +#include +// --- --- + + +#endif diff --git a/src/apps/resourceedit/DefaultTypes.cpp b/src/apps/resourceedit/DefaultTypes.cpp new file mode 100644 index 0000000000..9f7de5deae --- /dev/null +++ b/src/apps/resourceedit/DefaultTypes.cpp @@ -0,0 +1,101 @@ +/* + * Copyright 2012-2013 Tri-Edge AI + * All rights reserved. Distributed under the terms of the MIT license. + */ + + +#include "DefaultTypes.h" + +#include + + +BString +toStringBOOL(const void* data) +{ + if (*(bool*)data) + return "✔ true"; + else + return "✖ false"; +} + + +BString +toStringBYTE(const void* data) +{ + return (BString() << *(int8*)data); +} + + +BString +toStringSHRT(const void* data) +{ + return (BString() << *(int16*)data); +} + + +BString +toStringLONG(const void* data) +{ + return (BString() << *(int32*)data); +} + + +BString +toStringLLNG(const void* data) +{ + return (BString() << *(int64*)data); +} + + +BString +toStringUBYT(const void* data) +{ + return (BString() << *(uint8*)data); +} + + +BString +toStringUSHT(const void* data) +{ + return (BString() << *(uint16*)data); +} + + +BString +toStringULNG(const void* data) +{ + return (BString() << *(uint32*)data); +} + + +BString +toStringULLG(const void* data) +{ + return (BString() << *(uint64*)data); +} + + +BString +toStringRAWT(const void* data) +{ + return "[Raw Data]"; +} + + +int32 +FindTypeCodeIndex(type_code code) +{ + for (int32 i = 0; kDefaultTypes[i].type != NULL; i++) + if (kDefaultTypes[i].typeCode == code) + return i; + + return -1; +} + + +void +TypeCodeToString(type_code code, char* str) +{ + *(type_code*)str = B_HOST_TO_BENDIAN_INT32(code); + str[4] = '\0'; +} diff --git a/src/apps/resourceedit/DefaultTypes.h b/src/apps/resourceedit/DefaultTypes.h new file mode 100644 index 0000000000..42ebf87d77 --- /dev/null +++ b/src/apps/resourceedit/DefaultTypes.h @@ -0,0 +1,66 @@ +/* + * Copyright 2012-2013 Tri-Edge AI + * All rights reserved. Distributed under the terms of the MIT license. + */ +#ifndef DEFAULT_TYPES_H +#define DEFAULT_TYPES_H + + +#include + + +struct ResourceDataType { + const char* type; + type_code typeCode; + uint32 size; + BString (*toString)(const void*); +}; + +// TODO: Rework design of this. This one sucks. + +BString toStringBOOL(const void* data); +BString toStringBYTE(const void* data); +BString toStringSHRT(const void* data); +BString toStringLONG(const void* data); +BString toStringLLNG(const void* data); +BString toStringUBYT(const void* data); +BString toStringUSHT(const void* data); +BString toStringULNG(const void* data); +BString toStringULLG(const void* data); +BString toStringRAWT(const void* data); + +char * const kDefaultData[] = { + 0, 0, 0, 0, 0, 0, 0, 0 +}; + +#define LINE "", 0, ~0 +#define END NULL, 0, 0 + +const ResourceDataType kDefaultTypes[] = { + { "bool", 'BOOL', 1, toStringBOOL }, + { LINE }, + { "int8", 'BYTE', 1, toStringBYTE }, + { "int16", 'SHRT', 2, toStringSHRT }, + { "int32", 'LONG', 4, toStringLONG }, + { "int64", 'LLNG', 8, toStringLLNG }, + { LINE }, + { "uint8", 'UBYT', 1, toStringUBYT }, + { "uint16", 'USHT', 2, toStringUSHT }, + { "uint32", 'ULNG', 4, toStringULNG }, + { "uint64", 'ULLG', 8, toStringULLG }, + { LINE }, + { "raw", 'RAWT', 0, toStringRAWT }, + { END } +}; + +const int32 kDefaultTypeSelected = 4; + // int32 + +#undef LINE +#undef END + +int32 FindTypeCodeIndex(type_code code); +void TypeCodeToString(type_code code, char* str); + + +#endif diff --git a/src/apps/resourceedit/ImageButton.cpp b/src/apps/resourceedit/ImageButton.cpp new file mode 100644 index 0000000000..7b0b8dd995 --- /dev/null +++ b/src/apps/resourceedit/ImageButton.cpp @@ -0,0 +1,67 @@ +/* + * Copyright 2012-2013 Tri-Edge AI + * All rights reserved. Distributed under the terms of the MIT license. + */ + + +#include "ImageButton.h" + +#include + + +ImageButton::ImageButton(BRect frame, const char* name, BBitmap* image, + BMessage* message, uint32 resizingMode = B_FOLLOW_NONE) + : + BButton(frame, name, "", message, resizingMode) +{ + fImage = image; + + fDrawPoint.x = ((frame.RightTop().x - frame.LeftTop().x) + - (image->Bounds().RightBottom().x + 1)) / 2; + + fDrawPoint.y = ((frame.LeftBottom().y - frame.LeftTop().y) + - (image->Bounds().RightBottom().y + 1)) / 2; + + fInnerBounds = Bounds(); + fInnerBounds.InsetBy(3, 3); + + SetDrawingMode(B_OP_ALPHA); +} + + +ImageButton::~ImageButton() +{ + +} + + +void +ImageButton::Draw(BRect updateRect) +{ + BButton::Draw(updateRect); + DrawBitmap(fImage, fDrawPoint); + + if (!IsEnabled()) { + rgb_color tempColor = HighColor(); + SetHighColor(255, 255, 255, 155); + FillRect(fInnerBounds, B_SOLID_HIGH); + SetHighColor(tempColor); + } +} + + +void +ImageButton::ResizeTo(float width, float height) +{ + BButton::ResizeTo(width, height); + fInnerBounds = Bounds(); + fInnerBounds.InsetBy(3, 3); +} + + +void +ImageButton::SetBitmap(BBitmap* image) +{ + fImage = image; + Invalidate(); +} diff --git a/src/apps/resourceedit/ImageButton.h b/src/apps/resourceedit/ImageButton.h new file mode 100644 index 0000000000..e0c3de8c89 --- /dev/null +++ b/src/apps/resourceedit/ImageButton.h @@ -0,0 +1,32 @@ +/* + * Copyright 2012-2013 Tri-Edge AI + * All rights reserved. Distributed under the terms of the MIT license. + */ +#ifndef IMAGE_BUTTON_H +#define IMAGE_BUTTON_H + + +#include + + +class ImageButton : public BButton +{ +public: + ImageButton(BRect frame, const char* name, BBitmap* image, + BMessage* message, uint32 resizingMode); + ~ImageButton(); + + void Draw(BRect updateRect); + void ResizeTo(float width, float height); + + void SetBitmap(BBitmap* image); + +private: + BBitmap* fImage; + BPoint fDrawPoint; + BRect fInnerBounds; + +}; + + +#endif diff --git a/src/apps/resourceedit/Jamfile b/src/apps/resourceedit/Jamfile new file mode 100644 index 0000000000..9507e9ad1b --- /dev/null +++ b/src/apps/resourceedit/Jamfile @@ -0,0 +1,23 @@ +SubDir HAIKU_TOP src apps resourceedit ; + +UsePrivateHeaders interface shared ; + +Application ResourceEdit + : + DefaultTypes.cpp + ImageButton.cpp + MainWindow.cpp + ResourceEdit.cpp + ResourceListView.cpp + ResourceRow.cpp + main.cpp + : + be + tracker + translation + libcolumnlistview.a + $(TARGET_LIBSTDC++) + + : + ResourceEdit.rdef +; diff --git a/src/apps/resourceedit/MainWindow.cpp b/src/apps/resourceedit/MainWindow.cpp new file mode 100644 index 0000000000..d6413e3ea9 --- /dev/null +++ b/src/apps/resourceedit/MainWindow.cpp @@ -0,0 +1,562 @@ +/* + * Copyright 2012-2013 Tri-Edge AI + * All rights reserved. Distributed under the terms of the MIT license. + */ + + +#include "MainWindow.h" + +#include "Constants.h" +#include "ImageButton.h" +#include "ResourceListView.h" +#include "ResourceRow.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +using namespace std; + + +MainWindow::MainWindow(BRect frame, BEntry* assocEntry) + : + BWindow(frame, NULL, B_DOCUMENT_WINDOW, 0) +{ + fAssocEntry = assocEntry; + + fSavePanel = NULL; + + fMenuBar = new BMenuBar(BRect(0, 0, 600, 1), "fMenuBar"); + + fFileMenu = new BMenu("File", B_ITEMS_IN_COLUMN); + fNewItem = new BMenuItem("New", new BMessage(MSG_NEW), 'N'); + fOpenItem = new BMenuItem("Open", new BMessage(MSG_OPEN), 'O'); + fCloseItem = new BMenuItem("Close", new BMessage(MSG_CLOSE), 'W'); + fSaveItem = new BMenuItem("Save", new BMessage(MSG_SAVE), 'S'); + fSaveAsItem = new BMenuItem("Save As" B_UTF8_ELLIPSIS, new + BMessage(MSG_SAVEAS)); + fSaveAllItem = new BMenuItem("Save All", new BMessage(MSG_SAVEALL), 'S', + B_SHIFT_KEY); + fMergeWithItem = new BMenuItem("Merge With" B_UTF8_ELLIPSIS, + new BMessage(MSG_MERGEWITH), 'M'); + fQuitItem = new BMenuItem("Quit", new BMessage(MSG_QUIT), 'Q'); + + fEditMenu = new BMenu("Edit", B_ITEMS_IN_COLUMN); + fUndoItem = new BMenuItem("Undo", new BMessage(MSG_UNDO), 'Z'); + fRedoItem = new BMenuItem("Redo", new BMessage(MSG_REDO), 'Y'); + fCutItem = new BMenuItem("Cut", new BMessage(MSG_CUT), 'X'); + fCopyItem = new BMenuItem("Copy", new BMessage(MSG_COPY), 'C'); + fPasteItem = new BMenuItem("Paste", new BMessage(MSG_PASTE), 'V'); + fClearItem = new BMenuItem("Clear", new BMessage(MSG_CLEAR)); + fSelectAllItem = new BMenuItem("Select All", + new BMessage(MSG_SELECTALL), 'A'); + + fHelpMenu = new BMenu("Help", B_ITEMS_IN_COLUMN); + + fResourceIDText = new BTextControl(BRect(0, 0, 47, 23).OffsetBySelf(8, 24), + "fResourceIDText", NULL, "0", NULL); + fResourceTypePopUp = new BPopUpMenu("(Type)"); + fResourceTypeMenu = new BMenuField(BRect(0, 0, 1, 1).OffsetBySelf(60, 24), + "fResourceTypeMenu", NULL, fResourceTypePopUp); + + for (int32 i = 0; kDefaultTypes[i].type != NULL; i++) { + if (kDefaultTypes[i].size == ~(uint32)0) + fResourceTypePopUp->AddSeparatorItem(); + else + fResourceTypePopUp->AddItem( + new BMenuItem(kDefaultTypes[i].type, NULL)); + } + + fResourceTypePopUp->ItemAt(kDefaultTypeSelected)->SetMarked(true); + + fToolbarView = new BView(BRect(0, 0, 600, 51), "fToolbarView", + B_FOLLOW_LEFT_RIGHT, 0); + + fToolbarView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + + BRect toolRect = BRect(0, 0, 23, 23).OffsetBySelf(8, 24); + + fAddButton = new ImageButton(toolRect.OffsetBySelf(200, 0), + "fAddButton", BTranslationUtils::GetBitmap('PNG ', "add.png"), + new BMessage(MSG_ADD), B_FOLLOW_NONE); + fAddButton->ResizeTo(23, 23); + + fRemoveButton = new ImageButton(toolRect.OffsetBySelf(30, 0), + "fRemoveButton", BTranslationUtils::GetBitmap('PNG ', "remove.png"), + new BMessage(MSG_REMOVE), B_FOLLOW_NONE); + fRemoveButton->ResizeTo(23, 23); + fRemoveButton->SetEnabled(false); + + fMoveUpButton = new ImageButton(toolRect.OffsetBySelf(30, 0), + "fMoveUpButton", BTranslationUtils::GetBitmap('PNG ', "moveup.png"), + new BMessage(MSG_MOVEUP), B_FOLLOW_NONE); + fMoveUpButton->ResizeTo(23, 23); + fMoveUpButton->SetEnabled(false); + + fMoveDownButton = new ImageButton(toolRect.OffsetBySelf(30, 0), + "fMoveDownButton", BTranslationUtils::GetBitmap('PNG ', "movedown.png"), + new BMessage(MSG_MOVEDOWN), B_FOLLOW_NONE); + fMoveDownButton->ResizeTo(23, 23); + fMoveDownButton->SetEnabled(false); + + BRect listRect = Bounds(); + listRect.SetLeftTop(BPoint(0, 52)); + listRect.InsetBy(-1, -1); + + fResourceList = new ResourceListView(listRect, "fResourceList", + B_FOLLOW_ALL, 0); + + fResourceList->AddColumn(new BIntegerColumn("ID", 48, 1, 999, + B_ALIGN_RIGHT), 0); + fResourceList->AddColumn(new BStringColumn("Name", 156, 1, 999, + B_TRUNCATE_END, B_ALIGN_LEFT), 1); + fResourceList->AddColumn(new BStringColumn("Type", 56, 1, 999, + B_TRUNCATE_END, B_ALIGN_CENTER), 2); + fResourceList->AddColumn(new BStringColumn("Code", 56, 1, 999, + B_TRUNCATE_END, B_ALIGN_CENTER), 3); + fResourceList->AddColumn(new BStringColumn("Data", 156, 1, 999, + B_TRUNCATE_END, B_ALIGN_LEFT), 4); + fResourceList->AddColumn(new BSizeColumn("Size", 74, 1, 999, + B_ALIGN_RIGHT), 5); + + fResourceList->SetLatchWidth(0); + + fResourceList->SetTarget(this); + fResourceList->SetSelectionMessage(new BMessage(MSG_SELECTION)); + + AddChild(fMenuBar); + + fMenuBar->AddItem(fFileMenu); + fFileMenu->AddItem(fNewItem); + fFileMenu->AddItem(fOpenItem); + fFileMenu->AddItem(fCloseItem); + fFileMenu->AddSeparatorItem(); + fFileMenu->AddItem(fSaveItem); + fFileMenu->AddItem(fSaveAsItem); + fFileMenu->AddItem(fSaveAllItem); + fFileMenu->AddItem(fMergeWithItem); + fFileMenu->AddSeparatorItem(); + fFileMenu->AddItem(fQuitItem); + + fMenuBar->AddItem(fEditMenu); + fEditMenu->AddItem(fUndoItem); + fEditMenu->AddItem(fRedoItem); + fEditMenu->AddSeparatorItem(); + fEditMenu->AddItem(fCutItem); + fEditMenu->AddItem(fCopyItem); + fEditMenu->AddItem(fPasteItem); + fEditMenu->AddItem(fClearItem); + fEditMenu->AddSeparatorItem(); + fEditMenu->AddItem(fSelectAllItem); + + fMenuBar->AddItem(fHelpMenu); + + fToolbarView->AddChild(fResourceIDText); + fToolbarView->AddChild(fResourceTypeMenu); + + fToolbarView->AddChild(fAddButton); + fToolbarView->AddChild(fRemoveButton); + fToolbarView->AddChild(fMoveUpButton); + fToolbarView->AddChild(fMoveDownButton); + + AddChild(fToolbarView); + + AddChild(fResourceList); + + if (assocEntry != NULL) { + _SetTitleFromEntry(); + _Load(); + } else { + SetTitle("ResourceEdit | " B_UTF8_ELLIPSIS); + } +} + + +MainWindow::~MainWindow() +{ + +} + + +bool +MainWindow::QuitRequested() +{ + // TODO: Check if file is saved. + + BMessage* msg = new BMessage(MSG_CLOSE); + msg->AddPointer("window", (void*)this); + be_app->PostMessage(msg); + return true; +} + + +void +MainWindow::SelectionChanged() +{ + if (fResourceList->CurrentSelection(NULL) == NULL) { + fMoveUpButton->SetEnabled(false); + fMoveDownButton->SetEnabled(false); + fRemoveButton->SetEnabled(false); + } else { + fRemoveButton->SetEnabled(true); + fMoveUpButton->SetEnabled(!fResourceList->RowAt(0)->IsSelected()); + fMoveDownButton->SetEnabled(!fResourceList->RowAt( + fResourceList->CountRows() - 1)->IsSelected()); + } +} + + +void +MainWindow::MessageReceived(BMessage* msg) +{ + switch (msg->what) { + case MSG_NEW: + be_app->PostMessage(MSG_NEW); + break; + + case MSG_OPEN: + be_app->PostMessage(MSG_OPEN); + break; + + case MSG_CLOSE: + PostMessage(B_QUIT_REQUESTED); + break; + + case MSG_SAVE: + _Save(); + break; + + case MSG_SAVEAS: + _SaveAs(); + break; + + case MSG_SAVEAS_DONE: + { + entry_ref ref; + const char* leaf; + + if (msg->FindRef("directory", &ref) != B_OK) + break; + + if (msg->FindString("name", &leaf) != B_OK) + break; + + BDirectory dir(&ref); + _Save(new BEntry(&dir, leaf)); + + break; + } + case MSG_SAVEALL: + be_app->PostMessage(MSG_SAVEALL); + break; + + case MSG_MERGEWITH: + PRINT(("[MSG_MERGEWITH]: Not yet implemented.")); + // TODO: Implement. + // "Merge from..." might be a better idea actually. + break; + + case MSG_QUIT: + be_app->PostMessage(B_QUIT_REQUESTED); + break; + + case MSG_UNDO: + // TODO: Implement. + PRINT(("[MSG_UNDO]: Not yet implemented.")); + break; + + case MSG_REDO: + // TODO: Implement. + PRINT(("[MSG_REDO]: Not yet implemented.")); + break; + + case MSG_CUT: + // TODO: Implement. + PRINT(("[MSG_CUT]: Not yet implemented.")); + break; + + case MSG_COPY: + // TODO: Implement. + PRINT(("[MSG_COPY]: Not yet implemented.")); + break; + + case MSG_PASTE: + // TODO: Implement. + PRINT(("[MSG_PASTE]: Not yet implemented.")); + break; + + case MSG_CLEAR: + fResourceList->Clear(); + SelectionChanged(); + break; + + case MSG_SELECTALL: + { + for (int32 i = 0; i < fResourceList->CountRows(); i++) + fResourceList->AddToSelection(fResourceList->RowAt(i)); + + SelectionChanged(); + break; + } + case MSG_ADD: + { + // Thank you, François Claus :D Merry Christmas! + + int32 ix = fResourceTypePopUp->FindMarkedIndex(); + + if (ix != -1) { + ResourceRow* row = new ResourceRow(); + row->SetResourceID(_NextResourceID()); + row->SetResourceType(kDefaultTypes[ix].type); + row->SetResourceTypeCode(kDefaultTypes[ix].typeCode); + row->SetResourceRawData(kDefaultData); + row->SetResourceSize(kDefaultTypes[ix].size); + fResourceList->AddRow(row); + } + + break; + } + case MSG_REMOVE: + { + for (int i = 0; i < fResourceList->CountRows(); i++) { + BRow* row = fResourceList->RowAt(i); + + if (row->IsSelected()) { + fResourceList->RemoveRow(row); + i--; + } + } + + break; + } + case MSG_MOVEUP: + { + for (int i = 1; i < fResourceList->CountRows(); i++) { + BRow* row = fResourceList->RowAt(i); + + if (row->IsSelected()) + fResourceList->SwapRows(i, i - 1); + + } + + fResourceList->ClearSortColumns(); + SelectionChanged(); + break; + } + case MSG_MOVEDOWN: + { + for (int i = fResourceList->CountRows() - 1 - 1; i >= 0; i--) { + BRow* row = fResourceList->RowAt(i); + + if (row->IsSelected()) + fResourceList->SwapRows(i, i + 1); + } + + fResourceList->ClearSortColumns(); + SelectionChanged(); + break; + } + case MSG_SELECTION: + SelectionChanged(); + break; + + default: + BWindow::MessageReceived(msg); + } +} + + +void +MainWindow::_SetTitleFromEntry() +{ + char nameBuffer[B_FILE_NAME_LENGTH]; + + fAssocEntry->GetName(nameBuffer); + + BString title; + title << "ResourceEdit | "; + title << nameBuffer; + SetTitle(title); +} + + +void +MainWindow::_SaveAs() +{ + if (fSavePanel == NULL) + fSavePanel = new BFilePanel(B_SAVE_PANEL, new BMessenger(this), NULL, + B_FILE_NODE, false, new BMessage(MSG_SAVEAS_DONE)); + + fSavePanel->Rewind(); + fSavePanel->Show(); +} + + +void +MainWindow::_Save(BEntry* entry) +{ + if (entry == NULL) { + if (fAssocEntry == NULL) { + _SaveAs(); + return; + } else + entry = fAssocEntry; + } else { + if (fAssocEntry == NULL) { + fAssocEntry = entry; + _SetTitleFromEntry(); + } + } + + /*BPath path; + entry->GetPath(&path); + + // I wouldn't use std:: if BFile had cooler stuff. + // Not very comfortable here. + + fstream out(path.Path(), ios::out); + + time_t timeNow = time(0); + + + out << "/-" << endl; + out << " - This file is auto-generated by Haiku ResourceEdit." << endl; + out << " - Time: " << ctime((const time_t*)&timeNow); + out << " -\" << endl; + + for (int32 i = 0; i < fResourceList->CountRows(); i++) { + ResourceRow* row = (ResourceRow*)fResourceList->RowAt(i); + + out << endl; + out << "resource"; + + if (true) { + // TODO: Implement no-ID cases. + + out << "(" << row->ResourceID(); + + if (row->ResourceName()[0] != '\0') { + out << ", \"" << row->ResourceName() << "\"" << endl; + } + + out << ") "; + } + + if (row->ResourceTypeCode()[0] != '\0') + out << "#\'" << row->ResourceTypeCode() << "\' "; + + if (strcmp(row->ResourceType(), "raw") != 0) + out << row->ResourceType() << ' ' << row->ResourceData(); + else { + // TODO: Implement hexdump and import. + out << "array {" << endl; + out << "\t\"Not yet implemented.\"" << endl; + out << "}"; + } + + out << endl; + } + + out.close();*/ + + // Commented out whole output section. Switching to .rsrc files to + // close Part 1 of GCI task. + + // TODO: Implement exporting to .rdef and/or other formats. + + + BFile* file = new BFile(entry, B_READ_WRITE | B_CREATE_FILE); + BResources output(file, true); + delete file; + + for (int32 i = 0; i < fResourceList->CountRows(); i++) { + ResourceRow* row = (ResourceRow*)fResourceList->RowAt(i); + output.AddResource(row->ResourceTypeCode(), row->ResourceID(), + row->ResourceRawData(), row->ResourceSize(), row->ResourceName()); + } + + output.Sync(); +} + + +void +MainWindow::_Load() +{ + /*BPath path; + struct stat st; + + fAssocEntry->GetPath(&path); + fAssocEntry->GetStat(&st); + + int fd = open(path.Path(), 0); + const char* in = (const char*)mmap(NULL, st.st_size, PROT_READ, + MAP_SHARED, fd, 0); + + // TODO: Fix stucking bug. + // TODO: Parse data. + + for (int32 i = 0; i < st.st_size - 1; i++) { + //... + }*/ + + // Commented out input section. Same reason as above. + + // TODO: Implement importing from .rdef and/or other formats. + + BFile* file = new BFile(fAssocEntry, B_READ_ONLY); + BResources input(file); + delete file; + + type_code code; + int32 id; + const char* name; + size_t size; + + for (int32 i = 0; input.GetResourceInfo(i, &code, &id, &name, &size); i++) { + ResourceRow* row = new ResourceRow(); + row->SetResourceID(id); + row->SetResourceName(name); + row->SetResourceSize(size); + row->SetResourceTypeCode(code); + row->SetResourceRawData(input.LoadResource(code, id, &size)); + fResourceList->AddRow(row); + } +} + + +int32 +MainWindow::_NextResourceID() +{ + int32 currentID = atoi(fResourceIDText->Text()); + int32 nextID = currentID + 1; + BString text; + + // Should I check if the ID is already present in the list? + // Hmmm... + + text << nextID; + fResourceIDText->SetText(text); + + return currentID; +} diff --git a/src/apps/resourceedit/MainWindow.h b/src/apps/resourceedit/MainWindow.h new file mode 100644 index 0000000000..bc1523fa35 --- /dev/null +++ b/src/apps/resourceedit/MainWindow.h @@ -0,0 +1,85 @@ +/* + * Copyright 2012-2013 Tri-Edge AI + * All rights reserved. Distributed under the terms of the MIT license. + */ +#ifndef MAIN_WINDOW_H +#define MAIN_WINDOW_H + + +#include + + +class ImageButton; + +class BColumnListView; +class BEntry; +class BFilePanel; +class BMenu; +class BMenuBar; +class BMenuField; +class BMenuItem; +class BMessage; +class BPopUpMenu; +class BTextControl; + + +class MainWindow : public BWindow { +public: + MainWindow(BRect frame, BEntry* entry); + ~MainWindow(); + + bool QuitRequested(); + void MessageReceived(BMessage* msg); + void SelectionChanged(); + +private: + BEntry* fAssocEntry; + + BMenuBar* fMenuBar; + + BMenu* fFileMenu; + BMenuItem* fNewItem; + BMenuItem* fOpenItem; + BMenuItem* fCloseItem; + BMenuItem* fSaveItem; + BMenuItem* fSaveAsItem; + BMenuItem* fSaveAllItem; + BMenuItem* fMergeWithItem; + BMenuItem* fQuitItem; + + BMenu* fEditMenu; + BMenuItem* fUndoItem; + BMenuItem* fRedoItem; + BMenuItem* fCutItem; + BMenuItem* fCopyItem; + BMenuItem* fPasteItem; + BMenuItem* fClearItem; + BMenuItem* fSelectAllItem; + + BMenu* fHelpMenu; + + BTextControl* fResourceIDText; + BPopUpMenu* fResourceTypePopUp; + BMenuField* fResourceTypeMenu; + + BView* fToolbarView; + ImageButton* fAddButton; + ImageButton* fRemoveButton; + ImageButton* fMoveUpButton; + ImageButton* fMoveDownButton; + + BColumnListView* fResourceList; + + BFilePanel* fSavePanel; + + void _SetTitleFromEntry(); + void _SaveAs(); + void _Save(BEntry* entry = NULL); + void _Load(); + + int32 _NextResourceID(); + +}; + + +#endif diff --git a/src/apps/resourceedit/ResourceEdit.cpp b/src/apps/resourceedit/ResourceEdit.cpp new file mode 100644 index 0000000000..2ff1a577a4 --- /dev/null +++ b/src/apps/resourceedit/ResourceEdit.cpp @@ -0,0 +1,121 @@ +/* + * Copyright 2012-2013 Tri-Edge AI + * All rights reserved. Distributed under the terms of the MIT license. + */ + + +#include "ResourceEdit.h" + +#include "AboutWindow.h" +#include "Constants.h" +#include "MainWindow.h" + +#include +#include + + +ResourceEdit::ResourceEdit() + : + BApplication("application/x-vnd.Haiku-ResourceEdit") +{ + fCascade = BRect(100, 100, 700, 400); + fCascadeCount = 0; + + fOpenPanel = new BFilePanel(B_OPEN_PANEL, &be_app_messenger, NULL, 0, true, + new BMessage(MSG_OPEN_DONE)); +} + + +ResourceEdit::~ResourceEdit() +{ + +} + + +void +ResourceEdit::MessageReceived(BMessage* msg) +{ + switch (msg->what) { + case MSG_NEW: + _CreateWindow(NULL); + break; + + case MSG_OPEN: + fOpenPanel->Show(); + break; + + case MSG_OPEN_DONE: + { + entry_ref ref; + + while (fOpenPanel->GetNextSelectedRef(&ref) == B_OK) + _CreateWindow(new BEntry(&ref)); + + fOpenPanel->Rewind(); + + break; + } + case MSG_CLOSE: + { + MainWindow* window; + msg->FindPointer("window", (void**)&window); + fWindowList.RemoveItem(window); + + if (fWindowList.CountItems() == 0) + Quit(); + + break; + } + case MSG_SAVEALL: + { + for (int32 i = 0; i < fWindowList.CountItems(); i++) + ((MainWindow*)fWindowList.ItemAt(i))->PostMessage(MSG_SAVE); + + break; + } + default: + BApplication::MessageReceived(msg); + } +} + + +void +ResourceEdit::ArgvReceived(int32 argc, char* argv[]) +{ + for (int32 i = 1; i < argc; i++) + _CreateWindow(new BEntry(argv[i])); +} + + +void +ResourceEdit::ReadyToRun() +{ + if (fWindowList.CountItems() <= 0) + _CreateWindow(NULL); +} + + +void +ResourceEdit::_CreateWindow(BEntry* assocEntry) +{ + MainWindow* window = new MainWindow(_Cascade(), assocEntry); + + fWindowList.AddItem(window); + + window->Show(); +} + + +BRect +ResourceEdit::_Cascade() +{ + if (fCascadeCount == 8) { + fCascade.OffsetBy(-20 * 8, -20 * 8); + fCascadeCount = 0; + } else { + fCascade.OffsetBy(20, 20); + fCascadeCount++; + } + + return fCascade; +} diff --git a/src/apps/resourceedit/ResourceEdit.h b/src/apps/resourceedit/ResourceEdit.h new file mode 100644 index 0000000000..dcdf976cff --- /dev/null +++ b/src/apps/resourceedit/ResourceEdit.h @@ -0,0 +1,42 @@ +/* + * Copyright 2012-2013 Tri-Edge AI + * All rights reserved. Distributed under the terms of the MIT license. + */ +#ifndef RESOURCE_EDIT_H +#define RESOURCE_EDIT_H + + +#include + + +class MainWindow; + +class BEntry; +class BFilePanel; +class BMessage; + + +class ResourceEdit : public BApplication { +public: + ResourceEdit(); + ~ResourceEdit(); + + void MessageReceived(BMessage* msg); + +private: + BRect fCascade; + uint32 fCascadeCount; + BList fWindowList; + + BFilePanel* fOpenPanel; + + void ArgvReceived(int32 argc, char* argv[]); + void ReadyToRun(); + + void _CreateWindow(BEntry* assocEntry); + BRect _Cascade(); + +}; + + +#endif diff --git a/src/apps/resourceedit/ResourceEdit.rdef b/src/apps/resourceedit/ResourceEdit.rdef new file mode 100644 index 0000000000..58b821c357 --- /dev/null +++ b/src/apps/resourceedit/ResourceEdit.rdef @@ -0,0 +1,136 @@ +resource app_signature "application/x-vnd.Haiku-ResourceEdit"; + +resource app_name_catalog_entry "x-vnd.Haiku-ResourceEdit:System name:ResourceEdit"; + +resource app_version { + major = 0, + middle = 1, + minor = 0, + + variety = B_APPV_ALPHA, + internal = 0, + + short_info = "ResourceEdit", + long_info = "ResourceEdit © 2012-2013 Haiku, Inc." +}; + +resource app_flags B_SINGLE_LAUNCH; + +resource(1, "BEOS:FILE_TYPES") message { + "types" = "text/x-vnd.Be.ResourceDef" +}; + +resource vector_icon { + $"6E6369660E050102000603399E0F3D9C0ABF82B23B84A94B88504870C900A5FF" + $"F5BCEAFFF2FFB3FFE3020106023E49240000000000003CAAAA4940004A3000FF" + $"C0FFDD7C6DFFBC040192020006023A4BAE3411A9B629883C6629495368484715" + $"00FFF9BAFFFFC104020006023A6A0E3670BCB6D8C13AD0F64A21BC4A0DF300BA" + $"DCFFFF2A20F10200060239AAD5343BA5B6E7993C629D4ABB354803A500E99797" + $"FFCE323202000602AAB1FB3A081FBE8A26AF5E794C4014448D43FFFDDCAB00DB" + $"AB5F02000602B507E13A82E2BAD599B56BB44A7652479FE400116201FE69A403" + $"020006023C08200000000000004000004A4000000000FD6AD839004AB9270200" + $"06023D4D340000000000004000004A5000000000009CFA80FFF8FAFF02000603" + $"B2F679BA14D43A7FB6B38E9E460F5547105A00FFEED58DDBAB5FCFFFEED50401" + $"95020012023B8E380000000000004000004A5400C100000001FFFF0199120606" + $"AE0BB40BBF4D33C3AFB75DC173BDEFC607C13EC804CA28BD82C118B920C51BBB" + $"40BF07B8083AB6BC0605AE02B57D3EB9B9C3EFB7BB44BBB751BD75C936CA8EC1" + $"B1402F0A093B593D5BBFCDC93E455BC516C5F160465B435D4544510A045A425E" + $"3F5A3D57400A063236323D3A41403E403739330A063A433A4A404D464A464341" + $"400A064237423E48424E3F4E3948350604EE532755295528552A532B5229522A" + $"52280604EE532456295625562D532E5029502D50250A04B969B771332E502E4E" + $"2B0A04B969B5BAB969B7714E2B4E270A043324B969B5BA4E2750240A063124B8" + $"BAB5B2B8BAB779312EB677B6ECB67CB63C0606B20831245356295625562D532E" + $"3126290804BA28B4D33027302BBA28B8580003C6E8B4D3C6E8B4D3C690B51750" + $"2950B59E50B78DC6E8B858C690B814C6E8B8580A04C6F0C5C24E4F514BC9BBC4" + $"280A06C4E04F41C507374B394A45C33CC6D1C36F120A030202032020250A0001" + $"0130202501178400040A0201012020250A00010030202501178400040A010100" + $"2020250A000304050630202501178400040A0401042020250A0501052020250A" + $"0601062020250A0C0110000A0D0111000A00030D0E0F123ED413BED4133ED413" + $"3ED41347F4A24A588901178400040A0B010C023ED413BED4133ED4133ED41347" + $"F4A24A58890A0A010B023ED413BED4133ED4133ED41347F4A24A58890A09010A" + $"023ED413BED4133ED4133ED41347F4A24A58890A080109023ED413BED4133ED4" + $"133ED41347F4A24A58890A070108023ED413BED4133ED4133ED41347F4A24A58" + $"890A0001070A3ED413BED4133ED4133ED41347F4A24A588915FF" +}; + +resource(1, "add.png") #'PNG ' array { + $"89504E470D0A1A0A0000000D4948445200000018000000180806000000E0773D" + $"F80000017B494441544889ED95B14EC25014863F6AAB4864C40768D84C184908" + $"3E002B899B71742171C7677024716572C207707124260C0E460709A94C86844D" + $"144BEF6D716841CA2D5083C6857FBB7FFE73BF7B4F7B5AD8E8BF9588952A5231" + $"0B660D1D0D008967DD59559A5CAC2AD56301D2E473A739CDD8330010EF42B31E" + $"AD32D000BAEB03005BDA48210190524EEC9D5575B1011FCE07C676700347C42D" + $"8B0F1042E0391E00AE70D70014A990261FF2521C0EE5105DF8712925A4C852A2" + $"0EB4A7B9012D9A5CCE96AA6FD119AE79646AF3B6B16B7CA7C7203ED53659D796" + $"478D1CF0B4F8060934477714DB11735E54731368C0FE72C018466214511D4363" + $"D5520112AFFFD6575A4492508BB02300126F35E0812A2F94435E8A2CC7644806" + $"6B1BB8A2CF904E2837A00B61880AF0C7BFC1EC1095A8E3929996BAC0900E379C" + $"03BDB91D5E97037C75E7D66DA01091EB01CF0BF60040EDF52FEBCF01F13E1503" + $"5ADC72C2567020172F78A02B15EF7FE0EB007F8826F2807B60F0833D3652F505" + $"AA6A764F51A11AA20000000049454E44AE426082" +}; + +resource(2, "remove.png") #'PNG ' array { + $"89504E470D0A1A0A0000000D4948445200000018000000180806000000E0773D" + $"F800000275494441544889ED94C14B93611CC73F7B7D6DF80EDA72BEAFCE2D82" + $"57F022099AE065902884791C41052BD7FE804DA48378AF4E49978E199845273D" + $"CC90C0759B78085C66186387053A9C4B3417CB4DD6D3C136F5F5DDC04E1DFCC2" + $"0F5E9EDFFB7EBEBFEFFB3CEF0BE7FA6FA5C3C551557D1780A78064728B148027" + $"A3AAFA5E07C799E1E31ECFC7642824627EBF08C282C1440AC2B398DF2F92A190" + $"18F778523A38CD587566F03BAAFA617868E85A8BA2D06CB3E172B974CBDA9A77" + $"19A6014B10261EF87CE14EB71B9B24D1E6763B4AEBEBB737F2F9573BF0ABA6C1" + $"B0AACE04FBFBAF373734208A4544B188A628B8344D9792496F17740D0F0E86AF" + $"B6B454FA3649A2ADB5D5F1736BEBE6523EFF02289579B2D160379BFDBA99C90C" + $"A986F50EBB9D7B7D7D03C04087DD4E696FEF447F339361379BDD00BA81A5AA09" + $"E2B050974A793545D1554942140A9552651955964FAC894281CFE934D38B8BD1" + $"97F01A5804F6AB1A006219A6E574DAAB59AD7A932C230E0EAAD66A26C39B783C" + $"3A09534004D8A9B907C74DEAB359AF2ACB7A9310A7A61685025FB6B7799B4854" + $"8583C91E18B42A72B9815295A6C8E5CA977366F05A09A4204CDC8270BBCD5639" + $"2DC67202CDF9BC6E859EBF47581841966A701F84DB6BA7AB2801CC4074126E00" + $"BF6B2608C0631F3C348327806D4E7FB24E4003DD0ABDF1C3937434AD11E280EE" + $"C62AF05988CE423461D26F3C7CD60D74D64CB00573F570F7323814037C12A696" + $"E15103F468A097937C0722F06D069EEFC027E087C90C47D2C13906A918880894" + $"7F76F7814BE5E44158888088811883940E21A0AD26D86832022B019837C0CB92" + $"02303F022B67861FD305A0D7045E9685C3777EE55FE0E702E00F037E0BAE5DFC" + $"3C830000000049454E44AE426082" +}; + +resource(3, "moveup.png") #'PNG ' array { + $"89504E470D0A1A0A0000000D4948445200000018000000180806000000E0773D" + $"F8000001C8494441544889ED933B485B6118861F93D8788F510E27DAE00D259D" + $"0485823108723843296E22850E0EBA140AA543C4A18A9442A920EA62068582E2" + $"E0AA83E2050415A18B882028ED927AE8693C31510721A8F93B5841E9C9498A2E" + $"822FBCC3CFF7F3BCDFF75FE0510F465EC81E57F93AAE32ED85EC7B854B609F50" + $"98D4D755A1AFAB6242615302C77DC16D2185316D392044AC4D88589BD0960222" + $"A4B02A81FDCEF0D116BE84E7EA8530945B0ECFD58B911616D2312C3B1808F0A1" + $"FD9DAFBFB2D90DE2F2965D4F9DC8725E6D997ED4B072C0CC7F077C6AE27DC79B" + $"9AC19AD6221017A676573CC1539CFB4CFA1DAF5CD598CD38A0EF39DDAFBBA550" + $"9D5A00E2DCD22555763C85B686E2C8996BED178B6903828DBCEAEC94A67C2F9C" + $"64610DBF7669B5038FD3E9CF3B3C4B6EEAACDDE4FDF3D4FCE5F4D8EC063F96AE" + $"D6451512B2CFFC1823FB70FAD3B8EAD401FE72BAD8620A08A70CF8F80DD5BB4D" + $"179053E6C2DDFBD608CAB5E601A761181C63483F210EA02530807CCB09760C8E" + $"776018E025549324C8A5790049D04F88CF6B7C4EB12383DF28FE3A552D8D6CE9" + $"B7DC4D0F3FC0F20EB404D1EF1B44627BC866F5A328112D41D48A919541138540" + $"23A9A73D047633E03CCA5C7F00288AC08FE23A7EB30000000049454E44AE4260" + $"82" +}; + +resource(4, "movedown.png") #'PNG ' array { + $"89504E470D0A1A0A0000000D4948445200000018000000180806000000E0773D" + $"F8000001E6494441544889ED92DD4B53611CC73F6ED5BC680D978F6B792AC45C" + $"E164577A9710E7A6B0BAEAAE0B41F09F08BAEAC66E4421F042AF6A228A2F28BA" + $"A42226859B48DD0C247A811C8E1DE2D0081793A9674F174B523BCF966F78515F" + $"F8C173CEF7F7FB7E785EE0BF8E5B15A5CC90C0DD7543BC3DEB7707ECFC6F46D6" + $"B8FFDC6C4A98645419274A013417D50D37EB030D772ED8FA9FA657FCDA9CD991" + $"80EE7D010028AC83B5A6F6C0556AFC2F0079B0726AAF8CCA03E426588A20B979" + $"08006B437D44D6C6DE0121C169CD8500F07BD09059B04EDA4FCB2C7E0F556D50" + $"0790CA63264C7E6C6FF9E3998EDF6631D8265A1CCEE2F7994BE0BB627F8F5F3F" + $"E4594D16D7050B969E99CB7767080159E50EE2691E5FCD9B4F03B704158E5F3F" + $"1577E0BB5C2C5980F71193789A97401058D8EA71EE1E8A1924BC192A6BDDB96B" + $"D5753990E5EBE38B1C4383841FBD631A7803584A00C0EB34AF6A329CABF5D0EC" + $"BD0848757D9E83E130230F17990422C08EEDDA0200A22922DA771ACF0B82559A" + $"7DCF9705187BC2D48338A3C00CA0786E0A0970F4B6329B0C23E5D2CE4A86913D" + $"ADCC02F700F79E827743FA74A2A991DFE1A96164DF75A202DA01CFBEC3B7419C" + $"033A316302698C23077462023A00EF81C3B7A4C1A97E9DF97E9D790D3A8BDCC3" + $"970368067C4711FE8FEA273678C1FAFB9AC8FD0000000049454E44AE426082" +}; diff --git a/src/apps/resourceedit/ResourceListView.cpp b/src/apps/resourceedit/ResourceListView.cpp new file mode 100644 index 0000000000..a329d77ca6 --- /dev/null +++ b/src/apps/resourceedit/ResourceListView.cpp @@ -0,0 +1,52 @@ +/* + * Copyright 2012-2013 Tri-Edge AI + * All rights reserved. Distributed under the terms of the MIT license. + */ + + +#include "ResourceListView.h" + +#include "Constants.h" + +#include +#include + + +ResourceListView::ResourceListView(BRect rect, const char* name, + uint32 resizingMode, uint32 drawFlags, border_style border, + bool showHorizontalScrollbar) + : + BColumnListView(rect, name, resizingMode, drawFlags, border, + showHorizontalScrollbar) +{ + +} + + +ResourceListView::~ResourceListView() +{ + +} + + +void +ResourceListView::MessageReceived(BMessage* msg) +{ + switch (msg->what) { + case B_SIMPLE_DATA: { + entry_ref ref; + int32 n = 0; + + // TODO: Implement D&D adding of files. + + while (msg->FindRef("refs", n++, &ref) == B_OK) { + PRINT(("%s\n", ref.name)); + // ... + } + + break; + } + default: + BColumnListView::MessageReceived(msg); + } +} diff --git a/src/apps/resourceedit/ResourceListView.h b/src/apps/resourceedit/ResourceListView.h new file mode 100644 index 0000000000..5551f82922 --- /dev/null +++ b/src/apps/resourceedit/ResourceListView.h @@ -0,0 +1,26 @@ +/* + * Copyright 2012-2013 Tri-Edge AI + * All rights reserved. Distributed under the terms of the MIT license. + */ +#ifndef RESOURCE_LIST_VIEW_H +#define RESOURCE_LIST_VIEW_H + + +#include + + +class ResourceListView : public BColumnListView { +public: + ResourceListView(BRect rect, const char* name, uint32 resizingMode, + uint32 drawFlags, border_style border = B_NO_BORDER, + bool showHorizontalScrollbar = true); + ~ResourceListView(); + + void MessageReceived(BMessage* msg); + +private: + +}; + + +#endif diff --git a/src/apps/resourceedit/ResourceRow.cpp b/src/apps/resourceedit/ResourceRow.cpp new file mode 100644 index 0000000000..ebe5dce9ea --- /dev/null +++ b/src/apps/resourceedit/ResourceRow.cpp @@ -0,0 +1,141 @@ +/* + * Copyright 2012-2013 Tri-Edge AI + * All rights reserved. Distributed under the terms of the MIT license. + */ + + +#include "ResourceRow.h" + +#include +#include + + +ResourceRow::ResourceRow() + : + BRow() +{ + fRawData = NULL; + + SetField(new BIntegerField(0), 0); + SetField(new BStringField(""), 1); + SetField(new BStringField(""), 2); + SetField(new BStringField(""), 3); + SetField(new BStringField(""), 4); + SetField(new BSizeField(0), 5); +} + + +ResourceRow::~ResourceRow() +{ + // ... +} + + +void +ResourceRow::SetResourceID(int32 id) +{ + ((BIntegerField*)GetField(0))->SetValue(id); +} + + +void +ResourceRow::SetResourceName(const char* name) +{ + ((BStringField*)GetField(1))->SetString(name); +} + + +void +ResourceRow::SetResourceType(const char* type) +{ + ((BStringField*)GetField(2))->SetString(type); +} + + +void +ResourceRow::SetResourceTypeCode(type_code code) +{ + fTypeCode = code; + TypeCodeToString(code, fTypeString); + ((BStringField*)GetField(3))->SetString(fTypeString); +} + + +void +ResourceRow::SetResourceData(const char* data) +{ + ((BStringField*)GetField(4))->SetString(data); +} + + +void +ResourceRow::SetResourceRawData(const void* data) +{ + if (data == NULL) + data = kDefaultData; + + fRawData = data; + + int32 ix = FindTypeCodeIndex(ResourceTypeCode()); + + if (ix == -1) + SetResourceData("[Unknown Data]"); + else + SetResourceData(kDefaultTypes[ix].toString(fRawData)); +} + + +void +ResourceRow::SetResourceSize(off_t size) +{ + ((BSizeField*)GetField(5))->SetSize(size); +} + + +int32 +ResourceRow::ResourceID() +{ + return ((BIntegerField*)GetField(0))->Value(); +} + + +const char* +ResourceRow::ResourceName() +{ + return ((BStringField*)GetField(1))->String(); +} + + +const char* +ResourceRow::ResourceType() +{ + return ((BStringField*)GetField(2))->String(); +} + + +type_code +ResourceRow::ResourceTypeCode() +{ + return fTypeCode; +} + + +const char* +ResourceRow::ResourceData() +{ + return ((BStringField*)GetField(4))->String(); +} + + +const void* +ResourceRow::ResourceRawData() +{ + return fRawData; +} + + +off_t +ResourceRow::ResourceSize() +{ + return ((BSizeField*)GetField(5))->Size(); +} diff --git a/src/apps/resourceedit/ResourceRow.h b/src/apps/resourceedit/ResourceRow.h new file mode 100644 index 0000000000..a9e65caa0e --- /dev/null +++ b/src/apps/resourceedit/ResourceRow.h @@ -0,0 +1,43 @@ +/* + * Copyright 2012-2013 Tri-Edge AI + * All rights reserved. Distributed under the terms of the MIT license. + */ +#ifndef RESOURCE_ROW_H +#define RESOURCE_ROW_H + + +#include "DefaultTypes.h" + +#include + + +class ResourceRow : public BRow { +public: + ResourceRow(); + ~ResourceRow(); + + void SetResourceID(int32 id); + void SetResourceName(const char* name); + void SetResourceType(const char* type); + void SetResourceTypeCode(type_code code); + void SetResourceData(const char* data); + void SetResourceRawData(const void*); + void SetResourceSize(off_t size); + + int32 ResourceID(); + const char* ResourceName(); + const char* ResourceType(); + type_code ResourceTypeCode(); + const char* ResourceData(); + const void* ResourceRawData(); + off_t ResourceSize(); + +private: + const void* fRawData; + type_code fTypeCode; + char fTypeString[8]; + +}; + + +#endif diff --git a/src/apps/resourceedit/main.cpp b/src/apps/resourceedit/main.cpp new file mode 100644 index 0000000000..b370361660 --- /dev/null +++ b/src/apps/resourceedit/main.cpp @@ -0,0 +1,17 @@ +/* + * Copyright 2012-2013 Tri-Edge AI + * All rights reserved. Distributed under the terms of the MIT license. + */ + + +#include "ResourceEdit.h" + + +int +main() +{ + ResourceEdit* app = new ResourceEdit(); + app->Run(); + delete app; + return 0; +} diff --git a/src/kits/interface/ColumnListView.cpp b/src/kits/interface/ColumnListView.cpp index 91bf16a430..ec8b1affa7 100644 --- a/src/kits/interface/ColumnListView.cpp +++ b/src/kits/interface/ColumnListView.cpp @@ -523,6 +523,13 @@ BRow::IsExpanded() const } +bool +BRow::IsSelected() const +{ + return fPrevSelected != NULL; +} + + void BRow::ValidateFields() const { @@ -1258,6 +1265,60 @@ BColumnListView::UpdateRow(BRow* row) } +bool +BColumnListView::SwapRows(int32 index1, int32 index2, BRow* parentRow1, + BRow* parentRow2) +{ + BRow* row1 = NULL; + BRow* row2 = NULL; + + BRowContainer* container1 = NULL; + BRowContainer* container2 = NULL; + + if (parentRow1 == NULL) + container1 = fOutlineView->RowList(); + else + container1 = parentRow1->fChildList; + + if (container1 == NULL) + return false; + + if (parentRow2 == NULL) + container2 = fOutlineView->RowList(); + else + container2 = parentRow1->fChildList; + + if (container2 == NULL) + return false; + + row1 = container1->ItemAt(index1); + + if (row1 == NULL) + return false; + + row2 = container2->ItemAt(index2); + + if (row2 == NULL) + return false; + + container1->ReplaceItem(index2, row1); + container2->ReplaceItem(index1, row2); + + BRect rect1; + BRect rect2; + BRect rect; + + fOutlineView->FindRect(row1, &rect1); + fOutlineView->FindRect(row2, &rect2); + + rect = rect1 | rect2; + + fOutlineView->Invalidate(rect); + + return true; +} + + void BColumnListView::ScrollTo(const BRow* row) { @@ -4195,7 +4256,7 @@ OutlineView::AddRow(BRow* row, int32 Index, BRow* parentRow) row->fParent = parentRow; - if (fMasterView->SortingEnabled()) { + if (fMasterView->SortingEnabled() && !fSortColumns->IsEmpty()) { // Ignore index here. if (parentRow) { if (parentRow->fChildList == NULL) diff --git a/src/kits/interface/Menu.cpp b/src/kits/interface/Menu.cpp index 8491d2fcce..0485f9779b 100644 --- a/src/kits/interface/Menu.cpp +++ b/src/kits/interface/Menu.cpp @@ -1107,6 +1107,7 @@ BMenu::FindMarked() { for (int32 i = 0; i < fItems.CountItems(); i++) { BMenuItem* item = ItemAt(i); + if (item->IsMarked()) return item; } @@ -1115,6 +1116,20 @@ BMenu::FindMarked() } +int32 +BMenu::FindMarkedIndex() +{ + for (int32 i = 0; i < fItems.CountItems(); i++) { + BMenuItem* item = ItemAt(i); + + if (item->IsMarked()) + return i; + } + + return -1; +} + + BMenu* BMenu::Supermenu() const { From dc4fe6be00757dfe3e0882d54598be4b98926404 Mon Sep 17 00:00:00 2001 From: Tri-Edge AI Date: Mon, 14 Jan 2013 06:47:46 +0200 Subject: [PATCH 016/104] Extended ResourceEdit. Signed-off-by: Matt Madia --- src/apps/resourceedit/Constants.h | 21 +- src/apps/resourceedit/DefaultTypes.cpp | 88 +- src/apps/resourceedit/DefaultTypes.h | 79 +- src/apps/resourceedit/EditWindow.cpp | 163 ++++ src/apps/resourceedit/EditWindow.h | 53 ++ src/apps/resourceedit/Jamfile | 35 +- src/apps/resourceedit/MainWindow.cpp | 782 ++++++++++++++++-- src/apps/resourceedit/MainWindow.h | 111 ++- src/apps/resourceedit/ResourceEdit.cpp | 37 +- src/apps/resourceedit/ResourceEdit.h | 5 + src/apps/resourceedit/ResourceEdit.rdef | 2 +- src/apps/resourceedit/ResourceListView.cpp | 12 +- src/apps/resourceedit/ResourceListView.h | 1 + src/apps/resourceedit/ResourceRow.cpp | 78 +- src/apps/resourceedit/ResourceRow.h | 15 +- src/apps/resourceedit/SettingsFile.cpp | 56 ++ src/apps/resourceedit/SettingsFile.h | 33 + src/apps/resourceedit/SettingsWindow.cpp | 120 +++ src/apps/resourceedit/SettingsWindow.h | 48 ++ src/apps/resourceedit/edits/AppFlagsEdit.cpp | 4 + src/apps/resourceedit/edits/AppFlagsEdit.h | 4 + src/apps/resourceedit/edits/BooleanEdit.cpp | 71 ++ src/apps/resourceedit/edits/BooleanEdit.h | 30 + src/apps/resourceedit/edits/EditView.cpp | 52 ++ src/apps/resourceedit/edits/EditView.h | 31 + src/apps/resourceedit/edits/NormalEdit.cpp | 64 ++ src/apps/resourceedit/edits/NormalEdit.h | 31 + .../{ => interface}/ImageButton.cpp | 0 .../{ => interface}/ImageButton.h | 0 .../settings/GenericSettingsView.cpp | 60 ++ .../settings/GenericSettingsView.h | 37 + src/apps/resourceedit/support/UndoContext.cpp | 175 ++++ src/apps/resourceedit/support/UndoContext.h | 55 ++ 33 files changed, 2121 insertions(+), 232 deletions(-) create mode 100644 src/apps/resourceedit/EditWindow.cpp create mode 100644 src/apps/resourceedit/EditWindow.h create mode 100644 src/apps/resourceedit/SettingsFile.cpp create mode 100644 src/apps/resourceedit/SettingsFile.h create mode 100644 src/apps/resourceedit/SettingsWindow.cpp create mode 100644 src/apps/resourceedit/SettingsWindow.h create mode 100644 src/apps/resourceedit/edits/AppFlagsEdit.cpp create mode 100644 src/apps/resourceedit/edits/AppFlagsEdit.h create mode 100644 src/apps/resourceedit/edits/BooleanEdit.cpp create mode 100644 src/apps/resourceedit/edits/BooleanEdit.h create mode 100644 src/apps/resourceedit/edits/EditView.cpp create mode 100644 src/apps/resourceedit/edits/EditView.h create mode 100644 src/apps/resourceedit/edits/NormalEdit.cpp create mode 100644 src/apps/resourceedit/edits/NormalEdit.h rename src/apps/resourceedit/{ => interface}/ImageButton.cpp (100%) rename src/apps/resourceedit/{ => interface}/ImageButton.h (100%) create mode 100644 src/apps/resourceedit/settings/GenericSettingsView.cpp create mode 100644 src/apps/resourceedit/settings/GenericSettingsView.h create mode 100644 src/apps/resourceedit/support/UndoContext.cpp create mode 100644 src/apps/resourceedit/support/UndoContext.h diff --git a/src/apps/resourceedit/Constants.h b/src/apps/resourceedit/Constants.h index 4a9766e7d7..1bb2e97590 100644 --- a/src/apps/resourceedit/Constants.h +++ b/src/apps/resourceedit/Constants.h @@ -25,13 +25,24 @@ #define MSG_CLEAR 'm015' #define MSG_SELECTALL 'm016' -#define MSG_ADD 'm020' -#define MSG_REMOVE 'm021' -#define MSG_MOVEUP 'm022' -#define MSG_MOVEDOWN 'm023' +#define MSG_ADDAPPRES 'm020' +#define MSG_SETTINGS 'm021' -#define MSG_SELECTION 'm030' +#define MSG_ADD 'm030' +#define MSG_REMOVE 'm031' +#define MSG_MOVEUP 'm032' +#define MSG_MOVEDOWN 'm033' +#define MSG_SELECTION 'm040' +#define MSG_INVOCATION 'm041' + +#define MSG_ACCEPT 'm050' +#define MSG_CANCEL 'm051' +#define MSG_IGNORE 'm052' + +#define MSG_SETTINGS_APPLY 'm022' +#define MSG_SETTINGS_REVERT 'm023' +#define MSG_SETTINGS_CLOSED 'm024' // TODO: Remove prior to release. #define DEBUG 1 diff --git a/src/apps/resourceedit/DefaultTypes.cpp b/src/apps/resourceedit/DefaultTypes.cpp index 9f7de5deae..3fed852f9c 100644 --- a/src/apps/resourceedit/DefaultTypes.cpp +++ b/src/apps/resourceedit/DefaultTypes.cpp @@ -9,84 +9,22 @@ #include -BString -toStringBOOL(const void* data) +int32 +ResourceType::FindIndex(type_code code) { - if (*(bool*)data) - return "✔ true"; - else - return "✖ false"; -} + for (int32 i = 0; kDefaultTypes[i].type != NULL; i++) + if (StringToCode(kDefaultTypes[i].code) == code) + return i; - -BString -toStringBYTE(const void* data) -{ - return (BString() << *(int8*)data); -} - - -BString -toStringSHRT(const void* data) -{ - return (BString() << *(int16*)data); -} - - -BString -toStringLONG(const void* data) -{ - return (BString() << *(int32*)data); -} - - -BString -toStringLLNG(const void* data) -{ - return (BString() << *(int64*)data); -} - - -BString -toStringUBYT(const void* data) -{ - return (BString() << *(uint8*)data); -} - - -BString -toStringUSHT(const void* data) -{ - return (BString() << *(uint16*)data); -} - - -BString -toStringULNG(const void* data) -{ - return (BString() << *(uint32*)data); -} - - -BString -toStringULLG(const void* data) -{ - return (BString() << *(uint64*)data); -} - - -BString -toStringRAWT(const void* data) -{ - return "[Raw Data]"; + return -1; } int32 -FindTypeCodeIndex(type_code code) +ResourceType::FindIndex(const char* type) { for (int32 i = 0; kDefaultTypes[i].type != NULL; i++) - if (kDefaultTypes[i].typeCode == code) + if (strcmp(kDefaultTypes[i].type, type) == 0) return i; return -1; @@ -94,8 +32,16 @@ FindTypeCodeIndex(type_code code) void -TypeCodeToString(type_code code, char* str) +ResourceType::CodeToString(type_code code, char* str) { *(type_code*)str = B_HOST_TO_BENDIAN_INT32(code); str[4] = '\0'; } + + +type_code +ResourceType::StringToCode(const char* code) +{ + // TODO: Code may be in other formats, too! Ex.: 0x4C4F4E47 + return B_BENDIAN_TO_HOST_INT32(*(int32*)code); +} diff --git a/src/apps/resourceedit/DefaultTypes.h b/src/apps/resourceedit/DefaultTypes.h index 42ebf87d77..ef51b66aa1 100644 --- a/src/apps/resourceedit/DefaultTypes.h +++ b/src/apps/resourceedit/DefaultTypes.h @@ -6,61 +6,64 @@ #define DEFAULT_TYPES_H +#include "AppFlagsEdit.h" +#include "BooleanEdit.h" +#include "EditView.h" +#include "NormalEdit.h" +#include "ResourceRow.h" + #include -struct ResourceDataType { - const char* type; - type_code typeCode; - uint32 size; - BString (*toString)(const void*); +struct ResourceType { + const char* type; + const char* code; + const char* data; + uint32 size; + EditView* edit; + + static int32 FindIndex(const char* type); + static int32 FindIndex(type_code code); + + static void CodeToString(type_code code, char* str); + static type_code StringToCode(const char* code); }; -// TODO: Rework design of this. This one sucks. -BString toStringBOOL(const void* data); -BString toStringBYTE(const void* data); -BString toStringSHRT(const void* data); -BString toStringLONG(const void* data); -BString toStringLLNG(const void* data); -BString toStringUBYT(const void* data); -BString toStringUSHT(const void* data); -BString toStringULNG(const void* data); -BString toStringULLG(const void* data); -BString toStringRAWT(const void* data); +#define LINE "", "", "", ~0, NULL +#define END NULL, NULL, NULL, 0, NULL -char * const kDefaultData[] = { - 0, 0, 0, 0, 0, 0, 0, 0 -}; - -#define LINE "", 0, ~0 -#define END NULL, 0, 0 - -const ResourceDataType kDefaultTypes[] = { - { "bool", 'BOOL', 1, toStringBOOL }, +const ResourceType kDefaultTypes[] = { + { "app_signature", "", "application/MyApp", 18, new NormalEdit() }, + { "app_name_catalog_entry", "", "MyApp:System name:MyApp", 24, new NormalEdit() }, + //{ "app_flags", "", "None", 4, NULL }, { LINE }, - { "int8", 'BYTE', 1, toStringBYTE }, - { "int16", 'SHRT', 2, toStringSHRT }, - { "int32", 'LONG', 4, toStringLONG }, - { "int64", 'LLNG', 8, toStringLLNG }, + { "bool", "BOOL", "false", 1, new BooleanEdit() }, { LINE }, - { "uint8", 'UBYT', 1, toStringUBYT }, - { "uint16", 'USHT', 2, toStringUSHT }, - { "uint32", 'ULNG', 4, toStringULNG }, - { "uint64", 'ULLG', 8, toStringULLG }, + { "int8", "BYTE", "0", 1, new NormalEdit() }, + { "int16", "SHRT", "0", 2, new NormalEdit() }, + { "int32", "LONG", "0", 4, new NormalEdit() }, + { "int64", "LLNG", "0", 8, new NormalEdit() }, { LINE }, - { "raw", 'RAWT', 0, toStringRAWT }, + { "uint8", "UBYT", "0", 1, new NormalEdit() }, + { "uint16", "USHT", "0", 2, new NormalEdit() }, + { "uint32", "ULNG", "0", 4, new NormalEdit() }, + { "uint64", "ULLG", "0", 8, new NormalEdit() }, + { LINE }, + { "string", "CSTR", "\"\"", 0, NULL }, + { "raw", "RAWT", "", 0, NULL }, + { LINE }, + { "array", "", "", 0, NULL }, + { "message", "", "", 0, NULL }, + { "import", "", "", 0, NULL }, { END } }; -const int32 kDefaultTypeSelected = 4; +const int32 kDefaultTypeSelected = 8; // int32 #undef LINE #undef END -int32 FindTypeCodeIndex(type_code code); -void TypeCodeToString(type_code code, char* str); - #endif diff --git a/src/apps/resourceedit/EditWindow.cpp b/src/apps/resourceedit/EditWindow.cpp new file mode 100644 index 0000000000..73b03644ae --- /dev/null +++ b/src/apps/resourceedit/EditWindow.cpp @@ -0,0 +1,163 @@ +/* + * Copyright 2012-2013 Tri-Edge AI + * All rights reserved. Distributed under the terms of the MIT license. + */ + + +#include "EditWindow.h" + +#include "Constants.h" +#include "DefaultTypes.h" +#include "EditView.h" +#include "ResourceRow.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +EditWindow::EditWindow(BRect frame, ResourceRow* row) + : + BWindow(frame, "Edit Resource", + B_TITLED_WINDOW_LOOK, B_MODAL_APP_WINDOW_FEEL, 0) +{ + int32 ix = ResourceType::FindIndex(row->ResourceType()); + + fRow = row; + + fView = new BView(Bounds(), "fView", B_FOLLOW_ALL, 0); + fView->SetLayout(new BGroupLayout(B_VERTICAL)); + + fIDText = new BTextControl(BRect(0, 0, 0, 0), + "fIDText", "ID:", row->ResourceStringID(), NULL); + fIDText->SetDivider(50); + + fNameText = new BTextControl(BRect(0, 0, 0, 0), + "fNameText", "Name:", row->ResourceName(), NULL); + fNameText->SetDivider(50); + + fTypePopUp = new BPopUpMenu("(Type)"); + + // TODO: (Not so) evil redundancy. + for (int32 i = 0; kDefaultTypes[i].type != NULL; i++) { + if (kDefaultTypes[i].size == ~(uint32)0) + fTypePopUp->AddSeparatorItem(); + else + fTypePopUp->AddItem(new BMenuItem(kDefaultTypes[i].type, + new BMessage(MSG_SELECTION))); + } + // --- + + fTypePopUp->ItemAt(ix)->SetMarked(true); + + fTypeMenu = new BMenuField(BRect(0, 0, 0, 0), + "fTypeMenu", "Type:", fTypePopUp); + fTypeMenu->SetDivider(50); + + fCodeText = new BTextControl(BRect(0, 0, 0, 0), + "fCodeText", "Code:", row->ResourceStringCode(), NULL); + fCodeText->SetDivider(50); + + fEditViewBox = new BBox(BRect(0, 0, 0, 0), "fEditViewBox"); + fEditViewBox->SetLayout(new BGroupLayout(B_VERTICAL)); + + fEditView = kDefaultTypes[ix].edit; + fEditView->AttachTo(fEditViewBox); + fEditView->Edit(fRow); + + fErrorString = new BStringView(BRect(0, 0, 0, 0), + "fErrorString", ""); + + fErrorString->SetHighColor(ui_color(B_FAILURE_COLOR)); + + fCancelButton = new BButton(BRect(0, 0, 0, 0), + "fCancelButton", "Cancel", new BMessage(MSG_CANCEL)); + fOKButton = new BButton(BRect(0, 0, 0, 0), + "fOKButton", "OK", new BMessage(MSG_ACCEPT)); + + fView->AddChild(BGroupLayoutBuilder(B_VERTICAL, 8) + .Add(fIDText) + .Add(fNameText) + .Add(fTypeMenu) + .Add(fCodeText) + .Add(fEditViewBox) + .Add(fErrorString) + .Add(BGroupLayoutBuilder(B_HORIZONTAL, 8) + .AddGlue() + .Add(fCancelButton) + .Add(fOKButton) + .SetInsets(8, 8, 8, 8) + ) + .SetInsets(8, 8, 8, 8) + ); + + AddChild(fView); + ResizeTo(250, 350); + + Show(); +} + + +EditWindow::~EditWindow() +{ + fEditView->RemoveSelf(); +} + + +void +EditWindow::MessageReceived(BMessage* msg) +{ + switch (msg->what) { + case MSG_SELECTION: + { + int32 ix = fTypePopUp->FindMarkedIndex(); + + fCodeText->SetText(kDefaultTypes[ix].code); + + fEditView->RemoveSelf(); + + fEditView = kDefaultTypes[ix].edit; + fEditView->AttachTo(fEditViewBox); + fEditView->Edit(fRow); + + break; + } + case MSG_CANCEL: + PostMessage(B_QUIT_REQUESTED); + break; + + case MSG_ACCEPT: + { + if (_Validate()) { + int32 ix = fTypePopUp->FindMarkedIndex(); + + fRow->SetResourceStringID(fIDText->Text()); + fRow->SetResourceName(fNameText->Text()); + fRow->SetResourceType(kDefaultTypes[ix].type); + fRow->SetResourceStringCode(fCodeText->Text()); + fRow->SetResourceSize(kDefaultTypes[ix].size); + + fEditView->Commit(); + + PostMessage(B_QUIT_REQUESTED); + } + + break; + } + } +} + + +bool +EditWindow::_Validate() +{ + // TODO: Implement validation of entered data. + fErrorString->SetText(""); + return true; +} diff --git a/src/apps/resourceedit/EditWindow.h b/src/apps/resourceedit/EditWindow.h new file mode 100644 index 0000000000..d104af98fb --- /dev/null +++ b/src/apps/resourceedit/EditWindow.h @@ -0,0 +1,53 @@ +/* + * Copyright 2012-2013 Tri-Edge AI + * All rights reserved. Distributed under the terms of the MIT license. + */ +#ifndef EDIT_WINDOW_H +#define EDIT_WINDOW_H + + +#include + + +class EditView; +class ResourceRow; + +class BBox; +class BButton; +class BMenuField; +class BPopUpMenu; +class BStringView; +class BTextControl; + + +class EditWindow : public BWindow { +public: + EditWindow(BRect frame, ResourceRow* row); + ~EditWindow(); + + void MessageReceived(BMessage* msg); + +private: + ResourceRow* fRow; + + BView* fView; + + BTextControl* fIDText; + BTextControl* fNameText; + BPopUpMenu* fTypePopUp; + BMenuField* fTypeMenu; + BTextControl* fCodeText; + + EditView* fEditView; + BBox* fEditViewBox; + + BStringView* fErrorString; + + BButton* fCancelButton; + BButton* fOKButton; + + bool _Validate(); +}; + + +#endif diff --git a/src/apps/resourceedit/Jamfile b/src/apps/resourceedit/Jamfile index 9507e9ad1b..b392f77ea4 100644 --- a/src/apps/resourceedit/Jamfile +++ b/src/apps/resourceedit/Jamfile @@ -2,14 +2,46 @@ SubDir HAIKU_TOP src apps resourceedit ; UsePrivateHeaders interface shared ; +local sourceDirs = + edits + interface + settings + support +; + +local sourceDir ; + +for sourceDir in $(sourceDirs) { + SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src apps resourceedit $(sourceDir) ] ; +} + Application ResourceEdit : - DefaultTypes.cpp + # edits + AppFlagsEdit.cpp + BooleanEdit.cpp + EditView.cpp + NormalEdit.cpp + + # interface ImageButton.cpp + + # settings + GenericSettingsView.cpp + + # support + UndoContext.cpp + + # . + DefaultTypes.cpp + EditWindow.cpp MainWindow.cpp ResourceEdit.cpp ResourceListView.cpp ResourceRow.cpp + SettingsFile.cpp + SettingsWindow.cpp + main.cpp : be @@ -17,7 +49,6 @@ Application ResourceEdit translation libcolumnlistview.a $(TARGET_LIBSTDC++) - : ResourceEdit.rdef ; diff --git a/src/apps/resourceedit/MainWindow.cpp b/src/apps/resourceedit/MainWindow.cpp index d6413e3ea9..1a04e8c132 100644 --- a/src/apps/resourceedit/MainWindow.cpp +++ b/src/apps/resourceedit/MainWindow.cpp @@ -7,11 +7,17 @@ #include "MainWindow.h" #include "Constants.h" +#include "EditWindow.h" #include "ImageButton.h" #include "ResourceListView.h" #include "ResourceRow.h" +#include "SettingsFile.h" +#include "SettingsWindow.h" +#include "UndoContext.h" +#include #include +#include #include #include #include @@ -23,8 +29,8 @@ #include #include #include -#include #include +#include #include #include @@ -39,13 +45,19 @@ using namespace std; -MainWindow::MainWindow(BRect frame, BEntry* assocEntry) +MainWindow::MainWindow(BRect frame, BEntry* assocEntry, SettingsFile* settings) : - BWindow(frame, NULL, B_DOCUMENT_WINDOW, 0) + BWindow(frame, NULL, B_DOCUMENT_WINDOW, B_OUTLINE_RESIZE) { fAssocEntry = assocEntry; + fSettings = settings; + + fUndoContext = new UndoContext(); + + AdaptSettings(); fSavePanel = NULL; + fUnsavedChanges = false; fMenuBar = new BMenuBar(BRect(0, 0, 600, 1), "fMenuBar"); @@ -64,14 +76,24 @@ MainWindow::MainWindow(BRect frame, BEntry* assocEntry) fEditMenu = new BMenu("Edit", B_ITEMS_IN_COLUMN); fUndoItem = new BMenuItem("Undo", new BMessage(MSG_UNDO), 'Z'); + fUndoItem->SetEnabled(false); fRedoItem = new BMenuItem("Redo", new BMessage(MSG_REDO), 'Y'); + fRedoItem->SetEnabled(false); fCutItem = new BMenuItem("Cut", new BMessage(MSG_CUT), 'X'); + fCutItem->SetEnabled(false); fCopyItem = new BMenuItem("Copy", new BMessage(MSG_COPY), 'C'); + fCopyItem->SetEnabled(false); fPasteItem = new BMenuItem("Paste", new BMessage(MSG_PASTE), 'V'); + fPasteItem->SetEnabled(false); fClearItem = new BMenuItem("Clear", new BMessage(MSG_CLEAR)); fSelectAllItem = new BMenuItem("Select All", new BMessage(MSG_SELECTALL), 'A'); + fToolsMenu = new BMenu("Tools", B_ITEMS_IN_COLUMN); + fAddAppResourcesItem = new BMenuItem("Add app resources", + new BMessage(MSG_ADDAPPRES)); + fSettingsItem = new BMenuItem("Settings", new BMessage(MSG_SETTINGS)); + fHelpMenu = new BMenu("Help", B_ITEMS_IN_COLUMN); fResourceIDText = new BTextControl(BRect(0, 0, 47, 23).OffsetBySelf(8, 24), @@ -127,8 +149,8 @@ MainWindow::MainWindow(BRect frame, BEntry* assocEntry) fResourceList = new ResourceListView(listRect, "fResourceList", B_FOLLOW_ALL, 0); - fResourceList->AddColumn(new BIntegerColumn("ID", 48, 1, 999, - B_ALIGN_RIGHT), 0); + fResourceList->AddColumn(new BStringColumn("ID", 48, 1, 999, + B_ALIGN_LEFT), 0); fResourceList->AddColumn(new BStringColumn("Name", 156, 1, 999, B_TRUNCATE_END, B_ALIGN_LEFT), 1); fResourceList->AddColumn(new BStringColumn("Type", 56, 1, 999, @@ -140,10 +162,17 @@ MainWindow::MainWindow(BRect frame, BEntry* assocEntry) fResourceList->AddColumn(new BSizeColumn("Size", 74, 1, 999, B_ALIGN_RIGHT), 5); - fResourceList->SetLatchWidth(0); + //fResourceList->SetLatchWidth(0); fResourceList->SetTarget(this); fResourceList->SetSelectionMessage(new BMessage(MSG_SELECTION)); + fResourceList->SetInvocationMessage(new BMessage(MSG_INVOCATION)); + + fStatsString = new BStringView(BRect(3, 2, 150, 13), "fStatsString", ""); + fStatsString->SetFontSize(11.0f); + + fStatsBox = new BBox(BRect(0, 0, 150, 16), "fStatsBox"); + fStatsBox->SetBorder(B_PLAIN_BORDER); AddChild(fMenuBar); @@ -170,6 +199,11 @@ MainWindow::MainWindow(BRect frame, BEntry* assocEntry) fEditMenu->AddSeparatorItem(); fEditMenu->AddItem(fSelectAllItem); + fMenuBar->AddItem(fToolsMenu); + fToolsMenu->AddItem(fAddAppResourcesItem); + fToolsMenu->AddSeparatorItem(); + fToolsMenu->AddItem(fSettingsItem); + fMenuBar->AddItem(fHelpMenu); fToolbarView->AddChild(fResourceIDText); @@ -183,6 +217,8 @@ MainWindow::MainWindow(BRect frame, BEntry* assocEntry) AddChild(fToolbarView); AddChild(fResourceList); + fResourceList->AddStatusView(fStatsBox); + fStatsBox->AddChild(fStatsString); if (assocEntry != NULL) { _SetTitleFromEntry(); @@ -195,15 +231,57 @@ MainWindow::MainWindow(BRect frame, BEntry* assocEntry) MainWindow::~MainWindow() { - + delete fUndoContext; } bool MainWindow::QuitRequested() { - // TODO: Check if file is saved. + // CAUTION: Do not read the body of this function if you + // are known to suffer from gotophobia. + if (fUnsavedChanges) { + Activate(); + + char nameBuffer[B_FILE_NAME_LENGTH]; + + if (fAssocEntry != NULL) + fAssocEntry->GetName(nameBuffer); + else + strcpy(nameBuffer, "Untitled"); + + BString warning = ""; + warning << "Save changse to'"; + warning << nameBuffer; + warning << "' before closing?"; + + BAlert* alert = new BAlert("Save", warning.String(), + "Cancel", "Don't save", "Save", + B_WIDTH_AS_USUAL, B_OFFSET_SPACING, B_WARNING_ALERT); + + alert->SetShortcut(0, B_ESCAPE); + + int32 result = alert->Go(); + + switch (result) { + case 0: + return false; + case 1: + goto quit; + case 2: + { + _Save(); + + if (fUnsavedChanges) + return false; + else + goto quit; + } + } + } + + quit: BMessage* msg = new BMessage(MSG_CLOSE); msg->AddPointer("window", (void*)this); be_app->PostMessage(msg); @@ -218,15 +296,28 @@ MainWindow::SelectionChanged() fMoveUpButton->SetEnabled(false); fMoveDownButton->SetEnabled(false); fRemoveButton->SetEnabled(false); + + fCutItem->SetEnabled(false); + fCopyItem->SetEnabled(false); } else { fRemoveButton->SetEnabled(true); fMoveUpButton->SetEnabled(!fResourceList->RowAt(0)->IsSelected()); fMoveDownButton->SetEnabled(!fResourceList->RowAt( fResourceList->CountRows() - 1)->IsSelected()); + + fCutItem->SetEnabled(true); + fCopyItem->SetEnabled(true); } } +void +MainWindow::MouseDown(BPoint point) +{ + +} + + void MainWindow::MessageReceived(BMessage* msg) { @@ -282,13 +373,13 @@ MainWindow::MessageReceived(BMessage* msg) break; case MSG_UNDO: - // TODO: Implement. - PRINT(("[MSG_UNDO]: Not yet implemented.")); + fUndoContext->Undo(); + _RefreshUndoRedo(); break; case MSG_REDO: - // TODO: Implement. - PRINT(("[MSG_REDO]: Not yet implemented.")); + fUndoContext->Redo(); + _RefreshUndoRedo(); break; case MSG_CUT: @@ -307,10 +398,20 @@ MainWindow::MessageReceived(BMessage* msg) break; case MSG_CLEAR: - fResourceList->Clear(); + { + BList* rows = new BList(); + + for (int32 i = 0; i < fResourceList->CountRows(); i++) { + ResourceRow* row = (ResourceRow*)fResourceList->RowAt(i); + row->ActionIndex = i; + rows->AddItem(row); + } + + _Do(new RemoveAction("Clear", fResourceList, rows)); + SelectionChanged(); break; - + } case MSG_SELECTALL: { for (int32 i = 0; i < fResourceList->CountRows(); i++) @@ -319,6 +420,10 @@ MainWindow::MessageReceived(BMessage* msg) SelectionChanged(); break; } + case MSG_SETTINGS: + be_app->PostMessage(MSG_SETTINGS); + break; + case MSG_ADD: { // Thank you, François Claus :D Merry Christmas! @@ -326,67 +431,108 @@ MainWindow::MessageReceived(BMessage* msg) int32 ix = fResourceTypePopUp->FindMarkedIndex(); if (ix != -1) { + BList* rows = new BList(); + ResourceRow* row = new ResourceRow(); row->SetResourceID(_NextResourceID()); row->SetResourceType(kDefaultTypes[ix].type); - row->SetResourceTypeCode(kDefaultTypes[ix].typeCode); - row->SetResourceRawData(kDefaultData); + row->SetResourceStringCode(kDefaultTypes[ix].code); + row->SetResourceData(kDefaultTypes[ix].data); row->SetResourceSize(kDefaultTypes[ix].size); - fResourceList->AddRow(row); + row->ActionIndex = fResourceList->CountRows(NULL); + + rows->AddItem(row); + + _Do(new AddAction("Add", fResourceList, rows)); } break; } case MSG_REMOVE: { + BList* rows = new BList(); + for (int i = 0; i < fResourceList->CountRows(); i++) { - BRow* row = fResourceList->RowAt(i); + ResourceRow* row = (ResourceRow*)fResourceList->RowAt(i); if (row->IsSelected()) { - fResourceList->RemoveRow(row); - i--; + row->ActionIndex = i; + rows->AddItem(row); } } + if (!rows->IsEmpty()) + _Do(new RemoveAction("Remove", fResourceList, rows)); + else + delete rows; + break; } case MSG_MOVEUP: { + BList* rows = new BList(); + for (int i = 1; i < fResourceList->CountRows(); i++) { - BRow* row = fResourceList->RowAt(i); - - if (row->IsSelected()) - fResourceList->SwapRows(i, i - 1); + ResourceRow* row = (ResourceRow*)fResourceList->RowAt(i); + if (row->IsSelected()) { + row->ActionIndex = i; + rows->AddItem(row); + } } - fResourceList->ClearSortColumns(); - SelectionChanged(); + _Do(new MoveUpAction("Move Up", fResourceList, rows)); + break; } case MSG_MOVEDOWN: { - for (int i = fResourceList->CountRows() - 1 - 1; i >= 0; i--) { - BRow* row = fResourceList->RowAt(i); + BList* rows = new BList(); - if (row->IsSelected()) - fResourceList->SwapRows(i, i + 1); + for (int i = 0; i < fResourceList->CountRows() - 1; i++) { + ResourceRow* row = (ResourceRow*)fResourceList->RowAt(i); + + if (row->IsSelected()) { + row->ActionIndex = i; + rows->AddItem(row); + } } - fResourceList->ClearSortColumns(); - SelectionChanged(); + _Do(new MoveDownAction("Move Down", fResourceList, rows)); + break; } case MSG_SELECTION: SelectionChanged(); break; + case MSG_INVOCATION: + { + BRect frame = Frame(); + + new EditWindow(BRect(frame.left + 50, frame.top + 50, + frame.left + 300, frame.top + 350), + (ResourceRow*)fResourceList->CurrentSelection()); + + break; + } + case MSG_SETTINGS_APPLY: + AdaptSettings(); + break; + default: BWindow::MessageReceived(msg); } } +void +MainWindow::AdaptSettings() +{ + fUndoContext->SetLimit(fSettings->UndoLimit); +} + + void MainWindow::_SetTitleFromEntry() { @@ -429,7 +575,7 @@ MainWindow::_Save(BEntry* entry) } } - /*BPath path; + BPath path; entry->GetPath(&path); // I wouldn't use std:: if BFile had cooler stuff. @@ -440,10 +586,10 @@ MainWindow::_Save(BEntry* entry) time_t timeNow = time(0); - out << "/-" << endl; - out << " - This file is auto-generated by Haiku ResourceEdit." << endl; - out << " - Time: " << ctime((const time_t*)&timeNow); - out << " -\" << endl; + out << "/*" << endl; + out << " * This file is auto-generated by Haiku ResourceEdit." << endl; + out << " * Time: " << ctime((const time_t*)&timeNow); + out << " */" << endl; for (int32 i = 0; i < fResourceList->CountRows(); i++) { ResourceRow* row = (ResourceRow*)fResourceList->RowAt(i); @@ -451,20 +597,22 @@ MainWindow::_Save(BEntry* entry) out << endl; out << "resource"; - if (true) { - // TODO: Implement no-ID cases. - + if (row->ResourceStringID()[0] != '\0') { out << "(" << row->ResourceID(); - if (row->ResourceName()[0] != '\0') { - out << ", \"" << row->ResourceName() << "\"" << endl; - } + if (row->ResourceName()[0] != '\0') + out << ", \"" << row->ResourceName() << "\""; - out << ") "; + out << ")"; + } else { + if (row->ResourceName()[0] != '\0') + out << "(\"" << row->ResourceName() << "\")"; } - if (row->ResourceTypeCode()[0] != '\0') - out << "#\'" << row->ResourceTypeCode() << "\' "; + out << " "; + + if (row->ResourceStringCode()[0] != '\0') + out << "#\'" << row->ResourceStringCode() << "\' "; if (strcmp(row->ResourceType(), "raw") != 0) out << row->ResourceType() << ' ' << row->ResourceData(); @@ -475,56 +623,306 @@ MainWindow::_Save(BEntry* entry) out << "}"; } - out << endl; + out << ";" << endl; } - out.close();*/ + out.close(); - // Commented out whole output section. Switching to .rsrc files to - // close Part 1 of GCI task. + // Killed code: Export to .rsrc - // TODO: Implement exporting to .rdef and/or other formats. - - - BFile* file = new BFile(entry, B_READ_WRITE | B_CREATE_FILE); + /*BFile* file = new BFile(entry, B_READ_WRITE | B_CREATE_FILE); BResources output(file, true); delete file; for (int32 i = 0; i < fResourceList->CountRows(); i++) { ResourceRow* row = (ResourceRow*)fResourceList->RowAt(i); - output.AddResource(row->ResourceTypeCode(), row->ResourceID(), + + output.AddResource(row->ResourceCode(), row->ResourceID(), row->ResourceRawData(), row->ResourceSize(), row->ResourceName()); } - output.Sync(); + output.Sync();*/ + + fUnsavedChanges = false; } void MainWindow::_Load() { - /*BPath path; + // CAUTION: Here be dragons. + + // [Initialization phase] + + BPath path; struct stat st; fAssocEntry->GetPath(&path); fAssocEntry->GetStat(&st); int fd = open(path.Path(), 0); + const char* in = (const char*)mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0); - // TODO: Fix stucking bug. - // TODO: Parse data. + // [Setup phase] + + enum { + T_STATE_NORMAL, + T_STATE_COMMENT, + T_STATE_MULTILINE_COMMENT, + T_STATE_STRING, + } t_state = T_STATE_NORMAL; + + char quoteType = '\0'; + + char escChars[256]; + + for (int32 i = 0; i < 256; i++) + escChars[i] = ~(char)0; + + escChars['n'] = '\n'; + escChars['t'] = '\t'; + escChars['r'] = '\r'; + escChars['0'] = '\0'; + escChars['"'] = '\"'; + escChars['\'']= '\''; + + // TODO: Add other escape sequences? + // Multichar escape sequences cannot be resolved with this. + + BString buffer = ""; + BList* tokens = new BList(); + + BList* errors = new BList(); + // Multiple errors are allowed, but currently unused. + + BList* rows = new BList(); + + // [Tokenization phase] for (int32 i = 0; i < st.st_size - 1; i++) { - //... - }*/ + if (t_state == T_STATE_NORMAL) { + if (in[i] == ' ' || in[i] == '\t' || in[i] == '\n' + || in[i] == '\r') { - // Commented out input section. Same reason as above. + if (buffer != "") { + tokens->AddItem(new BString(buffer)); + buffer = ""; + } - // TODO: Implement importing from .rdef and/or other formats. + continue; + } - BFile* file = new BFile(fAssocEntry, B_READ_ONLY); + if (in[i] == ',' || in[i] == ';' || in[i] == '{' || in[i] == '}' + || in[i] == '(' || in[i] == ')') { + if (buffer != "") { + tokens->AddItem(new BString(buffer)); + buffer = in[i]; + tokens->AddItem(new BString(buffer)); + buffer = ""; + } + + continue; + } + + if (in[i] == '"' || in[i] == '\'') { + t_state = T_STATE_STRING; + quoteType = in[i]; + buffer += in[i]; + continue; + } + + if (in[i] == '/') { + if (in[i + 1] == '/') { + t_state = T_STATE_COMMENT; + continue; + } + + if (in[i + 1] == '*') { + t_state = T_STATE_MULTILINE_COMMENT; + continue; + } + } + + buffer += in[i]; + + } else if (t_state == T_STATE_COMMENT) { + if (in[i] == '\n') { + t_state = T_STATE_NORMAL; + continue; + } + } else if (t_state == T_STATE_MULTILINE_COMMENT) { + if (in[i] == '*' && in[i + 1] == '/') { + t_state = T_STATE_NORMAL; + i++; + continue; + } + } else if (t_state == T_STATE_STRING) { + if (in[i] == '\\' && escChars[in[i]] != ~(char)0) { + buffer += escChars[in[i]]; + i++; + continue; + } + + if (in[i] == quoteType) { + buffer += in[i]; + tokens->AddItem(new BString(buffer)); + buffer = ""; + t_state = T_STATE_NORMAL; + continue; + } + + buffer += in[i]; + } else { + // This can't even happen. + } + } + + if (t_state == T_STATE_MULTILINE_COMMENT) + errors->AddItem(new BString( + "Multi-line comment not closed by end of file.")); + else if (t_state == T_STATE_STRING) + errors->AddItem(new BString("String not closed by end of file.")); + else { + // [Parsing phase] + + for (int32 i = 0; i < tokens->CountItems(); i++) { + BString& token = *(BString*)tokens->ItemAt(i); + + if (token == "resource") { + ResourceRow* row = new ResourceRow(); + + token = *(BString*)tokens->ItemAt(++i); + + if (token[0] == '(') { + BList args; + bool wantComma = false; + + while (true) { + token = *(BString*)tokens->ItemAt(++i); + + if (token[0] == ')') + break; + + if (wantComma) { + if (token[0] != ',') { + errors->AddItem(new BString("Expected ','.")); + break; + } + + wantComma = false; + } else { + args.AddItem(tokens->ItemAt(i)); + wantComma = true; + } + } + + if (errors->CountItems() > 0) + break; + + token = *(BString*)tokens->ItemAt(++i); + + if (args.CountItems() > 2) { + errors->AddItem(new BString( + "Too many arguments for resource identifier.")); + break; + } + + if (args.CountItems() >= 1) { + BString& arg = *(BString*)args.ItemAt(0); + + if (arg[0] == '"') { + errors->AddItem(new BString( + "Resource ID cannot be a string.")); + break; + } + + row->SetResourceStringID(arg); + } + + if (args.CountItems() == 2) { + BString& arg = *(BString*)args.ItemAt(1); + + if (arg[0] != '"') { + errors->AddItem(new BString( + "Resource name must be a string.")); + break; + } + + row->SetResourceName(arg); + } + } + + if (token[0] == '#') { + if (token.Length() != 7 + || token[1] != '\'' || token[6] != '\'') { + errors->AddItem(new BString( + "Invalid syntax for resource type-code.")); + break; + } + + BString code; + token.CopyInto(code, 2, 4); + row->SetResourceStringCode(code); + + token = *(BString*)tokens->ItemAt(++i); + } + + if (token[0] == '(') { + BString& type = *(BString*)tokens->ItemAt(++i); + token = *(BString*)tokens->ItemAt(++i); + + if (token[0] != ')') { + errors->AddItem(new BString( + "Expected ')'.")); + break; + } + + row->SetResourceType(type); + } + + } else if (token == "type") { + // TODO: Implement. + } else if (token == "enum") { + // TODO: Implement. + } + } + } + + // [Result phase] + + if (errors->CountItems() > 0) { + for (int32 i = 0; i < errors->CountItems(); i++) { + BString& error = *(BString*)errors->ItemAt(i); + PRINT(("ERROR: %s\n", error.String())); + delete (BString*)tokens->ItemAt(i); + } + + delete errors; + } else { + for (int32 i = 0; i < rows->CountItems(); i++) { + ResourceRow* row = (ResourceRow*)rows->ItemAt(i); + PRINT(("[Resource]\n")); + PRINT(("id = %s\n", row->ResourceStringID())); + PRINT(("name = %s\n", row->ResourceName())); + // ... + PRINT(("\n")); + } + } + + // [Cleanup phase] + + for (int32 i = 0; i < tokens->CountItems(); i++) + delete (BString*)tokens->ItemAt(i); + + delete tokens; + + munmap((void*)in, st.st_size); + + // Killed code: Import from .rsrc + + /*BFile* file = new BFile(fAssocEntry, B_READ_ONLY); BResources input(file); delete file; @@ -538,10 +936,10 @@ MainWindow::_Load() row->SetResourceID(id); row->SetResourceName(name); row->SetResourceSize(size); - row->SetResourceTypeCode(code); + row->SetResourceCode(code); row->SetResourceRawData(input.LoadResource(code, id, &size)); fResourceList->AddRow(row); - } + }*/ } @@ -560,3 +958,255 @@ MainWindow::_NextResourceID() return currentID; } + + +void +MainWindow::_RefreshStats() +{ + const size_t kB = 1024; + const size_t MB = 1024 * 1024; + const size_t GB = 1024 * 1024 * 1024; + + size_t size = 0; + + BString text = ""; + + text << fResourceList->CountRows(); + text << " resources, "; + + for (int32 i = 0; i < fResourceList->CountRows(); i++) { + ResourceRow* row = (ResourceRow*)fResourceList->RowAt(i); + size += row->ResourceSize(); + } + + if (size >= GB) { + text << (double)size / GB; + text << " GB"; + } else if (size >= MB) { + text << (double)size / MB; + text << " MB"; + } else if (size >= kB) { + text << (double)size / kB; + text << " kB"; + } else { + text << size; + text << " bytes"; + } + + fStatsString->SetText(text); +} + + +void +MainWindow::_RefreshUndoRedo() +{ + if (fUndoContext->CanUndo()) { + fUndoItem->SetEnabled(true); + fUndoItem->SetLabel(fUndoContext->UndoLabel().Prepend("Undo ")); + } else { + fUndoItem->SetEnabled(false); + fUndoItem->SetLabel("Undo"); + } + + if (fUndoContext->CanRedo()) { + fRedoItem->SetEnabled(true); + fRedoItem->SetLabel(fUndoContext->RedoLabel().Prepend("Redo ")); + } else { + fRedoItem->SetEnabled(false); + fRedoItem->SetLabel("Redo"); + } +} + + +void +MainWindow::_Do(UndoContext::Action* action) +{ + fUnsavedChanges = true; + fUndoContext->Do(action); + _RefreshStats(); + _RefreshUndoRedo(); +} + + +MainWindow::AddAction::AddAction(const BString& label, + ResourceListView* list, BList* rows) + : + UndoContext::Action(label) +{ + fList = list; + fRows = rows; + fAdded = false; +} + + +MainWindow::AddAction::~AddAction() +{ + if (!fAdded) + for (int32 i = 0; i < fRows->CountItems(); i++) + delete (ResourceRow*)fRows->ItemAt(i); + + delete fRows; +} + + +void +MainWindow::AddAction::Do() +{ + for (int32 i = 0; i < fRows->CountItems(); i++) { + ResourceRow* row = (ResourceRow*)fRows->ItemAt(i); + fList->AddRow(row, row->ActionIndex, row->Parent); + } + + fAdded = true; +} + + +void +MainWindow::AddAction::Undo() +{ + for (int32 i = 0; i < fRows->CountItems(); i++) + fList->RemoveRow((ResourceRow*)fRows->ItemAt(i)); + + fAdded = false; +} + + +MainWindow::RemoveAction::RemoveAction(const BString& label, + ResourceListView* list, BList* rows) + : + UndoContext::Action(label) +{ + fList = list; + fRows = rows; + fRemoved = false; +} + + +MainWindow::RemoveAction::~RemoveAction() +{ + if (fRemoved) + for (int32 i = 0; i < fRows->CountItems(); i++) + delete (ResourceRow*)fRows->ItemAt(i); + + delete fRows; +} + + +void +MainWindow::RemoveAction::Do() +{ + for (int32 i = 0; i < fRows->CountItems(); i++) + fList->RemoveRow((ResourceRow*)fRows->ItemAt(i)); + + fRemoved = true; +} + + +void +MainWindow::RemoveAction::Undo() +{ + for (int32 i = 0; i < fRows->CountItems(); i++) { + ResourceRow* row = (ResourceRow*)fRows->ItemAt(i); + + fList->AddRow(row, row->ActionIndex, row->Parent); + } + + fRemoved = false; +} + +// TODO: Implement EditAction + +MainWindow::MoveUpAction::MoveUpAction(const BString& label, + ResourceListView* list, BList* rows) + : + UndoContext::Action(label) +{ + fList = list; + fRows = rows; +} + + +MainWindow::MoveUpAction::~MoveUpAction() +{ + delete fRows; +} + + +void +MainWindow::MoveUpAction::Do() +{ + for (int32 i = 0; i < fRows->CountItems(); i++) { + ResourceRow* row = (ResourceRow*)fRows->ItemAt(i); + + fList->SwapRows(row->ActionIndex, row->ActionIndex - 1, + row->Parent, row->Parent); + + row->ActionIndex--; + } + + fList->SelectionChanged(); +} + + +void +MainWindow::MoveUpAction::Undo() +{ + for (int32 i = fRows->CountItems() - 1; i >= 0; i--) { + ResourceRow* row = (ResourceRow*)fRows->ItemAt(i); + + fList->SwapRows(row->ActionIndex, row->ActionIndex + 1, + row->Parent, row->Parent); + + row->ActionIndex++; + } + + fList->SelectionChanged(); +} + +MainWindow::MoveDownAction::MoveDownAction(const BString& label, + ResourceListView* list, BList* rows) + : + UndoContext::Action(label) +{ + fList = list; + fRows = rows; +} + + +MainWindow::MoveDownAction::~MoveDownAction() +{ + delete fRows; +} + + +void +MainWindow::MoveDownAction::Do() +{ + for (int32 i = fRows->CountItems() - 1; i >= 0; i--) { + ResourceRow* row = (ResourceRow*)fRows->ItemAt(i); + + fList->SwapRows(row->ActionIndex, row->ActionIndex + 1, + row->Parent, row->Parent); + + row->ActionIndex++; + } + + fList->SelectionChanged(); +} + + +void +MainWindow::MoveDownAction::Undo() +{ + for (int32 i = 0; i < fRows->CountItems(); i++) { + ResourceRow* row = (ResourceRow*)fRows->ItemAt(i); + + fList->SwapRows(row->ActionIndex, row->ActionIndex - 1, + row->Parent, row->Parent); + + row->ActionIndex--; + } + + fList->SelectionChanged(); +} + diff --git a/src/apps/resourceedit/MainWindow.h b/src/apps/resourceedit/MainWindow.h index bc1523fa35..b903e1ef7a 100644 --- a/src/apps/resourceedit/MainWindow.h +++ b/src/apps/resourceedit/MainWindow.h @@ -6,12 +6,17 @@ #define MAIN_WINDOW_H +#include "UndoContext.h" + #include class ImageButton; +class ResourceListView; +class ResourceRow; +class SettingsFile; -class BColumnListView; +class BBox; class BEntry; class BFilePanel; class BMenu; @@ -20,20 +25,30 @@ class BMenuField; class BMenuItem; class BMessage; class BPopUpMenu; +class BStringView; class BTextControl; class MainWindow : public BWindow { public: - MainWindow(BRect frame, BEntry* entry); + MainWindow(BRect frame, BEntry* entry, SettingsFile* settings); ~MainWindow(); bool QuitRequested(); + void MouseDown(BPoint point); void MessageReceived(BMessage* msg); void SelectionChanged(); + void AdaptSettings(); + private: BEntry* fAssocEntry; + SettingsFile* fSettings; + + BFilePanel* fSavePanel; + bool fUnsavedChanges; + + UndoContext* fUndoContext; BMenuBar* fMenuBar; @@ -56,6 +71,10 @@ private: BMenuItem* fClearItem; BMenuItem* fSelectAllItem; + BMenu* fToolsMenu; + BMenuItem* fAddAppResourcesItem; + BMenuItem* fSettingsItem; + BMenu* fHelpMenu; BTextControl* fResourceIDText; @@ -68,9 +87,9 @@ private: ImageButton* fMoveUpButton; ImageButton* fMoveDownButton; - BColumnListView* fResourceList; - - BFilePanel* fSavePanel; + ResourceListView* fResourceList; + BBox* fStatsBox; + BStringView* fStatsString; void _SetTitleFromEntry(); void _SaveAs(); @@ -79,6 +98,88 @@ private: int32 _NextResourceID(); + void _RefreshStats(); + void _RefreshUndoRedo(); + void _Do(UndoContext::Action* action); + + class AddAction : public UndoContext::Action { + public: + AddAction(const BString& label, + ResourceListView* list, BList* rows); + ~AddAction(); + + void Do(); + void Undo(); + + private: + ResourceListView* fList; + BList* fRows; + bool fAdded; + + }; + + class RemoveAction : public UndoContext::Action { + public: + RemoveAction(const BString& label, + ResourceListView* list, BList* rows); + ~RemoveAction(); + + void Do(); + void Undo(); + + private: + ResourceListView* fList; + BList* fRows; + bool fRemoved; + + }; + + class EditAction : public UndoContext::Action { + public: + EditAction(const BString& label, + ResourceListView* list, + ResourceRow* rowold, ResourceRow* rownew); + ~EditAction(); + + void Do(); + void Undo(); + + private: + ResourceListView* fList; + ResourceRow* fRowOld; + ResourceRow* fRowNew; + + }; + + class MoveUpAction : public UndoContext::Action { + public: + MoveUpAction(const BString& label, + ResourceListView* list, BList* rows); + ~MoveUpAction(); + + void Do(); + void Undo(); + + private: + ResourceListView* fList; + BList* fRows; + + }; + + class MoveDownAction : public UndoContext::Action { + public: + MoveDownAction(const BString& label, + ResourceListView* list, BList* rows); + ~MoveDownAction(); + + void Do(); + void Undo(); + + private: + ResourceListView* fList; + BList* fRows; + + }; }; diff --git a/src/apps/resourceedit/ResourceEdit.cpp b/src/apps/resourceedit/ResourceEdit.cpp index 2ff1a577a4..977e463797 100644 --- a/src/apps/resourceedit/ResourceEdit.cpp +++ b/src/apps/resourceedit/ResourceEdit.cpp @@ -9,6 +9,8 @@ #include "AboutWindow.h" #include "Constants.h" #include "MainWindow.h" +#include "SettingsFile.h" +#include "SettingsWindow.h" #include #include @@ -23,6 +25,11 @@ ResourceEdit::ResourceEdit() fOpenPanel = new BFilePanel(B_OPEN_PANEL, &be_app_messenger, NULL, 0, true, new BMessage(MSG_OPEN_DONE)); + + fSettings = new SettingsFile("resourceedit_settings"); + fSettings->Load(); + + fSettingsWindow = NULL; } @@ -68,11 +75,35 @@ ResourceEdit::MessageReceived(BMessage* msg) } case MSG_SAVEALL: { - for (int32 i = 0; i < fWindowList.CountItems(); i++) - ((MainWindow*)fWindowList.ItemAt(i))->PostMessage(MSG_SAVE); + for (int32 i = 0; i < fWindowList.CountItems(); i++) { + MainWindow* window = ((MainWindow*)fWindowList.ItemAt(i)); + window->PostMessage(MSG_SAVE); + } break; } + case MSG_SETTINGS: + { + if (fSettingsWindow != NULL) + fSettingsWindow->Activate(); + else + fSettingsWindow = new SettingsWindow(fSettings); + + break; + } + case MSG_SETTINGS_APPLY: + { + for (int32 i = 0; i < fWindowList.CountItems(); i++) { + MainWindow* window = ((MainWindow*)fWindowList.ItemAt(i)); + window->PostMessage(MSG_SETTINGS_APPLY); + } + + break; + } + case MSG_SETTINGS_CLOSED: + fSettingsWindow = NULL; + break; + default: BApplication::MessageReceived(msg); } @@ -98,7 +129,7 @@ ResourceEdit::ReadyToRun() void ResourceEdit::_CreateWindow(BEntry* assocEntry) { - MainWindow* window = new MainWindow(_Cascade(), assocEntry); + MainWindow* window = new MainWindow(_Cascade(), assocEntry, fSettings); fWindowList.AddItem(window); diff --git a/src/apps/resourceedit/ResourceEdit.h b/src/apps/resourceedit/ResourceEdit.h index dcdf976cff..6168fcfc2c 100644 --- a/src/apps/resourceedit/ResourceEdit.h +++ b/src/apps/resourceedit/ResourceEdit.h @@ -10,6 +10,8 @@ class MainWindow; +class SettingsFile; +class SettingsWindow; class BEntry; class BFilePanel; @@ -30,6 +32,9 @@ private: BFilePanel* fOpenPanel; + SettingsFile* fSettings; + SettingsWindow* fSettingsWindow; + void ArgvReceived(int32 argc, char* argv[]); void ReadyToRun(); diff --git a/src/apps/resourceedit/ResourceEdit.rdef b/src/apps/resourceedit/ResourceEdit.rdef index 58b821c357..c225980220 100644 --- a/src/apps/resourceedit/ResourceEdit.rdef +++ b/src/apps/resourceedit/ResourceEdit.rdef @@ -16,7 +16,7 @@ resource app_version { resource app_flags B_SINGLE_LAUNCH; -resource(1, "BEOS:FILE_TYPES") message { +resource file_types message { "types" = "text/x-vnd.Be.ResourceDef" }; diff --git a/src/apps/resourceedit/ResourceListView.cpp b/src/apps/resourceedit/ResourceListView.cpp index a329d77ca6..654de4420b 100644 --- a/src/apps/resourceedit/ResourceListView.cpp +++ b/src/apps/resourceedit/ResourceListView.cpp @@ -19,7 +19,7 @@ ResourceListView::ResourceListView(BRect rect, const char* name, BColumnListView(rect, name, resizingMode, drawFlags, border, showHorizontalScrollbar) { - + //SetMouseTrackingEnabled(true); } @@ -29,11 +29,19 @@ ResourceListView::~ResourceListView() } +void +ResourceListView::MouseDown(BPoint point) +{ + PRINT(("MouseDown()")); +} + + void ResourceListView::MessageReceived(BMessage* msg) { switch (msg->what) { - case B_SIMPLE_DATA: { + case B_SIMPLE_DATA: + { entry_ref ref; int32 n = 0; diff --git a/src/apps/resourceedit/ResourceListView.h b/src/apps/resourceedit/ResourceListView.h index 5551f82922..88657f9376 100644 --- a/src/apps/resourceedit/ResourceListView.h +++ b/src/apps/resourceedit/ResourceListView.h @@ -16,6 +16,7 @@ public: bool showHorizontalScrollbar = true); ~ResourceListView(); + void MouseDown(BPoint point); void MessageReceived(BMessage* msg); private: diff --git a/src/apps/resourceedit/ResourceRow.cpp b/src/apps/resourceedit/ResourceRow.cpp index ebe5dce9ea..ecf94f709c 100644 --- a/src/apps/resourceedit/ResourceRow.cpp +++ b/src/apps/resourceedit/ResourceRow.cpp @@ -9,14 +9,17 @@ #include #include +#include + ResourceRow::ResourceRow() : BRow() { - fRawData = NULL; + Parent = NULL; + ActionIndex = -1; - SetField(new BIntegerField(0), 0); + SetField(new BStringField(""), 0); SetField(new BStringField(""), 1); SetField(new BStringField(""), 2); SetField(new BStringField(""), 3); @@ -34,7 +37,14 @@ ResourceRow::~ResourceRow() void ResourceRow::SetResourceID(int32 id) { - ((BIntegerField*)GetField(0))->SetValue(id); + ((BStringField*)GetField(0))->SetString((BString() << id).String()); +} + + +void +ResourceRow::SetResourceStringID(const char* id) +{ + ((BStringField*)GetField(0))->SetString(id); } @@ -53,14 +63,22 @@ ResourceRow::SetResourceType(const char* type) void -ResourceRow::SetResourceTypeCode(type_code code) +ResourceRow::SetResourceCode(type_code code) { - fTypeCode = code; - TypeCodeToString(code, fTypeString); + fCode = code; + ResourceType::CodeToString(code, fTypeString); ((BStringField*)GetField(3))->SetString(fTypeString); } +void +ResourceRow::SetResourceStringCode(const char* code) +{ + fCode = ResourceType::StringToCode(code); + ((BStringField*)GetField(3))->SetString(code); +} + + void ResourceRow::SetResourceData(const char* data) { @@ -68,23 +86,6 @@ ResourceRow::SetResourceData(const char* data) } -void -ResourceRow::SetResourceRawData(const void* data) -{ - if (data == NULL) - data = kDefaultData; - - fRawData = data; - - int32 ix = FindTypeCodeIndex(ResourceTypeCode()); - - if (ix == -1) - SetResourceData("[Unknown Data]"); - else - SetResourceData(kDefaultTypes[ix].toString(fRawData)); -} - - void ResourceRow::SetResourceSize(off_t size) { @@ -95,7 +96,18 @@ ResourceRow::SetResourceSize(off_t size) int32 ResourceRow::ResourceID() { - return ((BIntegerField*)GetField(0))->Value(); + const char* strID = ResourceStringID(); + + // TODO: Check whether is numeric and resolve if not. + + return atoi(strID); +} + + +const char* +ResourceRow::ResourceStringID() +{ + return ((BStringField*)GetField(0))->String(); } @@ -114,9 +126,16 @@ ResourceRow::ResourceType() type_code -ResourceRow::ResourceTypeCode() +ResourceRow::ResourceCode() { - return fTypeCode; + return fCode; +} + + +const char* +ResourceRow::ResourceStringCode() +{ + return ((BStringField*)GetField(3))->String(); } @@ -127,13 +146,6 @@ ResourceRow::ResourceData() } -const void* -ResourceRow::ResourceRawData() -{ - return fRawData; -} - - off_t ResourceRow::ResourceSize() { diff --git a/src/apps/resourceedit/ResourceRow.h b/src/apps/resourceedit/ResourceRow.h index a9e65caa0e..26d3660ff9 100644 --- a/src/apps/resourceedit/ResourceRow.h +++ b/src/apps/resourceedit/ResourceRow.h @@ -17,24 +17,27 @@ public: ~ResourceRow(); void SetResourceID(int32 id); + void SetResourceStringID(const char* id); void SetResourceName(const char* name); void SetResourceType(const char* type); - void SetResourceTypeCode(type_code code); + void SetResourceCode(type_code code); + void SetResourceStringCode(const char* code); void SetResourceData(const char* data); - void SetResourceRawData(const void*); void SetResourceSize(off_t size); int32 ResourceID(); + const char* ResourceStringID(); const char* ResourceName(); const char* ResourceType(); - type_code ResourceTypeCode(); + type_code ResourceCode(); + const char* ResourceStringCode(); const char* ResourceData(); - const void* ResourceRawData(); off_t ResourceSize(); + ResourceRow* Parent; + int32 ActionIndex; private: - const void* fRawData; - type_code fTypeCode; + type_code fCode; char fTypeString[8]; }; diff --git a/src/apps/resourceedit/SettingsFile.cpp b/src/apps/resourceedit/SettingsFile.cpp new file mode 100644 index 0000000000..63e84b5d9d --- /dev/null +++ b/src/apps/resourceedit/SettingsFile.cpp @@ -0,0 +1,56 @@ +/* + * Copyright 2012-2013 Tri-Edge AI + * All rights reserved. Distributed under the terms of the MIT license. + */ + + +#include "SettingsFile.h" + + +SettingsFile::SettingsFile(const char* name) +{ + find_directory(B_USER_SETTINGS_DIRECTORY, &fPath); + fPath.Append(name, true); +} + + +SettingsFile::~SettingsFile() +{ + +} + + +void +SettingsFile::Defaults() +{ + UndoLimit = 100; +} + + +void +SettingsFile::Load() +{ + fFile = new BFile(fPath.Path(), B_READ_ONLY); + + if (fFile->InitCheck() == B_OK) { + fFile->Read(&UndoLimit, sizeof(UndoLimit)); + // TODO: Add more settings here (2/3). + } else + Defaults(); + + delete fFile; +} + + +void +SettingsFile::Save() +{ + fFile = new BFile(fPath.Path(), B_WRITE_ONLY | B_CREATE_FILE); + + if (fFile->InitCheck() == B_OK) { + fFile->Write(&UndoLimit, sizeof(UndoLimit)); + // TODO: Add more settings here (3/3). + } + + delete fFile; +} diff --git a/src/apps/resourceedit/SettingsFile.h b/src/apps/resourceedit/SettingsFile.h new file mode 100644 index 0000000000..2c52232b4b --- /dev/null +++ b/src/apps/resourceedit/SettingsFile.h @@ -0,0 +1,33 @@ +/* + * Copyright 2012-2013 Tri-Edge AI + * All rights reserved. Distributed under the terms of the MIT license. + */ +#ifndef SETTINGS_FILE_H +#define SETTINGS_FILE_H + + +#include +#include +#include + + +class SettingsFile +{ +public: + int32 UndoLimit; + // TODO: Add more settings here (1/3). + + SettingsFile(const char* name); + ~SettingsFile(); + + void Defaults(); + void Load(); + void Save(); + +private: + BPath fPath; + BFile* fFile; +}; + + +#endif diff --git a/src/apps/resourceedit/SettingsWindow.cpp b/src/apps/resourceedit/SettingsWindow.cpp new file mode 100644 index 0000000000..9817659cb9 --- /dev/null +++ b/src/apps/resourceedit/SettingsWindow.cpp @@ -0,0 +1,120 @@ +/* + * Copyright 2012-2013 Tri-Edge AI + * All rights reserved. Distributed under the terms of the MIT license. + */ + + +#include "SettingsWindow.h" + +#include "Constants.h" +#include "GenericSettingsView.h" +#include "SettingsFile.h" + +#include +#include +#include +#include +#include +#include +#include + + +SettingsWindow::SettingsWindow(SettingsFile* settings) + : + BWindow(BRect(200, 150, 600, 450), "Settings", B_TITLED_WINDOW, B_NOT_RESIZABLE) +{ + fSettings = settings; + + BRect bounds = Bounds(); + + fBackView = new BView(bounds, "fBackView", B_FOLLOW_ALL, 0); + fBackView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + + fListView = new BListView(BRect(8, 8, 100 + 8, bounds.bottom - 8), + "fListView", B_SINGLE_SELECTION_LIST, B_FOLLOW_ALL); + + // TODO: Implement selecting different categories of settings. + // fListView->SetSelectionMessage(new BMessage(...)); + + fListView->AddItem(new BStringItem("Generic")); + fListView->Select(0); + + fScrollView = new BScrollView("fScrollView", fListView, B_FOLLOW_TOP_BOTTOM, + B_WILL_DRAW | B_FRAME_EVENTS, false, true); + + fGenericSettingsView = new GenericSettingsView( + BRect(132, 8, bounds.right - 8, bounds.bottom - 8 - 40), + "fGenericSettingsView", fSettings); + // TODO: Add more settings views (2/4). + + fRevertButton = new BButton(BRect(bounds.right - 152, bounds.bottom - 32, + bounds.right - 88, bounds.bottom - 8), + "fRevertButton", "Revert", + new BMessage(MSG_SETTINGS_REVERT)); + + fApplyButton = new BButton(BRect(bounds.right - 72, bounds.bottom - 32, + bounds.right - 8, bounds.bottom - 8), "fApplyButton", "Apply", + new BMessage(MSG_SETTINGS_APPLY)); + + AdaptSettings(); + + fBackView->AddChild(fScrollView); + fBackView->AddChild(fGenericSettingsView); + fBackView->AddChild(fRevertButton); + fBackView->AddChild(fApplyButton); + AddChild(fBackView); + + Show(); +} + + +SettingsWindow::~SettingsWindow() +{ + +} + + +bool +SettingsWindow::QuitRequested() +{ + be_app->PostMessage(MSG_SETTINGS_CLOSED); + return true; +} + +void +SettingsWindow::MessageReceived(BMessage* msg) +{ + switch (msg->what) + { + case MSG_SETTINGS_APPLY: + { + ApplySettings(); + fSettings->Save(); + be_app->PostMessage(MSG_SETTINGS_APPLY); + break; + } + case MSG_SETTINGS_REVERT: + { + AdaptSettings(); + fSettings->Save(); + be_app->PostMessage(MSG_SETTINGS_APPLY); + break; + } + default: + BWindow::MessageReceived(msg); + } +} + +void +SettingsWindow::ApplySettings() +{ + fGenericSettingsView->ApplySettings(); + // TODO: Add more settings views (3/4). +} + +void +SettingsWindow::AdaptSettings() +{ + fGenericSettingsView->AdaptSettings(); + // TODO: Add more settings views (4/4). +} diff --git a/src/apps/resourceedit/SettingsWindow.h b/src/apps/resourceedit/SettingsWindow.h new file mode 100644 index 0000000000..da015de5bf --- /dev/null +++ b/src/apps/resourceedit/SettingsWindow.h @@ -0,0 +1,48 @@ +/* + * Copyright 2012-2013 Tri-Edge AI + * All rights reserved. Distributed under the terms of the MIT license. + */ +#ifndef SETTINGS_WINDOW_H +#define SETTINGS_WINDOW_H + + +#include + + +class GenericSettingsView; +class SettingsFile; + +class BButton; +class BListView; +class BScrollView; +class BView; + + +class SettingsWindow : public BWindow { +public: + SettingsWindow(SettingsFile* settings); + ~SettingsWindow(); + + bool QuitRequested(); + void MessageReceived(BMessage* msg); + + void ApplySettings(); + void AdaptSettings(); + +private: + SettingsFile* fSettings; + + BView* fBackView; + BListView* fListView; + BScrollView* fScrollView; + + GenericSettingsView* fGenericSettingsView; + // TODO: Add more settings (1/4). + + BButton* fRevertButton; + BButton* fApplyButton; + +}; + + +#endif diff --git a/src/apps/resourceedit/edits/AppFlagsEdit.cpp b/src/apps/resourceedit/edits/AppFlagsEdit.cpp new file mode 100644 index 0000000000..5a1482533a --- /dev/null +++ b/src/apps/resourceedit/edits/AppFlagsEdit.cpp @@ -0,0 +1,4 @@ +/* + * Copyright 2012-2013 Tri-Edge AI + * All rights reserved. Distributed under the terms of the MIT license. + */ diff --git a/src/apps/resourceedit/edits/AppFlagsEdit.h b/src/apps/resourceedit/edits/AppFlagsEdit.h new file mode 100644 index 0000000000..5a1482533a --- /dev/null +++ b/src/apps/resourceedit/edits/AppFlagsEdit.h @@ -0,0 +1,4 @@ +/* + * Copyright 2012-2013 Tri-Edge AI + * All rights reserved. Distributed under the terms of the MIT license. + */ diff --git a/src/apps/resourceedit/edits/BooleanEdit.cpp b/src/apps/resourceedit/edits/BooleanEdit.cpp new file mode 100644 index 0000000000..bf65a9335e --- /dev/null +++ b/src/apps/resourceedit/edits/BooleanEdit.cpp @@ -0,0 +1,71 @@ +/* + * Copyright 2012-2013 Tri-Edge AI + * All rights reserved. Distributed under the terms of the MIT license. + */ + + +#include "NormalEdit.h" +#include "ResourceRow.h" + +#include +#include +#include + + +BooleanEdit::BooleanEdit() + : + EditView("BooleanEdit") +{ + +} + + +BooleanEdit::~BooleanEdit() +{ + +} + + +void +BooleanEdit::AttachTo(BView* view) +{ + EditView::AttachTo(view); + + SetLayout(new BGroupLayout(B_VERTICAL)); + + fValueCheck = new BCheckBox(BRect(0, 0, 0, 0), "fValueText", + "", NULL); + + AddChild(BGroupLayoutBuilder(B_VERTICAL, 0) + .Add(fValueCheck) + .AddGlue() + ); + + view->AddChild(this); +} + + +void +BooleanEdit::Edit(ResourceRow* row) +{ + EditView::Edit(row); + + BString data = fRow->ResourceData(); + + if (data == "" || data == "0" || data == "false") + fValueCheck->SetValue(B_CONTROL_OFF); + else + fValueCheck->SetValue(B_CONTROL_ON); +} + + +void +BooleanEdit::Commit() +{ + EditView::Commit(); + + if (fValueCheck->Value() == B_CONTROL_ON) + fRow->SetResourceData("true"); + else + fRow->SetResourceData("false"); +} diff --git a/src/apps/resourceedit/edits/BooleanEdit.h b/src/apps/resourceedit/edits/BooleanEdit.h new file mode 100644 index 0000000000..53889992bb --- /dev/null +++ b/src/apps/resourceedit/edits/BooleanEdit.h @@ -0,0 +1,30 @@ +/* + * Copyright 2012-2013 Tri-Edge AI + * All rights reserved. Distributed under the terms of the MIT license. + */ +#ifndef BOOLEAN_EDIT_H +#define BOOLEAN_EDIT_H + + +#include "EditView.h" + + +class BCheckBox; + + +class BooleanEdit : public EditView { +public: + BooleanEdit(); + ~BooleanEdit(); + + void AttachTo(BView* view); + void Edit(ResourceRow* row); + void Commit(); + +private: + BCheckBox* fValueCheck; + +}; + + +#endif diff --git a/src/apps/resourceedit/edits/EditView.cpp b/src/apps/resourceedit/edits/EditView.cpp new file mode 100644 index 0000000000..dc9861aeb4 --- /dev/null +++ b/src/apps/resourceedit/edits/EditView.cpp @@ -0,0 +1,52 @@ +/* + * Copyright 2012-2013 Tri-Edge AI + * All rights reserved. Distributed under the terms of the MIT license. + */ + + +#include "EditView.h" + + +EditView::EditView(const char* name) + : + BView(BRect(0, 0, 0, 0), name, 0, 0) +{ + // Implemented by subclasses. +} + + +EditView::~EditView() +{ + // Implemented by subclasses. +} + + +void +EditView::AttachTo(BView* view) +{ + while (true) { + BView* child = ChildAt(0); + + if (child == NULL) + break; + + child->RemoveSelf(); + } + + // Implemented by subclasses. +} + + +void +EditView::Edit(ResourceRow* row) +{ + fRow = row; + // Implemented by subclasses. +} + + +void +EditView::Commit() +{ + // Implemented by subclasses. +} diff --git a/src/apps/resourceedit/edits/EditView.h b/src/apps/resourceedit/edits/EditView.h new file mode 100644 index 0000000000..23aca74036 --- /dev/null +++ b/src/apps/resourceedit/edits/EditView.h @@ -0,0 +1,31 @@ +/* + * Copyright 2012-2013 Tri-Edge AI + * All rights reserved. Distributed under the terms of the MIT license. + */ +#ifndef EDIT_VIEW_H +#define EDIT_VIEW_H + + +#include + + +class ResourceRow; + + +class EditView : public BView { +public: + EditView(const char* name); + virtual ~EditView(); + + virtual void AttachTo(BView* view); + virtual void Edit(ResourceRow* row); + virtual void Commit(); + +protected: + ResourceRow* fRow; + +}; + + +#endif + diff --git a/src/apps/resourceedit/edits/NormalEdit.cpp b/src/apps/resourceedit/edits/NormalEdit.cpp new file mode 100644 index 0000000000..fa822515bf --- /dev/null +++ b/src/apps/resourceedit/edits/NormalEdit.cpp @@ -0,0 +1,64 @@ +/* + * Copyright 2012-2013 Tri-Edge AI + * All rights reserved. Distributed under the terms of the MIT license. + */ + + +#include "NormalEdit.h" +#include "ResourceRow.h" + +#include +#include +#include + + +NormalEdit::NormalEdit() + : + EditView("NormalEdit") +{ + +} + + +NormalEdit::~NormalEdit() +{ + +} + + +void +NormalEdit::AttachTo(BView* view) +{ + EditView::AttachTo(view); + + SetLayout(new BGroupLayout(B_VERTICAL)); + + fValueText = new BTextControl(BRect(0, 0, 0, 0), "fValueText", + "Value:", "", NULL); + fValueText->SetDivider(50); + + AddChild(BGroupLayoutBuilder(B_VERTICAL, 0) + .Add(fValueText) + .AddGlue() + ); + + view->AddChild(this); +} + + +void +NormalEdit::Edit(ResourceRow* row) +{ + EditView::Edit(row); + + fValueText->SetText(fRow->ResourceData()); +} + + +void +NormalEdit::Commit() +{ + EditView::Commit(); + + fRow->SetResourceData(fValueText->Text()); +} diff --git a/src/apps/resourceedit/edits/NormalEdit.h b/src/apps/resourceedit/edits/NormalEdit.h new file mode 100644 index 0000000000..ea5fe78e09 --- /dev/null +++ b/src/apps/resourceedit/edits/NormalEdit.h @@ -0,0 +1,31 @@ +/* + * Copyright 2012-2013 Tri-Edge AI + * All rights reserved. Distributed under the terms of the MIT license. + */ +#ifndef NORMAL_EDIT_H +#define NORMAL_EDIT_H + + +#include "EditView.h" + + +class BTextControl; + +// TODO: Templatize this class and rename to NumericEdit. +//template +class NormalEdit : public EditView { +public: + NormalEdit(); + ~NormalEdit(); + + void AttachTo(BView* view); + void Edit(ResourceRow* row); + void Commit(); + +private: + BTextControl* fValueText; + +}; + + +#endif diff --git a/src/apps/resourceedit/ImageButton.cpp b/src/apps/resourceedit/interface/ImageButton.cpp similarity index 100% rename from src/apps/resourceedit/ImageButton.cpp rename to src/apps/resourceedit/interface/ImageButton.cpp diff --git a/src/apps/resourceedit/ImageButton.h b/src/apps/resourceedit/interface/ImageButton.h similarity index 100% rename from src/apps/resourceedit/ImageButton.h rename to src/apps/resourceedit/interface/ImageButton.h diff --git a/src/apps/resourceedit/settings/GenericSettingsView.cpp b/src/apps/resourceedit/settings/GenericSettingsView.cpp new file mode 100644 index 0000000000..65d3377b6c --- /dev/null +++ b/src/apps/resourceedit/settings/GenericSettingsView.cpp @@ -0,0 +1,60 @@ +/* + * Copyright 2012-2013 Tri-Edge AI + * All rights reserved. Distributed under the terms of the MIT license. + */ + + +#include "GenericSettingsView.h" + +#include "SettingsFile.h" + +#include +#include +#include +#include + +#include + + +GenericSettingsView::GenericSettingsView(BRect frame, const char* name, + SettingsFile* settings, uint32 resizingMode, uint32 flags) + : + BView(frame, name, resizingMode, flags) +{ + fSettings = settings; + + SetLayout(new BGroupLayout(B_VERTICAL)); + + fUndoLimitText = new BTextControl(BRect(0, 0, 0, 0), "fUndoLimitText", + "Undo Limit:", NULL, NULL); + fUndoLimitText->SetDivider(100); + + // TODO: Add more controls for generic settings (2/4). + + AddChild(BGroupLayoutBuilder(B_VERTICAL, 8) + .Add(fUndoLimitText) + .AddGlue() + ); +} + + +GenericSettingsView::~GenericSettingsView() +{ + +} + + +void +GenericSettingsView::ApplySettings() +{ + fSettings->UndoLimit = atoi(fUndoLimitText->Text()); + // TODO: Add more controls for generic settings (3/4). +} + + +void +GenericSettingsView::AdaptSettings() +{ + fUndoLimitText->SetText(BString() << fSettings->UndoLimit); + // TODO: Add more controls for generic settings (4/4). +} diff --git a/src/apps/resourceedit/settings/GenericSettingsView.h b/src/apps/resourceedit/settings/GenericSettingsView.h new file mode 100644 index 0000000000..47d141127a --- /dev/null +++ b/src/apps/resourceedit/settings/GenericSettingsView.h @@ -0,0 +1,37 @@ +/* + * Copyright 2012-2013 Tri-Edge AI + * All rights reserved. Distributed under the terms of the MIT license. + */ +#ifndef GENERIC_SETTINGS_VIEW_H +#define GENERIC_SETTINGS_VIEW_H + + +#include + + +class SettingsFile; + +class BTextControl; + + +class GenericSettingsView : public BView { +public: + GenericSettingsView(BRect frame, const char* name, + SettingsFile* settings, + uint32 resizingMode = B_FOLLOW_ALL, + uint32 flags = 0); + ~GenericSettingsView(); + + void ApplySettings(); + void AdaptSettings(); + +private: + SettingsFile* fSettings; + + BTextControl* fUndoLimitText; + // TODO: Add more controls for generic settings (1/4). + +}; + + +#endif diff --git a/src/apps/resourceedit/support/UndoContext.cpp b/src/apps/resourceedit/support/UndoContext.cpp new file mode 100644 index 0000000000..c4f6775b2d --- /dev/null +++ b/src/apps/resourceedit/support/UndoContext.cpp @@ -0,0 +1,175 @@ +/* + * Copyright 2012-2013 Tri-Edge AI + * All rights reserved. Distributed under the terms of the MIT license. + */ + + +#include "UndoContext.h" + +#include "Constants.h" + +#include +#include + + +UndoContext::Action::Action(const BString& label) +{ + fLabel = label; +} + + +UndoContext::Action::~Action() +{ + +} + + +void +UndoContext::Action::Do() +{ + +} + + +void +UndoContext::Action::Undo() +{ + +} + + +void +UndoContext::Action::SetLabel(const BString& label) +{ + fLabel = label; +} + + +BString +UndoContext::Action::Label() const +{ + return fLabel; +} + + +UndoContext::UndoContext() +{ + fAt = 0; + fLimit = 3; + fHistory = new BList(); +} + + +UndoContext::~UndoContext() +{ + for (int32 i = 0; i < fHistory->CountItems(); i++) + delete (Action*)fHistory->ItemAt(i); + + delete fHistory; +} + + +void +UndoContext::SetLimit(int32 limit) +{ + int32 delta = fLimit - limit; + + if (limit > 1) + fLimit = limit; + else + limit = 1; + + if (delta > 0) { + for (int32 i = 0; i < delta; i++) + delete (Action*)fHistory->ItemAt(i); + + fHistory->RemoveItems(0, delta); + + if (fAt > fLimit) + fAt = fLimit; + } +} + + +int32 +UndoContext::Limit() const +{ + return fLimit; +} + + +void +UndoContext::Do(UndoContext::Action* action) +{ + int32 count = fHistory->CountItems(); + + if (fAt >= fLimit) + delete (Action*)fHistory->RemoveItem((int32)0); + else { + for (int32 i = fAt; i < count; i++) + delete (Action*)fHistory->ItemAt(i); + + fHistory->RemoveItems(fAt, count - fAt); + + fAt++; + } + + fHistory->AddItem(action); + + action->Do(); +} + + +void +UndoContext::Undo() +{ + if (!CanUndo()) + return; + + fAt--; + ((Action*)fHistory->ItemAt(fAt))->Undo(); +} + + +void +UndoContext::Redo() +{ + if (!CanRedo()) + return; + + ((Action*)fHistory->ItemAt(fAt))->Do(); + fAt++; +} + + +bool +UndoContext::CanUndo() const +{ + return fAt > 0; +} + + +bool +UndoContext::CanRedo() const +{ + return fAt < fHistory->CountItems(); +} + + +BString +UndoContext::UndoLabel() const +{ + if (CanUndo()) + return ((Action*)fHistory->ItemAt(fAt - 1))->Label(); + else + return ""; +} + +BString +UndoContext::RedoLabel() const +{ + if (CanRedo()) + return ((Action*)fHistory->ItemAt(fAt))->Label(); + else + return ""; +} diff --git a/src/apps/resourceedit/support/UndoContext.h b/src/apps/resourceedit/support/UndoContext.h new file mode 100644 index 0000000000..0146e1be48 --- /dev/null +++ b/src/apps/resourceedit/support/UndoContext.h @@ -0,0 +1,55 @@ +/* + * Copyright 2012-2013 Tri-Edge AI + * All rights reserved. Distributed under the terms of the MIT license. + */ +#ifndef UNDO_CONTEXT_H +#define UNDO_CONTEXT_H + + +#include +#include + + +class UndoContext { +public: + class Action { + public: + Action(const BString& label); + virtual ~Action(); + + virtual void Do(); + virtual void Undo(); + + void SetLabel(const BString& label); + BString Label() const; + + private: + BString fLabel; + }; + + UndoContext(); + ~UndoContext(); + + void SetLimit(int32 limit); + int32 Limit() const; + + void Do(Action* action); + + void Undo(); + void Redo(); + + bool CanUndo() const; + bool CanRedo() const; + + BString UndoLabel() const; + BString RedoLabel() const; + +private: + int32 fAt; + int32 fLimit; + BList* fHistory; + +}; + + +#endif From 9590a81c9cd728292b2770b4a08aaeea1f589ed6 Mon Sep 17 00:00:00 2001 From: Matt Madia Date: Thu, 28 Feb 2013 17:03:27 -0500 Subject: [PATCH 017/104] GCC 4 build fix. Suggested by leavengood. Closes #968. --- src/apps/resourceedit/MainWindow.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/apps/resourceedit/MainWindow.cpp b/src/apps/resourceedit/MainWindow.cpp index 1a04e8c132..ae04c01af8 100644 --- a/src/apps/resourceedit/MainWindow.cpp +++ b/src/apps/resourceedit/MainWindow.cpp @@ -759,8 +759,8 @@ MainWindow::_Load() continue; } } else if (t_state == T_STATE_STRING) { - if (in[i] == '\\' && escChars[in[i]] != ~(char)0) { - buffer += escChars[in[i]]; + if (in[i] == '\\' && escChars[(int)in[i]] != ~(char)0) { + buffer += escChars[(int)in[i]]; i++; continue; } From 79dd1ff2af8c74dbf10bec9b3bba82b1a6207e75 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Fri, 1 Mar 2013 01:47:00 +0000 Subject: [PATCH 018/104] iprowifi4965: Re-add working wlan card pciid * Centrino Advanced-N 6235 * Originally introduced in hrev44579 * Likely removed in last wlan driver sync * Confirmed working 100% * Upstream bug: http://www.freebsd.org/cgi/query-pr.cgi?pr=173898 --- .../kernel/drivers/network/wlan/iprowifi4965/dev/iwn/if_iwn.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/dev/iwn/if_iwn.c b/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/dev/iwn/if_iwn.c index 4ae4191617..53efcb5077 100644 --- a/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/dev/iwn/if_iwn.c +++ b/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/dev/iwn/if_iwn.c @@ -89,6 +89,7 @@ static const struct iwn_ident iwn_ident_table[] = { { 0x8086, 0x008b, "Intel Centrino Wireless-N 1030" }, { 0x8086, 0x0090, "Intel Centrino Advanced-N 6230" }, { 0x8086, 0x0091, "Intel Centrino Advanced-N 6230" }, + { 0x8086, 0x088e, "Intel Centrino Advanced-N 6235" }, { 0x8086, 0x0885, "Intel Centrino Wireless-N + WiMAX 6150" }, { 0x8086, 0x0886, "Intel Centrino Wireless-N + WiMAX 6150" }, { 0x8086, 0x0896, "Intel Centrino Wireless-N 130" }, From 9741a1b5b0f0d155700817c84f629a6d477172f0 Mon Sep 17 00:00:00 2001 From: Niels Sascha Reedijk Date: Sat, 2 Mar 2013 06:23:44 +0100 Subject: [PATCH 019/104] Update translations from Pootle --- data/catalogs/apps/drivesetup/de.catkeys | 3 +- data/catalogs/apps/drivesetup/fr.catkeys | 5 ++- data/catalogs/apps/launchbox/de.catkeys | 3 +- data/catalogs/apps/launchbox/hu.catkeys | 3 +- data/catalogs/apps/launchbox/ja.catkeys | 3 +- data/catalogs/apps/launchbox/sv.catkeys | 3 +- data/catalogs/apps/webpositive/de.catkeys | 7 +++- data/catalogs/apps/webpositive/hu.catkeys | 7 +++- data/catalogs/apps/webpositive/ja.catkeys | 37 +++++++++++--------- data/catalogs/apps/webpositive/sv.catkeys | 7 +++- data/catalogs/preferences/network/de.catkeys | 7 +++- data/catalogs/preferences/network/hu.catkeys | 7 +++- data/catalogs/preferences/network/ja.catkeys | 7 +++- data/catalogs/preferences/network/sv.catkeys | 7 +++- 14 files changed, 77 insertions(+), 29 deletions(-) diff --git a/data/catalogs/apps/drivesetup/de.catkeys b/data/catalogs/apps/drivesetup/de.catkeys index c190fb327c..0626b1f558 100644 --- a/data/catalogs/apps/drivesetup/de.catkeys +++ b/data/catalogs/apps/drivesetup/de.catkeys @@ -1,4 +1,4 @@ -1 german x-vnd.Haiku-DriveSetup 3977871021 +1 german x-vnd.Haiku-DriveSetup 3775412465 DriveSetup System name Datenträgerverwaltung Cancel AbstractParametersPanel Abbrechen Delete MainWindow Löschen @@ -63,6 +63,7 @@ Continue MainWindow Weiter Cannot delete the selected partition. MainWindow Gewählte Partition konnte nicht gelöscht werden. Mount all MainWindow Alle einhängen End: %s Support Ende: %s +The panel could not return successfully. MainWindow Das Fenster meldete sich nicht mehr zurück. Cancel MainWindow Abbrechen Delete partition MainWindow Partition löschen Are you sure you want to change parameters of the selected partition?\n\nThe partition may no longer be recognized by other operating systems anymore! MainWindow Sollen die Parameter der ausgewählten Partition wirklich geändert werden?\n\nAndere Betriebssysteme können die Partition unter Umständen nicht mehr erkennen! diff --git a/data/catalogs/apps/drivesetup/fr.catkeys b/data/catalogs/apps/drivesetup/fr.catkeys index 03662b085b..b459f00aeb 100644 --- a/data/catalogs/apps/drivesetup/fr.catkeys +++ b/data/catalogs/apps/drivesetup/fr.catkeys @@ -1,11 +1,14 @@ -1 french x-vnd.Haiku-DriveSetup 659039073 +1 french x-vnd.Haiku-DriveSetup 1767229522 DriveSetup System name Gestionnaire de disque +Cancel AbstractParametersPanel Annuler Delete MainWindow Supprimer Are you sure you want to write the changes back to disk now?\n\nAll data on the selected partition will be irretrievably lost if you do so! MainWindow Êtes-vous sûr de vouloir écrire les changements sur le disque ?\n\nToutes les données de la partition sélectionnée seront effacées si vous le faites ! Rescan MainWindow Analyser OK MainWindow OK Could not aquire partitioning information. MainWindow Impossible de récupérer les informations sur les partitions. There's no space on the partition where a child partition could be created. MainWindow Il n'y a pas de place dans cette partition pour créer une partition fille. +Initialize InitializeParametersPanel Initialiser +OK AbstractParametersPanel OK PartitionList Unable to find the selected partition by ID. MainWindow Impossible de trouver la partition sélectionnée par son ID. Select a partition from the list below. DiskView Sélectionnez une partition dans la liste ci-dessous. diff --git a/data/catalogs/apps/launchbox/de.catkeys b/data/catalogs/apps/launchbox/de.catkeys index 574dd880a6..89412eb866 100644 --- a/data/catalogs/apps/launchbox/de.catkeys +++ b/data/catalogs/apps/launchbox/de.catkeys @@ -1,4 +1,4 @@ -1 german x-vnd.Haiku-LaunchBox 3016105370 +1 german x-vnd.Haiku-LaunchBox 3692177981 New LaunchBox Neu Set description… LaunchBox Beschreibung ändern… Vertical layout LaunchBox Vertikale Anordnung @@ -6,6 +6,7 @@ OK LaunchBox OK Pad 1 LaunchBox Block 1 last chance LaunchBox letzte Chance Quit LaunchBox Beenden +Open containing folder LaunchBox Speicherort öffnen Clear button LaunchBox Feld leeren LaunchBox System name LaunchBox Ignore double-click LaunchBox Doppelklick ignorieren diff --git a/data/catalogs/apps/launchbox/hu.catkeys b/data/catalogs/apps/launchbox/hu.catkeys index 8624590250..0eab8e1a16 100644 --- a/data/catalogs/apps/launchbox/hu.catkeys +++ b/data/catalogs/apps/launchbox/hu.catkeys @@ -1,4 +1,4 @@ -1 hungarian x-vnd.Haiku-LaunchBox 3016105370 +1 hungarian x-vnd.Haiku-LaunchBox 3692177981 New LaunchBox Új Set description… LaunchBox Leírás… Vertical layout LaunchBox Függőleges elrendezés @@ -6,6 +6,7 @@ OK LaunchBox Rendben Pad 1 LaunchBox 1. tálca last chance LaunchBox utolsó esély Quit LaunchBox Kilépés +Open containing folder LaunchBox Tartalmazó mappa megnyitása Clear button LaunchBox Gomb kiürítése LaunchBox System name Indítósáv Ignore double-click LaunchBox Dupla kattintás figyelmen kívül hagyása diff --git a/data/catalogs/apps/launchbox/ja.catkeys b/data/catalogs/apps/launchbox/ja.catkeys index 136fced848..61ec830123 100644 --- a/data/catalogs/apps/launchbox/ja.catkeys +++ b/data/catalogs/apps/launchbox/ja.catkeys @@ -1,4 +1,4 @@ -1 japanese x-vnd.Haiku-LaunchBox 3016105370 +1 japanese x-vnd.Haiku-LaunchBox 3692177981 New LaunchBox 新規作成 Set description… LaunchBox 説明の作成… Vertical layout LaunchBox 垂直配置 @@ -6,6 +6,7 @@ OK LaunchBox OK Pad 1 LaunchBox パッド 1 last chance LaunchBox 最後のチャンス Quit LaunchBox 終了 +Open containing folder LaunchBox フォルダーを開く Clear button LaunchBox ボタンを消去 LaunchBox System name ランチャー Ignore double-click LaunchBox ダブルクリックを無視する diff --git a/data/catalogs/apps/launchbox/sv.catkeys b/data/catalogs/apps/launchbox/sv.catkeys index b2464136fd..a723f9e4d7 100644 --- a/data/catalogs/apps/launchbox/sv.catkeys +++ b/data/catalogs/apps/launchbox/sv.catkeys @@ -1,4 +1,4 @@ -1 swedish x-vnd.Haiku-LaunchBox 3016105370 +1 swedish x-vnd.Haiku-LaunchBox 3692177981 New LaunchBox Ny Set description… LaunchBox Ange beskrivning... Vertical layout LaunchBox Vertikal utformning @@ -6,6 +6,7 @@ OK LaunchBox OK Pad 1 LaunchBox Block 1 last chance LaunchBox sista chansen Quit LaunchBox Avsluta +Open containing folder LaunchBox Öppna innehållande mapp Clear button LaunchBox Rensa knapp LaunchBox System name StartBlock Ignore double-click LaunchBox Ignorera dubbelklick diff --git a/data/catalogs/apps/webpositive/de.catkeys b/data/catalogs/apps/webpositive/de.catkeys index 634635f628..0b35527229 100644 --- a/data/catalogs/apps/webpositive/de.catkeys +++ b/data/catalogs/apps/webpositive/de.catkeys @@ -1,4 +1,4 @@ -1 german x-vnd.Haiku-WebPositive 233049275 +1 german x-vnd.Haiku-WebPositive 3577331897 Show home button Settings Window Home-Symbol anzeigen Username: Authentication Panel Benutzername: Copy URL to clipboard Download Window Adresse kopieren @@ -16,6 +16,7 @@ Start page: Settings Window Startseite: History WebPositive Window Verlauf Error opening downloads folder Download Window Fehler beim Öffnen des Download-Ordners Paste WebPositive Window Einfügen +Proxy username: Settings Window Proxy-Nutzername: Settings Settings Window Einstellungen %seconds seconds left Download Window Noch %seconds Sekunden Confirmation WebPositive Window Bestätigung @@ -41,6 +42,7 @@ Quit WebPositive Window Beenden Full screen WebPositive Window Vollbild Open download error Download Window Fehler beim Öffnen Standard font: Settings Window Standardschrift: +Find previous occurrence of search terms WebPositive Window find bar previous button tooltip Vorheriger Treffer Restart Download Window Neustart Proxy server Settings Window Proxy-Server Open containing folder Download Window Speicherort öffnen @@ -58,6 +60,7 @@ Cut WebPositive Window Ausschneiden Bookmark this page WebPositive Window Lesezeichen für diese Seite anlegen There was an error trying to show the Bookmarks folder.\n\nError: %error WebPositive Window Don't translate variable %error Der Lesezeichen-Ordner kann nicht angezeigt werden.\n\nFehler: %error Open downloads folder Download Window Download-Ordner öffnen +Proxy password: Settings Window Proxy-Passwort: Number of days to keep links in History menu: Settings Window Anzahl der Tage im Verlauf-Menü: Hide Download Window Ausblenden Reset size WebPositive Window Größe zurücksetzen @@ -67,6 +70,7 @@ There was an error retrieving the bookmark folder.\n\nError: %error WebPositive Over 1 day left Download Window Noch über einen Tag Downloads WebPositive Window Downloads Requesting %url WebPositive Window %url wird angefordert +Find next occurrence of search terms WebPositive Window find bar next button tooltip Nächster Treffer Apply Settings Window Anwenden Bookmark info WebPositive Window Lesezeichen Info Size: Font Selection view Größe: @@ -80,6 +84,7 @@ Open blank page Settings Window Leere Seite öffnen New tabs: Settings Window Neue Reiter: Cancel WebPositive Window Abbrechen Open all WebPositive Window Alle öffnen +Proxy server requires authentication Settings Window Der Proxy-Server verlangt eine Authentifizierung Clear URL Bar Leeren Cut URL Bar Ausschneiden Clear WebPositive Window Leeren diff --git a/data/catalogs/apps/webpositive/hu.catkeys b/data/catalogs/apps/webpositive/hu.catkeys index 26a74725e8..1d6c6f88b2 100644 --- a/data/catalogs/apps/webpositive/hu.catkeys +++ b/data/catalogs/apps/webpositive/hu.catkeys @@ -1,4 +1,4 @@ -1 hungarian x-vnd.Haiku-WebPositive 233049275 +1 hungarian x-vnd.Haiku-WebPositive 3577331897 Show home button Settings Window Kezdőlap-gomb megjelenítése Username: Authentication Panel Felhasználónév: Copy URL to clipboard Download Window Cím másolása a vágólapra @@ -16,6 +16,7 @@ Start page: Settings Window Kezdőlap: History WebPositive Window Előzmény Error opening downloads folder Download Window Hiba történt a letöltések mappa megnyitásakor Paste WebPositive Window Beillesztés +Proxy username: Settings Window Felhasználónév a proxyhoz: Settings Settings Window Beállítások %seconds seconds left Download Window %seconds másodperc van hátra Confirmation WebPositive Window Megerősítés @@ -41,6 +42,7 @@ Quit WebPositive Window Kilépés Full screen WebPositive Window Teljes képernyő Open download error Download Window A letöltés nem nyitható meg Standard font: Settings Window Normál betűtípus: +Find previous occurrence of search terms WebPositive Window find bar previous button tooltip Előző találat Restart Download Window Újraindítás Proxy server Settings Window Proxy Open containing folder Download Window Tartalmazó mappa megnyitása @@ -58,6 +60,7 @@ Cut WebPositive Window Kivágás Bookmark this page WebPositive Window Könyvjelző az oldalhoz There was an error trying to show the Bookmarks folder.\n\nError: %error WebPositive Window Don't translate variable %error Hiba történt a Könyvjelzők mappa megjelenítésekor.\n\nHiba: %error Open downloads folder Download Window A letöltési mappa megnyitása +Proxy password: Settings Window Jelszó a proxyhoz: Number of days to keep links in History menu: Settings Window Előzmények megtartásának ideje (nap): Hide Download Window Elrejtés Reset size WebPositive Window Méret visszaállítása @@ -67,6 +70,7 @@ There was an error retrieving the bookmark folder.\n\nError: %error WebPositive Over 1 day left Download Window Több, mint 1 nap van hátra Downloads WebPositive Window Letöltések Requesting %url WebPositive Window %url megnyitása +Find next occurrence of search terms WebPositive Window find bar next button tooltip Következő találat Apply Settings Window Alkalmaz Bookmark info WebPositive Window Könyvjelző információi Size: Font Selection view Méret: @@ -80,6 +84,7 @@ Open blank page Settings Window Üres oldal megnyitása New tabs: Settings Window Új fülek: Cancel WebPositive Window Mégse Open all WebPositive Window Az összes megnyitása +Proxy server requires authentication Settings Window A proxy hitelesítést kér Clear URL Bar Törlés Cut URL Bar Kivágás Clear WebPositive Window Törlés diff --git a/data/catalogs/apps/webpositive/ja.catkeys b/data/catalogs/apps/webpositive/ja.catkeys index bd247f7e8d..66881f1190 100644 --- a/data/catalogs/apps/webpositive/ja.catkeys +++ b/data/catalogs/apps/webpositive/ja.catkeys @@ -1,4 +1,4 @@ -1 japanese x-vnd.Haiku-WebPositive 233049275 +1 japanese x-vnd.Haiku-WebPositive 3577331897 Show home button Settings Window ホームボタンを表示する Username: Authentication Panel ユーザー名: Copy URL to clipboard Download Window URL をクリップボードにコピー @@ -16,6 +16,7 @@ Start page: Settings Window スタートページ: History WebPositive Window 履歴 Error opening downloads folder Download Window ダウンロードフォルダーを開く際にエラーが発生しました Paste WebPositive Window 貼り付け +Proxy username: Settings Window ユーザー名: Settings Settings Window 設定 %seconds seconds left Download Window 残り %seconds 秒 Confirmation WebPositive Window 確認 @@ -41,6 +42,7 @@ Quit WebPositive Window 終了 Full screen WebPositive Window 全画面表示 Open download error Download Window ダウンロードを開く際にエラー Standard font: Settings Window 標準フォント: +Find previous occurrence of search terms WebPositive Window find bar previous button tooltip 文字列を前方へ検索 Restart Download Window 再開 Proxy server Settings Window プロキシサーバー Open containing folder Download Window ファイルのフォルダーを開く @@ -48,38 +50,41 @@ New window WebPositive Window 新規ウィンドウ Open Download Window 開く Reload WebPositive Window 再読み込み Downloads Download Window ダウンロード -Sans serif font: Settings Window サンセリフフォント: +Sans serif font: Settings Window サンセリフフォント: Over %days days left Download Window 残り %days 日以上 Forward WebPositive Window 進む of Download Window ...as in '12kB of 256kB' / Revert Settings Window 元に戻す -Fixed font: Settings Window 固定幅フォント: +Fixed font: Settings Window 固定幅フォント: Cut WebPositive Window 切り取り Bookmark this page WebPositive Window このページをブックマーク There was an error trying to show the Bookmarks folder.\n\nError: %error WebPositive Window Don't translate variable %error ブックマークフォルダーを表示しようとした時にエラーが発生しました。\n\nエラー: %error Open downloads folder Download Window ダウンロードフォルダーを開く -Number of days to keep links in History menu: Settings Window 履歴メニューにリンクを残す日数: +Proxy password: Settings Window パスワード: +Number of days to keep links in History menu: Settings Window 履歴メニューにリンクを残す日数: Hide Download Window 隠す Reset size WebPositive Window サイズをリセット -Find: WebPositive Window 検索: +Find: WebPositive Window 検索: Increase size WebPositive Window サイズを大きく -There was an error retrieving the bookmark folder.\n\nError: %error WebPositive Window Don't translate the variable %error ブックマークフォルダーの取得時にエラーが発生しました。\n\nエラー: %error +There was an error retrieving the bookmark folder.\n\nError: %error WebPositive Window Don't translate the variable %error ブックマークフォルダーの取得時にエラーが発生しました。\n\nエラー: %error Over 1 day left Download Window 残り 1 日以上 Downloads WebPositive Window ダウンロード Requesting %url WebPositive Window 要求中 %url +Find next occurrence of search terms WebPositive Window find bar next button tooltip 文字列を後方へ検索 Apply Settings Window 適用 Bookmark info WebPositive Window ブックマーク情報 -Size: Font Selection view サイズ: +Size: Font Selection view サイズ: Show tabs if only one page is open Settings Window ページが一つだけ開いている場合もタブを表示する。 About WebPositive Window WebPositive について -Finish: Download Window Finishing time 完了: +Finish: Download Window Finishing time 完了: Fonts Settings Window フォント OK Download Window OK Page source error WebPositive Window ページソースのエラー Open blank page Settings Window 空白のページを開く -New tabs: Settings Window 新しいタブ: +New tabs: Settings Window 新しいタブ: Cancel WebPositive Window 中止 Open all WebPositive Window すべて開く +Proxy server requires authentication Settings Window プロキシサーバーは認証を必要 Clear URL Bar クリア Cut URL Bar 切り取り Clear WebPositive Window クリア @@ -87,8 +92,8 @@ Remove Download Window 削除 Find WebPositive Window 検索 Find previous WebPositive Window 前を検索 Settings WebPositive Window 設定 -Proxy server address: Settings Window プロキシサーバーのアドレス: -Proxy server port: Settings Window プロキシサーバーポート: +Proxy server address: Settings Window プロキシサーバーのアドレス: +Proxy server port: Settings Window プロキシサーバーポート: Bookmarks WebPositive Window ブックマーク %minutes minutes Download Window %minutes 分 Paste URL Bar 貼り付け @@ -100,7 +105,7 @@ Open start page Settings Window スタートページを開く Continue downloads WebPositive ダウンロードを続ける Cancel Download Window 中止 Open search page Settings Window 検索ページを開く -Password: Authentication Panel パスワード: +Password: Authentication Panel パスワード: Back WebPositive Window 戻る New browser window Download Window 新規ブラウザウィンドウ Today WebPositive Window 今日 @@ -108,17 +113,17 @@ Today WebPositive Window 今日 Remember username and password for this site Authentication Panel このサイトのユーザー名とパスワードを記憶する Earlier WebPositive Window 6 日以上前 Authentication required Authentication Panel 認証が必要です -Use proxy server to connect to the internet Settings Window インターネット接続にプロキシーサーバーを使用する。 +Use proxy server to connect to the internet Settings Window インターネット接続にプロキシサーバーを使用する。 There are still downloads in progress, do you really want to quit WebPositive now? WebPositive ダウンロードが進行中です。WebPositive を今終了してもよいですか? Auto-hide interface in full screen mode Settings Window 全画面表示時に自動的にインターフェイスを隠す。 %url failed WebPositive Window Loading URL failed. Don't translate variable %url. %url 失敗。 New tab WebPositive Window 新規タブ Downloads in progress WebPositive ダウンロードが進行中です -Style: Font Selection view スタイル: +Style: Font Selection view スタイル: General Settings Window 一般 View WebPositive Window 表示 Previous WebPositive Window 前へ -There was an error creating the bookmark file.\n\nError: %error WebPositive Window Don't translate variable %error ブックマークファイルの作成中にエラーが発生しました。\n\nエラー: %error +There was an error creating the bookmark file.\n\nError: %error WebPositive Window Don't translate variable %error ブックマークファイルの作成中にエラーが発生しました。\n\nエラー: %error Bookmark error WebPositive Window ブックマークエラー Do you really want to clear the browsing history? WebPositive Window 本当にブラウズ履歴をクリアしますか? Copy WebPositive Window コピー @@ -131,6 +136,6 @@ Copy URL Bar コピー OK WebPositive Window OK Manage bookmarks WebPositive Window ブックマークの管理 A bookmark for this page (%bookmarkName) already exists. WebPositive Window Don't translate variable %bookmarkName このページ (%bookmarkName) のブックマークはすでにあります。 -New windows: Settings Window 新規ウィンドウ: +New windows: Settings Window 新規ウィンドウ: %url finished WebPositive Window Loading URL finished. Don't translate variable %url. %url 完了。 Remove finished Download Window Remove finished diff --git a/data/catalogs/apps/webpositive/sv.catkeys b/data/catalogs/apps/webpositive/sv.catkeys index ce2d8d97ec..6d084cf973 100644 --- a/data/catalogs/apps/webpositive/sv.catkeys +++ b/data/catalogs/apps/webpositive/sv.catkeys @@ -1,4 +1,4 @@ -1 swedish x-vnd.Haiku-WebPositive 233049275 +1 swedish x-vnd.Haiku-WebPositive 3577331897 Show home button Settings Window Visa hem-knappen Username: Authentication Panel Användarnamn: Copy URL to clipboard Download Window Kopiera URL till urklipp @@ -16,6 +16,7 @@ Start page: Settings Window Start sida: History WebPositive Window Historik Error opening downloads folder Download Window Fel vid öppnande av nerladdnings foldern Paste WebPositive Window Klistra in +Proxy username: Settings Window Proxyanvändarnamn: Settings Settings Window Inställningar %seconds seconds left Download Window %seconds secunder kvar Confirmation WebPositive Window Bekräftelse @@ -41,6 +42,7 @@ Quit WebPositive Window Avsluta Full screen WebPositive Window Helskärm Open download error Download Window Öppna nerladdnings error Standard font: Settings Window Standardtypsnitt: +Find previous occurrence of search terms WebPositive Window find bar previous button tooltip Sök föregående förekomst av söktermerna Restart Download Window Starta om Proxy server Settings Window Proxyserver Open containing folder Download Window Öppna innehållande mapp @@ -58,6 +60,7 @@ Cut WebPositive Window Klipp ut Bookmark this page WebPositive Window Spara sidan som bokmärke There was an error trying to show the Bookmarks folder.\n\nError: %error WebPositive Window Don't translate variable %error Problem att visa Bokmärkes mappen.\n\nFel: %error Open downloads folder Download Window Öppna nerladdningsmapp +Proxy password: Settings Window Proxylösenord: Number of days to keep links in History menu: Settings Window Antal dagar att bevara länkar i Historia menyn: Hide Download Window Dölj Reset size WebPositive Window Återställ storlek @@ -67,6 +70,7 @@ There was an error retrieving the bookmark folder.\n\nError: %error WebPositive Over 1 day left Download Window Över 1 dag kvar Downloads WebPositive Window Nerladdningar Requesting %url WebPositive Window Begär %url +Find next occurrence of search terms WebPositive Window find bar next button tooltip Sök nästa förekomst av söktermerna Apply Settings Window Tillämpa Bookmark info WebPositive Window Bokmärksinformation Size: Font Selection view Storlek: @@ -80,6 +84,7 @@ Open blank page Settings Window Öppna blank sida New tabs: Settings Window Ny flik Cancel WebPositive Window Avbryt Open all WebPositive Window Öppna alla +Proxy server requires authentication Settings Window Proxyservern kräver behörighetskontroll Clear URL Bar Töm Cut URL Bar Klipp ut Clear WebPositive Window Töm diff --git a/data/catalogs/preferences/network/de.catkeys b/data/catalogs/preferences/network/de.catkeys index 4dc531d6e4..fe143ac3c3 100644 --- a/data/catalogs/preferences/network/de.catkeys +++ b/data/catalogs/preferences/network/de.catkeys @@ -1,22 +1,27 @@ -1 german x-vnd.Haiku-Network 365183238 +1 german x-vnd.Haiku-Network 1341378870 Choose automatically EthernetSettingsView Automatisch auswählen Gateway: EthernetSettingsView Gateway: Netmask: EthernetSettingsView Netzmaske: DHCP EthernetSettingsView DHCP DNS #2: EthernetSettingsView DNS #2: Apply EthernetSettingsView Anwenden +Netmask is invalid EthernetSettingsView Ungültige Netzmaske OK EthernetSettingsView OK DNS #1: EthernetSettingsView DNS #1: IP address: EthernetSettingsView IP-Adresse: Adapter: EthernetSettingsView Adapter: Domain: EthernetSettingsView Domäne: +Gateway is invalid EthernetSettingsView Ungültiges Gateway +DNS #1 is invalid EthernetSettingsView Ungültiger DNS #1 Revert EthernetSettingsView Anfangswerte EthernetSettingsView Network System name Netzwerk Mode: EthernetSettingsView Modus: +IP address is invalid EthernetSettingsView Ungültige IP-Adresse Network: EthernetSettingsView Netzwerk: The net_server needs to run for the auto configuration! EthernetSettingsView Zur Auto-Konfiguration muss der net_server laufen! Disabled EthernetSettingsView Deaktiviert Auto-configuring failed: EthernetSettingsView Auto-Konfiguration fehlgeschlagen: Static EthernetSettingsView Statisch +DNS #2 is invalid EthernetSettingsView Ungültiger DNS #2 EthernetSettingsView diff --git a/data/catalogs/preferences/network/hu.catkeys b/data/catalogs/preferences/network/hu.catkeys index d4ebca8532..0e8b4b07f8 100644 --- a/data/catalogs/preferences/network/hu.catkeys +++ b/data/catalogs/preferences/network/hu.catkeys @@ -1,22 +1,27 @@ -1 hungarian x-vnd.Haiku-Network 365183238 +1 hungarian x-vnd.Haiku-Network 1341378870 Choose automatically EthernetSettingsView Automatikus választás Gateway: EthernetSettingsView Átjáró: Netmask: EthernetSettingsView Hálózati maszk: DHCP EthernetSettingsView DHCP (automatikus) DNS #2: EthernetSettingsView DNS #2: Apply EthernetSettingsView Alkalmaz +Netmask is invalid EthernetSettingsView Az alhálózati maszk érvénytelen OK EthernetSettingsView Rendben DNS #1: EthernetSettingsView DNS #1: IP address: EthernetSettingsView IP-cím: Adapter: EthernetSettingsView Hálózati kártya: Domain: EthernetSettingsView Tartomány: +Gateway is invalid EthernetSettingsView Az átjáró érvénytelen +DNS #1 is invalid EthernetSettingsView Az elsődleges DNS érvénytelen Revert EthernetSettingsView Visszaállít EthernetSettingsView Network System name Hálózat Mode: EthernetSettingsView Beállítás: +IP address is invalid EthernetSettingsView Az IP-cím érvénytelen Network: EthernetSettingsView Hálózat: The net_server needs to run for the auto configuration! EthernetSettingsView A net_servernek futnia kell az automatikus beállításokhoz! Disabled EthernetSettingsView Letiltva Auto-configuring failed: EthernetSettingsView Az automatikus beállítás nem sikerült: Static EthernetSettingsView Állandó (kézi) +DNS #2 is invalid EthernetSettingsView A másodlagos DNS érvénytelen EthernetSettingsView diff --git a/data/catalogs/preferences/network/ja.catkeys b/data/catalogs/preferences/network/ja.catkeys index b3e99571d8..fbfceee648 100644 --- a/data/catalogs/preferences/network/ja.catkeys +++ b/data/catalogs/preferences/network/ja.catkeys @@ -1,22 +1,27 @@ -1 japanese x-vnd.Haiku-Network 365183238 +1 japanese x-vnd.Haiku-Network 1341378870 Choose automatically EthernetSettingsView 自動選択 Gateway: EthernetSettingsView ゲートウェイ: Netmask: EthernetSettingsView サブネットマスク: DHCP EthernetSettingsView 自動 (DHCP) DNS #2: EthernetSettingsView セカンダリ DNS サーバー: Apply EthernetSettingsView 適用 +Netmask is invalid EthernetSettingsView ネットマスクが正しくありません OK EthernetSettingsView Ok DNS #1: EthernetSettingsView プライマリ DNS サーバー: IP address: EthernetSettingsView IP アドレス: Adapter: EthernetSettingsView ネットワークアダプター: Domain: EthernetSettingsView ドメイン: +Gateway is invalid EthernetSettingsView ゲートウェイが正しくありません +DNS #1 is invalid EthernetSettingsView DNS #1 が正しくありません Revert EthernetSettingsView 元に戻す EthernetSettingsView <ワイヤレスネットワークが見つかりません> Network System name ネットワーク Mode: EthernetSettingsView モード: +IP address is invalid EthernetSettingsView IP アドレスが正しくありません Network: EthernetSettingsView ネットワーク: The net_server needs to run for the auto configuration! EthernetSettingsView 自動設定するには net_server が起動している必要があります! Disabled EthernetSettingsView 無効 Auto-configuring failed: EthernetSettingsView 自動設定に失敗しました: Static EthernetSettingsView 固定 IP +DNS #2 is invalid EthernetSettingsView DNS #2 が正しくありません EthernetSettingsView <アダプターがありません> diff --git a/data/catalogs/preferences/network/sv.catkeys b/data/catalogs/preferences/network/sv.catkeys index dd2db321a1..c7ac241b60 100644 --- a/data/catalogs/preferences/network/sv.catkeys +++ b/data/catalogs/preferences/network/sv.catkeys @@ -1,22 +1,27 @@ -1 swedish x-vnd.Haiku-Network 365183238 +1 swedish x-vnd.Haiku-Network 1341378870 Choose automatically EthernetSettingsView Välj automatiskt Gateway: EthernetSettingsView Gateway: Netmask: EthernetSettingsView Nätmask: DHCP EthernetSettingsView DHCP DNS #2: EthernetSettingsView Sekundär DNS: Apply EthernetSettingsView Använd +Netmask is invalid EthernetSettingsView Nätmasken är felaktig OK EthernetSettingsView Ok DNS #1: EthernetSettingsView Primär DNS: IP address: EthernetSettingsView IP-adress: Adapter: EthernetSettingsView Nätverkskort: Domain: EthernetSettingsView Domän: +Gateway is invalid EthernetSettingsView Gateway är ogiltig +DNS #1 is invalid EthernetSettingsView DNS #1 är ogiltig Revert EthernetSettingsView Återställ EthernetSettingsView Network System name Nätverk Mode: EthernetSettingsView Konfiguration: +IP address is invalid EthernetSettingsView IP-adressen är felaktig Network: EthernetSettingsView Nätverk: The net_server needs to run for the auto configuration! EthernetSettingsView Automatisk konfiguration kan inte ske utan att net_server körs! Disabled EthernetSettingsView Inaktiverad Auto-configuring failed: EthernetSettingsView Automatisk konfiguration misslyckades: Static EthernetSettingsView Statisk +DNS #2 is invalid EthernetSettingsView DNS #2 är ogiltig EthernetSettingsView From e381b02559509041a056831116044e5cc1b0b3e4 Mon Sep 17 00:00:00 2001 From: Tri-Edge AI Date: Sun, 16 Dec 2012 19:11:54 +0200 Subject: [PATCH 020/104] Bluetooth: Added settings to remember last used device. Signed-off-by: Matt Madia --- src/preferences/bluetooth/BluetoothMain.cpp | 2 +- .../bluetooth/BluetoothSettings.cpp | 56 ++++++ src/preferences/bluetooth/BluetoothSettings.h | 37 ++++ .../bluetooth/BluetoothSettingsView.cpp | 160 +++++++++++++----- .../bluetooth/BluetoothSettingsView.h | 51 +++--- src/preferences/bluetooth/BluetoothWindow.cpp | 1 - src/preferences/bluetooth/BluetoothWindow.h | 27 ++- .../bluetooth/ExtendedLocalDeviceView.cpp | 10 +- src/preferences/bluetooth/Jamfile | 1 + 9 files changed, 257 insertions(+), 88 deletions(-) create mode 100644 src/preferences/bluetooth/BluetoothSettings.cpp create mode 100644 src/preferences/bluetooth/BluetoothSettings.h diff --git a/src/preferences/bluetooth/BluetoothMain.cpp b/src/preferences/bluetooth/BluetoothMain.cpp index 0b71630b3f..3451ecb656 100644 --- a/src/preferences/bluetooth/BluetoothMain.cpp +++ b/src/preferences/bluetooth/BluetoothMain.cpp @@ -77,7 +77,7 @@ BluetoothApplication::MessageReceived(BMessage* message) BMessageRunner::StartSending(be_app_messenger, new BMessage('Xtmp'), 2 * 1000000, 1); } else { - fWindow = new BluetoothWindow(BRect(100, 100, 550, 420)); + fWindow = new BluetoothWindow(BRect(100, 100, 750, 420)); fWindow->Show(); } break; diff --git a/src/preferences/bluetooth/BluetoothSettings.cpp b/src/preferences/bluetooth/BluetoothSettings.cpp new file mode 100644 index 0000000000..ad6680ca59 --- /dev/null +++ b/src/preferences/bluetooth/BluetoothSettings.cpp @@ -0,0 +1,56 @@ +/* + * Copyright 2008-2009, Oliver Ruiz Dorantes, + * Copyright 2012-2013, Tri-Edge AI + * + * All rights reserved. Distributed under the terms of the MIT license. + */ + +#include "BluetoothSettings.h" + +BluetoothSettings::BluetoothSettings() +{ + find_directory(B_USER_SETTINGS_DIRECTORY, &fPath); + fPath.Append("Bluetooth_settings", true); +} + + +BluetoothSettings::~BluetoothSettings() +{ + +} + + +void +BluetoothSettings::Defaults() +{ + Data.PickedDevice = bdaddrUtils::NullAddress(); +} + + +void +BluetoothSettings::Load() +{ + fFile = new BFile(fPath.Path(), B_READ_ONLY); + + if (fFile->InitCheck() == B_OK) { + fFile->Read(&Data, sizeof(Data)); + // TODO: Add more settings here. + } else + Defaults(); + + delete fFile; +} + + +void +BluetoothSettings::Save() +{ + fFile = new BFile(fPath.Path(), B_WRITE_ONLY | B_CREATE_FILE); + + if (fFile->InitCheck() == B_OK) { + fFile->Write(&Data, sizeof(Data)); + // TODO: Add more settings here. + } + + delete fFile; +} diff --git a/src/preferences/bluetooth/BluetoothSettings.h b/src/preferences/bluetooth/BluetoothSettings.h new file mode 100644 index 0000000000..b04041006f --- /dev/null +++ b/src/preferences/bluetooth/BluetoothSettings.h @@ -0,0 +1,37 @@ +/* + * Copyright 2008-2009, Oliver Ruiz Dorantes, + * Copyright 2012-2013, Tri-Edge AI + * + * All rights reserved. Distributed under the terms of the MIT license. + */ + +#ifndef BLUETOOTH_SETTINGS_H +#define BLUETOOTH_SETTINGS_H + +#include +#include + +#include +#include +#include + +class BluetoothSettings +{ +public: + struct { + bdaddr_t PickedDevice; + } Data; + + BluetoothSettings(); + ~BluetoothSettings(); + + void Defaults(); + void Load(); + void Save(); + +private: + BPath fPath; + BFile* fFile; +}; + +#endif // BLUETOOTH_SETTINGS_H diff --git a/src/preferences/bluetooth/BluetoothSettingsView.cpp b/src/preferences/bluetooth/BluetoothSettingsView.cpp index b9ba836558..42da6dd48e 100644 --- a/src/preferences/bluetooth/BluetoothSettingsView.cpp +++ b/src/preferences/bluetooth/BluetoothSettingsView.cpp @@ -1,11 +1,18 @@ /* - * Copyright 2008-09, Oliver Ruiz Dorantes, + * Copyright 2008-2009, Oliver Ruiz Dorantes + * Copyright 2012-2013, Tri-Edge AI, + * * All rights reserved. Distributed under the terms of the MIT License. */ + #include "BluetoothSettingsView.h" -#include -#include +#include "defs.h" +#include "BluetoothSettings.h" +#include "BluetoothWindow.h" +#include "ExtendedLocalDeviceView.h" + +#include #include #include @@ -19,12 +26,8 @@ #include #include -#include -#include "ExtendedLocalDeviceView.h" - -#include "defs.h" -#include "BluetoothWindow.h" - +#include +#include #undef B_TRANSLATION_CONTEXT #define B_TRANSLATION_CONTEXT "Settings view" @@ -45,13 +48,15 @@ static const char* kLaptopLabel = B_TRANSLATE_MARK("Laptop"); static const char* kHandheldLabel = B_TRANSLATE_MARK("Handheld"); static const char* kPhoneLabel = B_TRANSLATE_MARK("Smart phone"); - // #pragma mark - BluetoothSettingsView::BluetoothSettingsView(const char* name) - : BView(name, 0), + : + BView(name, 0), fLocalDevicesMenu(NULL) { + fSettings.Load(); + _BuildConnectionPolicy(); fPolicyMenuField = new BMenuField("policy", B_TRANSLATE("Incoming connections policy:"), fPolicyMenu); @@ -65,10 +70,7 @@ BluetoothSettingsView::BluetoothSettingsView(const char* name) fInquiryTimeControl->SetHashMarkCount(255 / 15); fInquiryTimeControl->SetEnabled(true); - // hinting menu - _BuildClassMenu(); - fClassMenuField = new BMenuField("class", B_TRANSLATE("Identify host as:"), - fClassMenu); + fExtDeviceView = new ExtendedLocalDeviceView(BRect(0, 0, 5, 5), NULL); // localdevices menu _BuildLocalDevicesMenu(); @@ -76,13 +78,20 @@ BluetoothSettingsView::BluetoothSettingsView(const char* name) B_TRANSLATE("Local devices found on system:"), fLocalDevicesMenu); - fExtDeviceView = new ExtendedLocalDeviceView(BRect(0, 0, 5, 5), NULL); - SetLayout(new BGroupLayout(B_VERTICAL)); + if (ActiveLocalDevice != NULL) { + fExtDeviceView->SetLocalDevice(ActiveLocalDevice); + fExtDeviceView->SetEnabled(true); + } + + // hinting menu + _BuildClassMenu(); + fClassMenuField = new BMenuField("class", B_TRANSLATE("Identify host as:"), + fClassMenu); + // controls pane AddChild(BGridLayoutBuilder(10, 10) - .Add(fClassMenuField->CreateLabelLayoutItem(), 0, 0) .Add(fClassMenuField->CreateMenuBarLayoutItem(), 1, 0) @@ -107,7 +116,7 @@ BluetoothSettingsView::BluetoothSettingsView(const char* name) BluetoothSettingsView::~BluetoothSettingsView() { - + fSettings.Save(); } @@ -133,44 +142,52 @@ BluetoothSettingsView::MessageReceived(BMessage* message) case kMsgLocalSwitched: { LocalDevice* lDevice; - if (message->FindPointer("LocalDevice", (void**) &lDevice) == B_OK) { - // Device integrity should be rechecked - fExtDeviceView->SetLocalDevice(lDevice); - fExtDeviceView->SetEnabled(true); - ActiveLocalDevice = lDevice; + + if (message->FindPointer("LocalDevice", + (void**)&lDevice) == B_OK) { + + _MarkLocalDevice(lDevice); } + + break; } - break; -/* - To be fixed :) + // TODO: To be fixed. :) + + /* case kMsgSetConnectionPolicy: { //uint8 Policy; //if (message->FindInt8("Policy", (int8*)&Policy) == B_OK) break; } - + case kMsgSetInquiryTime: { break; - }*/ - + } + */ case kMsgSetDeviceClass: { uint8 deviceClass; - if (message->FindInt8("DeviceClass", (int8*)&deviceClass) == B_OK) { + + if (message->FindInt8("DeviceClass", + (int8*)&deviceClass) == B_OK) { + if (deviceClass == 5) _SetDeviceClass(2, 3, 0x72); else _SetDeviceClass(1, deviceClass, 0x72); } + break; } - case kMsgRefresh: + { _BuildLocalDevicesMenu(); fLocalDevicesMenu->SetTargetForItems(this); - break; + + break; + } default: BView::MessageReceived(message); } @@ -178,17 +195,18 @@ BluetoothSettingsView::MessageReceived(BMessage* message) bool -BluetoothSettingsView::_SetDeviceClass(uint8 major, uint8 minor, uint16 service) +BluetoothSettingsView::_SetDeviceClass(uint8 major, uint8 minor, + uint16 service) { bool haveRun = true; - - DeviceClass devClass; - devClass.SetRecord(major, minor, service); + + DeviceClass devClass(major, minor, service); + if (ActiveLocalDevice != NULL) ActiveLocalDevice->SetDeviceClass(devClass); else haveRun = false; - + return haveRun; } @@ -217,13 +235,16 @@ BluetoothSettingsView::_BuildConnectionPolicy() fPolicyMenu->AddItem(item); } - void BluetoothSettingsView::_BuildClassMenu() { - BMessage* message = NULL; BMenuItem* item = NULL; + DeviceClass devClass; + + if (ActiveLocalDevice != NULL) { + devClass = ActiveLocalDevice->GetDeviceClass(); + } fClassMenu = new BPopUpMenu(B_TRANSLATE("Identify us as...")); @@ -232,25 +253,45 @@ BluetoothSettingsView::_BuildClassMenu() item = new BMenuItem(B_TRANSLATE_NOCOLLECT(kDesktopLabel), message); fClassMenu->AddItem(item); + if (devClass.MajorDeviceClass() == 1 && + devClass.MinorDeviceClass() == 1) + item->SetMarked(true); + message = new BMessage(kMsgSetDeviceClass); message->AddInt8("DeviceClass", 2); item = new BMenuItem(B_TRANSLATE_NOCOLLECT(kServerLabel), message); fClassMenu->AddItem(item); + if (devClass.MajorDeviceClass() == 1 && + devClass.MinorDeviceClass() == 2) + item->SetMarked(true); + message = new BMessage(kMsgSetDeviceClass); message->AddInt8("DeviceClass", 3); item = new BMenuItem(B_TRANSLATE_NOCOLLECT(kLaptopLabel), message); fClassMenu->AddItem(item); + if (devClass.MajorDeviceClass() == 1 && + devClass.MinorDeviceClass() == 3) + item->SetMarked(true); + message = new BMessage(kMsgSetDeviceClass); message->AddInt8("DeviceClass", 4); item = new BMenuItem(B_TRANSLATE_NOCOLLECT(kHandheldLabel), message); fClassMenu->AddItem(item); + if (devClass.MajorDeviceClass() == 1 && + devClass.MinorDeviceClass() == 4) + item->SetMarked(true); + message = new BMessage(kMsgSetDeviceClass); message->AddInt8("DeviceClass", 5); item = new BMenuItem(B_TRANSLATE_NOCOLLECT(kPhoneLabel), message); fClassMenu->AddItem(item); + + if (devClass.MajorDeviceClass() == 2 && + devClass.MinorDeviceClass() == 3) + item->SetMarked(true); } @@ -260,20 +301,47 @@ BluetoothSettingsView::_BuildLocalDevicesMenu() LocalDevice* lDevice; if (!fLocalDevicesMenu) - fLocalDevicesMenu = new BPopUpMenu(B_TRANSLATE("Pick LocalDevice...")); + fLocalDevicesMenu = new BPopUpMenu(B_TRANSLATE("Pick device...")); - for (uint32 index = 0; index < LocalDevice::GetLocalDeviceCount(); index++) { + while (fLocalDevicesMenu->CountItems() > 0) { + BMenuItem* item = fLocalDevicesMenu->RemoveItem(0L); + if (item != NULL) { + delete item; + } + } + + ActiveLocalDevice = NULL; + + for (uint32 i = 0; i < LocalDevice::GetLocalDeviceCount(); i++) { lDevice = LocalDevice::GetLocalDevice(); - if (lDevice != NULL) { - // TODO Check if they already exists + if (lDevice != NULL) { BMessage* message = new BMessage(kMsgLocalSwitched); message->AddPointer("LocalDevice", lDevice); - BMenuItem* item = new BMenuItem((lDevice->GetFriendlyName().String()), - message); + BMenuItem* item = new BMenuItem( + (lDevice->GetFriendlyName().String()), message); + + if (bdaddrUtils::Compare(lDevice->GetBluetoothAddress(), + fSettings.Data.PickedDevice)) { + + item->SetMarked(true); + ActiveLocalDevice = lDevice; + } + fLocalDevicesMenu->AddItem(item); } } } + +void +BluetoothSettingsView::_MarkLocalDevice(LocalDevice* lDevice) +{ + // TODO: Device integrity should be rechecked. + + fExtDeviceView->SetLocalDevice(lDevice); + fExtDeviceView->SetEnabled(true); + ActiveLocalDevice = lDevice; + fSettings.Data.PickedDevice = lDevice->GetBluetoothAddress(); +} diff --git a/src/preferences/bluetooth/BluetoothSettingsView.h b/src/preferences/bluetooth/BluetoothSettingsView.h index d46bd1666c..25a03e439c 100644 --- a/src/preferences/bluetooth/BluetoothSettingsView.h +++ b/src/preferences/bluetooth/BluetoothSettingsView.h @@ -1,49 +1,58 @@ /* - * Copyright 2008-09, Oliver Ruiz Dorantes, + * Copyright 2008-2009, Oliver Ruiz Dorantes, + * Copyright 2012-2013, Tri-Edge AI, + * * All rights reserved. Distributed under the terms of the MIT License. */ + #ifndef BLUETOOTH_SETTINGS_VIEW_H #define BLUETOOTH_SETTINGS_VIEW_H +#include "BluetoothSettings.h" #include +class BluetoothSettings; +class ExtendedLocalDeviceView; +class LocalDevice; + class BBox; class BMenuField; class BPopUpMenu; class BSlider; -class ExtendedLocalDeviceView; - class BluetoothSettingsView : public BView { public: - BluetoothSettingsView(const char* name); - virtual ~BluetoothSettingsView(); + BluetoothSettingsView(const char* name); + virtual ~BluetoothSettingsView(); - virtual void AttachedToWindow(); - virtual void MessageReceived(BMessage* message); + virtual void AttachedToWindow(); + virtual void MessageReceived(BMessage* message); private: - void _BuildConnectionPolicy(); - void _BuildClassMenu(); - void _BuildLocalDevicesMenu(); - bool _SetDeviceClass(uint8 major, uint8 minor - , uint16 service); + void _BuildConnectionPolicy(); + void _BuildClassMenu(); + void _BuildLocalDevicesMenu(); + bool _SetDeviceClass(uint8 major, uint8 minor, + uint16 service); + void _MarkLocalDevice(LocalDevice* lDevice); protected: - float fDivider; + BluetoothSettings fSettings; - BMenuField* fPolicyMenuField; - BPopUpMenu* fPolicyMenu; - BMenuField* fClassMenuField; - BPopUpMenu* fClassMenu; - BMenuField* fLocalDevicesMenuField; - BPopUpMenu* fLocalDevicesMenu; + float fDivider; - ExtendedLocalDeviceView* fExtDeviceView; + BMenuField* fPolicyMenuField; + BPopUpMenu* fPolicyMenu; + BMenuField* fClassMenuField; + BPopUpMenu* fClassMenu; + BMenuField* fLocalDevicesMenuField; + BPopUpMenu* fLocalDevicesMenu; - BSlider* fInquiryTimeControl; + ExtendedLocalDeviceView* fExtDeviceView; + + BSlider* fInquiryTimeControl; }; diff --git a/src/preferences/bluetooth/BluetoothWindow.cpp b/src/preferences/bluetooth/BluetoothWindow.cpp index 87c1938222..28cdf3568f 100644 --- a/src/preferences/bluetooth/BluetoothWindow.cpp +++ b/src/preferences/bluetooth/BluetoothWindow.cpp @@ -89,7 +89,6 @@ BluetoothWindow::BluetoothWindow(BRect frame) // tabView->AddTab(fConnChan); tabView->AddTab(fSettingsView); - fRevertButton->SetEnabled(false); AddChild(BGroupLayoutBuilder(B_VERTICAL, 0) diff --git a/src/preferences/bluetooth/BluetoothWindow.h b/src/preferences/bluetooth/BluetoothWindow.h index 24e299a60d..aef9f05cbe 100644 --- a/src/preferences/bluetooth/BluetoothWindow.h +++ b/src/preferences/bluetooth/BluetoothWindow.h @@ -2,37 +2,36 @@ * Copyright 2008-09, Oliver Ruiz Dorantes, * All rights reserved. Distributed under the terms of the MIT License. */ + #ifndef BLUETOOTH_WINDOW_H #define BLUETOOTH_WINDOW_H +#include "BluetoothSettingsView.h" + #include #include #include #include #include - -#include "BluetoothSettingsView.h" - +class BluetoothSettingsView; class RemoteDevicesView; class ConnChanView; -class BluetoothWindow : public BWindow -{ +class BluetoothWindow : public BWindow { public: - BluetoothWindow(BRect frame); + BluetoothWindow(BRect frame); bool QuitRequested(void); void MessageReceived(BMessage *message); - + private: - RemoteDevicesView* fRemoteDevices; - ConnChanView* fConnChan; - BButton* fDefaultsButton; - BButton* fRevertButton; - BMenuBar* fMenubar; - - BluetoothSettingsView* fSettingsView; + RemoteDevicesView* fRemoteDevices; + ConnChanView* fConnChan; + BButton* fDefaultsButton; + BButton* fRevertButton; + BMenuBar* fMenubar; + BluetoothSettingsView* fSettingsView; }; #endif diff --git a/src/preferences/bluetooth/ExtendedLocalDeviceView.cpp b/src/preferences/bluetooth/ExtendedLocalDeviceView.cpp index 575c044ea2..31ddfaff28 100644 --- a/src/preferences/bluetooth/ExtendedLocalDeviceView.cpp +++ b/src/preferences/bluetooth/ExtendedLocalDeviceView.cpp @@ -72,7 +72,7 @@ ExtendedLocalDeviceView::SetLocalDevice(LocalDevice* lDevice) fDevice = lDevice; SetName(lDevice->GetFriendlyName().String()); fDeviceView->SetBluetoothDevice(lDevice); - + ClearDevice(); int value = fDevice->GetDiscoverable(); @@ -110,12 +110,12 @@ void ExtendedLocalDeviceView::MessageReceived(BMessage* message) { printf("ExtendedLocalDeviceView::MessageReceived\n"); - + if (fDevice == NULL) { printf("ExtendedLocalDeviceView::Device missing\n"); return; } - + if (message->WasDropped()) { } @@ -157,7 +157,7 @@ void ExtendedLocalDeviceView::SetEnabled(bool value) { printf("ExtendedLocalDeviceView::SetEnabled\n"); - + fVisible->SetEnabled(value); fAuthentication->SetEnabled(value); fDiscoverable->SetEnabled(value); @@ -168,7 +168,7 @@ void ExtendedLocalDeviceView::ClearDevice() { printf("ExtendedLocalDeviceView::ClearDevice\n"); - + fVisible->SetValue(false); fAuthentication->SetValue(false); fDiscoverable->SetValue(false); diff --git a/src/preferences/bluetooth/Jamfile b/src/preferences/bluetooth/Jamfile index 4b620f51db..351cab064f 100644 --- a/src/preferences/bluetooth/Jamfile +++ b/src/preferences/bluetooth/Jamfile @@ -8,6 +8,7 @@ AddResources Bluetooth : bluetooth-pref.rdef ; Preference Bluetooth : BluetoothDeviceView.cpp BluetoothMain.cpp + BluetoothSettings.cpp BluetoothSettingsView.cpp BluetoothWindow.cpp DeviceListItem.cpp From be7b42ea9971f750ebe8483e614a0f40c025ec35 Mon Sep 17 00:00:00 2001 From: Tri-Edge AI Date: Sun, 16 Dec 2012 19:18:19 +0200 Subject: [PATCH 021/104] Bluetooth: Added device class to settings, in case it can't be retrieved from the dongle. Signed-off-by: Matt Madia --- .../bluetooth/BluetoothSettings.cpp | 1 + src/preferences/bluetooth/BluetoothSettings.h | 1 + .../bluetooth/BluetoothSettingsView.cpp | 34 +++++++++---------- 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/src/preferences/bluetooth/BluetoothSettings.cpp b/src/preferences/bluetooth/BluetoothSettings.cpp index ad6680ca59..2f3bc59d86 100644 --- a/src/preferences/bluetooth/BluetoothSettings.cpp +++ b/src/preferences/bluetooth/BluetoothSettings.cpp @@ -24,6 +24,7 @@ void BluetoothSettings::Defaults() { Data.PickedDevice = bdaddrUtils::NullAddress(); + Data.LocalDeviceClass = DeviceClass(); } diff --git a/src/preferences/bluetooth/BluetoothSettings.h b/src/preferences/bluetooth/BluetoothSettings.h index b04041006f..0ba558b150 100644 --- a/src/preferences/bluetooth/BluetoothSettings.h +++ b/src/preferences/bluetooth/BluetoothSettings.h @@ -20,6 +20,7 @@ class BluetoothSettings public: struct { bdaddr_t PickedDevice; + DeviceClass LocalDeviceClass; } Data; BluetoothSettings(); diff --git a/src/preferences/bluetooth/BluetoothSettingsView.cpp b/src/preferences/bluetooth/BluetoothSettingsView.cpp index 42da6dd48e..54a1864094 100644 --- a/src/preferences/bluetooth/BluetoothSettingsView.cpp +++ b/src/preferences/bluetooth/BluetoothSettingsView.cpp @@ -83,6 +83,11 @@ BluetoothSettingsView::BluetoothSettingsView(const char* name) if (ActiveLocalDevice != NULL) { fExtDeviceView->SetLocalDevice(ActiveLocalDevice); fExtDeviceView->SetEnabled(true); + + DeviceClass rememberedClass = ActiveLocalDevice->GetDeviceClass(); + + if (!rememberedClass.IsUnknownDeviceClass()) + fSettings.Data.LocalDeviceClass = rememberedClass; } // hinting menu @@ -200,10 +205,10 @@ BluetoothSettingsView::_SetDeviceClass(uint8 major, uint8 minor, { bool haveRun = true; - DeviceClass devClass(major, minor, service); + fSettings.Data.LocalDeviceClass.SetRecord(major, minor, service); if (ActiveLocalDevice != NULL) - ActiveLocalDevice->SetDeviceClass(devClass); + ActiveLocalDevice->SetDeviceClass(fSettings.Data.LocalDeviceClass); else haveRun = false; @@ -240,11 +245,6 @@ BluetoothSettingsView::_BuildClassMenu() { BMessage* message = NULL; BMenuItem* item = NULL; - DeviceClass devClass; - - if (ActiveLocalDevice != NULL) { - devClass = ActiveLocalDevice->GetDeviceClass(); - } fClassMenu = new BPopUpMenu(B_TRANSLATE("Identify us as...")); @@ -253,8 +253,8 @@ BluetoothSettingsView::_BuildClassMenu() item = new BMenuItem(B_TRANSLATE_NOCOLLECT(kDesktopLabel), message); fClassMenu->AddItem(item); - if (devClass.MajorDeviceClass() == 1 && - devClass.MinorDeviceClass() == 1) + if (fSettings.Data.LocalDeviceClass.MajorDeviceClass() == 1 && + fSettings.Data.LocalDeviceClass.MinorDeviceClass() == 1) item->SetMarked(true); message = new BMessage(kMsgSetDeviceClass); @@ -262,8 +262,8 @@ BluetoothSettingsView::_BuildClassMenu() item = new BMenuItem(B_TRANSLATE_NOCOLLECT(kServerLabel), message); fClassMenu->AddItem(item); - if (devClass.MajorDeviceClass() == 1 && - devClass.MinorDeviceClass() == 2) + if (fSettings.Data.LocalDeviceClass.MajorDeviceClass() == 1 && + fSettings.Data.LocalDeviceClass.MinorDeviceClass() == 2) item->SetMarked(true); message = new BMessage(kMsgSetDeviceClass); @@ -271,8 +271,8 @@ BluetoothSettingsView::_BuildClassMenu() item = new BMenuItem(B_TRANSLATE_NOCOLLECT(kLaptopLabel), message); fClassMenu->AddItem(item); - if (devClass.MajorDeviceClass() == 1 && - devClass.MinorDeviceClass() == 3) + if (fSettings.Data.LocalDeviceClass.MajorDeviceClass() == 1 && + fSettings.Data.LocalDeviceClass.MinorDeviceClass() == 3) item->SetMarked(true); message = new BMessage(kMsgSetDeviceClass); @@ -280,8 +280,8 @@ BluetoothSettingsView::_BuildClassMenu() item = new BMenuItem(B_TRANSLATE_NOCOLLECT(kHandheldLabel), message); fClassMenu->AddItem(item); - if (devClass.MajorDeviceClass() == 1 && - devClass.MinorDeviceClass() == 4) + if (fSettings.Data.LocalDeviceClass.MajorDeviceClass() == 1 && + fSettings.Data.LocalDeviceClass.MinorDeviceClass() == 4) item->SetMarked(true); message = new BMessage(kMsgSetDeviceClass); @@ -289,8 +289,8 @@ BluetoothSettingsView::_BuildClassMenu() item = new BMenuItem(B_TRANSLATE_NOCOLLECT(kPhoneLabel), message); fClassMenu->AddItem(item); - if (devClass.MajorDeviceClass() == 2 && - devClass.MinorDeviceClass() == 3) + if (fSettings.Data.LocalDeviceClass.MajorDeviceClass() == 2 && + fSettings.Data.LocalDeviceClass.MinorDeviceClass() == 3) item->SetMarked(true); } From f0e995c8d48978ed5a78b7db6fe3ea6e73f3d17c Mon Sep 17 00:00:00 2001 From: Ziusudra Date: Sun, 25 Nov 2012 21:05:16 -0700 Subject: [PATCH 022/104] Create TimeZoneListView class and move GetToolTipAt into it, fixes #7726 Signed-off-by: Matt Madia --- src/preferences/time/Jamfile | 2 + src/preferences/time/TimeZoneListView.cpp | 74 +++++++++++++++++++++++ src/preferences/time/TimeZoneListView.h | 31 ++++++++++ src/preferences/time/ZoneView.cpp | 44 +------------- src/preferences/time/ZoneView.h | 9 +-- 5 files changed, 113 insertions(+), 47 deletions(-) create mode 100644 src/preferences/time/TimeZoneListView.cpp create mode 100644 src/preferences/time/TimeZoneListView.h diff --git a/src/preferences/time/Jamfile b/src/preferences/time/Jamfile index c0579a753f..bd1295a37b 100644 --- a/src/preferences/time/Jamfile +++ b/src/preferences/time/Jamfile @@ -19,6 +19,7 @@ local sources = TimeSettings.cpp TimeWindow.cpp TimeZoneListItem.cpp + TimeZoneListView.cpp TZDisplay.cpp ZoneView.cpp ; @@ -44,5 +45,6 @@ DoCatalogs Time : ntp.cpp Time.cpp TimeWindow.cpp + TimeZoneListView.cpp ZoneView.cpp ; diff --git a/src/preferences/time/TimeZoneListView.cpp b/src/preferences/time/TimeZoneListView.cpp new file mode 100644 index 0000000000..87a8519c85 --- /dev/null +++ b/src/preferences/time/TimeZoneListView.cpp @@ -0,0 +1,74 @@ +/* + * Copyright 2012, Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Sean Bailey +*/ + + +#include "TimeZoneListView.h" + +#include + +#include +#include +#include +#include +#include + +#include "TimeZoneListItem.h" + + +#undef B_TRANSLATION_CONTEXT +#define B_TRANSLATION_CONTEXT "Time" + + +TimeZoneListView::TimeZoneListView(void) + : + BOutlineListView("cityList", B_SINGLE_SELECTION_LIST), + fToolTip(NULL) +{ +} + + +TimeZoneListView::~TimeZoneListView() +{ + if (fToolTip != NULL) + fToolTip->ReleaseReference(); +} + + +bool +TimeZoneListView::GetToolTipAt(BPoint point, BToolTip** _tip) +{ + TimeZoneListItem* item = static_cast( + this->ItemAt(this->IndexOf(point))); + if (item == NULL || !item->HasTimeZone()) + return false; + + BString nowInTimeZone; + time_t now = time(NULL); + BLocale::Default()->FormatTime(&nowInTimeZone, now, B_SHORT_TIME_FORMAT, + &item->TimeZone()); + + BString dateInTimeZone; + BLocale::Default()->FormatDate(&dateInTimeZone, now, B_SHORT_DATE_FORMAT, + &item->TimeZone()); + + BString toolTip = item->Text(); + toolTip << '\n' << item->TimeZone().ShortName() << " / " + << item->TimeZone().ShortDaylightSavingName() + << B_TRANSLATE("\nNow: ") << nowInTimeZone + << " (" << dateInTimeZone << ')'; + + if (fToolTip != NULL) + fToolTip->ReleaseReference(); + fToolTip = new (std::nothrow) BTextToolTip(toolTip.String()); + if (fToolTip == NULL) + return false; + + *_tip = fToolTip; + + return true; +} diff --git a/src/preferences/time/TimeZoneListView.h b/src/preferences/time/TimeZoneListView.h new file mode 100644 index 0000000000..0b9fd48d0a --- /dev/null +++ b/src/preferences/time/TimeZoneListView.h @@ -0,0 +1,31 @@ +/* + * Copyright 2012, Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Sean Bailey + */ +#ifndef _TIME_ZONE_LIST_VIEW_H +#define _TIME_ZONE_LIST_VIEW_H + + +#include + + +class BTextToolTip; + + +class TimeZoneListView : public BOutlineListView { +public: + TimeZoneListView(void); + ~TimeZoneListView(); + +protected: + virtual bool GetToolTipAt(BPoint point, BToolTip** _tip); + +private: + BTextToolTip* fToolTip; +}; + + +#endif // _TIME_ZONE_LIST_VIEW_H diff --git a/src/preferences/time/ZoneView.cpp b/src/preferences/time/ZoneView.cpp index c773de5645..08f53327db 100644 --- a/src/preferences/time/ZoneView.cpp +++ b/src/preferences/time/ZoneView.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2004-2010, Haiku, Inc. All Rights Reserved. + * Copyright 2004-2012, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -42,7 +42,6 @@ #include #include #include -#include #include #include @@ -52,6 +51,7 @@ #include "TimeMessages.h" #include "TimeZoneListItem.h" +#include "TimeZoneListView.h" #include "TZDisplay.h" @@ -84,7 +84,6 @@ TimeZoneView::TimeZoneView(const char* name) : BGroupView(name, B_HORIZONTAL, B_USE_DEFAULT_SPACING), fGmtTime(NULL), - fToolTip(NULL), fUseGmtTime(false), fCurrentZoneItem(NULL), fOldZoneItem(NULL), @@ -107,8 +106,6 @@ TimeZoneView::CheckCanRevert() TimeZoneView::~TimeZoneView() { - if (fToolTip != NULL) - fToolTip->ReleaseReference(); _WriteRTCSettings(); } @@ -189,41 +186,6 @@ TimeZoneView::MessageReceived(BMessage* message) } -bool -TimeZoneView::GetToolTipAt(BPoint point, BToolTip** _tip) -{ - TimeZoneListItem* item = static_cast( - fZoneList->ItemAt(fZoneList->IndexOf(point))); - if (item == NULL || !item->HasTimeZone()) - return false; - - BString nowInTimeZone; - time_t now = time(NULL); - BLocale::Default()->FormatTime(&nowInTimeZone, now, B_SHORT_TIME_FORMAT, - &item->TimeZone()); - - BString dateInTimeZone; - BLocale::Default()->FormatDate(&dateInTimeZone, now, B_SHORT_DATE_FORMAT, - &item->TimeZone()); - - BString toolTip = item->Text(); - toolTip << '\n' << item->TimeZone().ShortName() << " / " - << item->TimeZone().ShortDaylightSavingName() - << B_TRANSLATE("\nNow: ") << nowInTimeZone - << " (" << dateInTimeZone << ')'; - - if (fToolTip != NULL) - fToolTip->ReleaseReference(); - fToolTip = new (std::nothrow) BTextToolTip(toolTip.String()); - if (fToolTip == NULL) - return false; - - *_tip = fToolTip; - - return true; -} - - void TimeZoneView::_UpdateDateTime(BMessage* message) { @@ -243,7 +205,7 @@ TimeZoneView::_UpdateDateTime(BMessage* message) void TimeZoneView::_InitView() { - fZoneList = new BOutlineListView("cityList", B_SINGLE_SELECTION_LIST); + fZoneList = new TimeZoneListView(); fZoneList->SetSelectionMessage(new BMessage(H_CITY_CHANGED)); fZoneList->SetInvocationMessage(new BMessage(H_SET_TIME_ZONE)); _BuildZoneMenu(); diff --git a/src/preferences/time/ZoneView.h b/src/preferences/time/ZoneView.h index b0ac9b49b6..9766263709 100644 --- a/src/preferences/time/ZoneView.h +++ b/src/preferences/time/ZoneView.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2011, Haiku, Inc. All Rights Reserved. + * Copyright 2004-2012, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -20,9 +20,9 @@ class BMessage; class BOutlineListView; class BPopUpMenu; class BRadioButton; -class BTextToolTip; class BTimeZone; class TimeZoneListItem; +class TimeZoneListView; class TTZDisplay; @@ -36,7 +36,6 @@ public: bool CheckCanRevert(); protected: - virtual bool GetToolTipAt(BPoint point, BToolTip** _tip); virtual void DoLayout(); private: @@ -58,15 +57,13 @@ private: void _Revert(); - BOutlineListView* fZoneList; + TimeZoneListView* fZoneList; BButton* fSetZone; TTZDisplay* fCurrent; TTZDisplay* fPreview; BRadioButton* fLocalTime; BRadioButton* fGmtTime; - BTextToolTip* fToolTip; - int32 fLastUpdateMinute; bool fUseGmtTime; bool fOldUseGmtTime; From 74252cefbcf266291fb069466189b4734eb05455 Mon Sep 17 00:00:00 2001 From: Matt Madia Date: Sat, 2 Mar 2013 19:08:57 -0500 Subject: [PATCH 023/104] Inform the decorators where to find DoublyLinkedList.h Prior to this, jam -q [ClassicBe|MacDecorator|WinDecorator] would fail. They still fail, but for one less reason at least. --- src/add-ons/decorators/BeDecorator/Jamfile | 1 + src/add-ons/decorators/MacDecorator/Jamfile | 1 + src/add-ons/decorators/WinDecorator/Jamfile | 1 + 3 files changed, 3 insertions(+) diff --git a/src/add-ons/decorators/BeDecorator/Jamfile b/src/add-ons/decorators/BeDecorator/Jamfile index 99e6d5fae8..2e6b9062b2 100644 --- a/src/add-ons/decorators/BeDecorator/Jamfile +++ b/src/add-ons/decorators/BeDecorator/Jamfile @@ -6,6 +6,7 @@ UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing ] ; UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing Painter ] ; UsePrivateHeaders app shared interface graphics ; UseLibraryHeaders agg ; +UsePrivateHeaders kernel ; AddResources ClassicBe : resources.rdef ; diff --git a/src/add-ons/decorators/MacDecorator/Jamfile b/src/add-ons/decorators/MacDecorator/Jamfile index 6ee87f0b4e..04e7b22941 100644 --- a/src/add-ons/decorators/MacDecorator/Jamfile +++ b/src/add-ons/decorators/MacDecorator/Jamfile @@ -8,6 +8,7 @@ UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing Painter ] ; UseHeaders [ FDirName $(HAIKU_TOP) src servers app font ] ; UsePrivateHeaders app shared interface graphics ; UseLibraryHeaders agg ; +UsePrivateHeaders kernel ; AddResources MacDecorator : resources.rdef ; diff --git a/src/add-ons/decorators/WinDecorator/Jamfile b/src/add-ons/decorators/WinDecorator/Jamfile index a0c60a2803..a7dbde8c58 100644 --- a/src/add-ons/decorators/WinDecorator/Jamfile +++ b/src/add-ons/decorators/WinDecorator/Jamfile @@ -6,6 +6,7 @@ UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing ] ; UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing Painter ] ; UsePrivateHeaders app shared interface graphics ; UseLibraryHeaders agg ; +UsePrivateHeaders kernel ; AddResources WinDecorator : resources.rdef ; From ca51eb367d8a1876855f9c53a08653c41a164ea5 Mon Sep 17 00:00:00 2001 From: Matt Madia Date: Sat, 2 Mar 2013 19:20:17 -0500 Subject: [PATCH 024/104] Add FreeType headers dependencies, #8716. This allows MacDecorator to build once again. Due to other errors, BeDecorator and WinDecorator do not (yet) fail on the missing FreeType header -- hence it being only a comment for now. --- src/add-ons/decorators/BeDecorator/Jamfile | 4 ++++ src/add-ons/decorators/MacDecorator/Jamfile | 3 +++ src/add-ons/decorators/WinDecorator/Jamfile | 4 ++++ 3 files changed, 11 insertions(+) diff --git a/src/add-ons/decorators/BeDecorator/Jamfile b/src/add-ons/decorators/BeDecorator/Jamfile index 2e6b9062b2..b4acfb0991 100644 --- a/src/add-ons/decorators/BeDecorator/Jamfile +++ b/src/add-ons/decorators/BeDecorator/Jamfile @@ -10,6 +10,10 @@ UsePrivateHeaders kernel ; AddResources ClassicBe : resources.rdef ; +#TODO: See #8716, hrev44313 for ft2build.h: No such file or directory +#Includes [ FGristFiles BeDecorator.cpp ] +# : $(HAIKU_FREETYPE_HEADERS_DEPENDENCY) ; + Addon ClassicBe : BeDecorator.cpp : be app_server $(TARGET_LIBSTDC++) $(TARGET_LIBSUPC++) diff --git a/src/add-ons/decorators/MacDecorator/Jamfile b/src/add-ons/decorators/MacDecorator/Jamfile index 04e7b22941..88ffb91998 100644 --- a/src/add-ons/decorators/MacDecorator/Jamfile +++ b/src/add-ons/decorators/MacDecorator/Jamfile @@ -12,6 +12,9 @@ UsePrivateHeaders kernel ; AddResources MacDecorator : resources.rdef ; +Includes [ FGristFiles MacDecorator.cpp ] + : $(HAIKU_FREETYPE_HEADERS_DEPENDENCY) ; + Addon MacDecorator : MacDecorator.cpp : be app_server $(TARGET_LIBSTDC++) diff --git a/src/add-ons/decorators/WinDecorator/Jamfile b/src/add-ons/decorators/WinDecorator/Jamfile index a7dbde8c58..b472e5989b 100644 --- a/src/add-ons/decorators/WinDecorator/Jamfile +++ b/src/add-ons/decorators/WinDecorator/Jamfile @@ -10,6 +10,10 @@ UsePrivateHeaders kernel ; AddResources WinDecorator : resources.rdef ; +#TODO: See #8716, hrev44313 for ft2build.h: No such file or directory +#Includes [ FGristFiles WinDecorator.cpp ] +# : $(HAIKU_FREETYPE_HEADERS_DEPENDENCY) ; + Addon WinDecorator : WinDecorator.cpp : be app_server $(TARGET_LIBSTDC++) From 703912cc4fd9b34b06f672df798fcebbadd609a5 Mon Sep 17 00:00:00 2001 From: Matt Madia Date: Sat, 2 Mar 2013 19:38:27 -0500 Subject: [PATCH 025/104] Aesthetical changes. No functional change. Manually applied humdinger's Decorator_aesthetics.diff patch from #7874. --- .../appearance/LookAndFeelSettingsView.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/preferences/appearance/LookAndFeelSettingsView.cpp b/src/preferences/appearance/LookAndFeelSettingsView.cpp index 5a6b12c455..eb048aaa32 100644 --- a/src/preferences/appearance/LookAndFeelSettingsView.cpp +++ b/src/preferences/appearance/LookAndFeelSettingsView.cpp @@ -74,7 +74,7 @@ LookAndFeelSettingsView::LookAndFeelSettingsView(const char* name) // Decorator menu _BuildDecorMenu(); fDecorMenuField = new BMenuField("decorator", - B_TRANSLATE("Window decorator:"), fDecorMenu); + B_TRANSLATE("Decorator:"), fDecorMenu); fDecorInfoButton = new BButton(B_TRANSLATE("About"), new BMessage(kMsgDecorInfo)); @@ -179,13 +179,14 @@ LookAndFeelSettingsView::MessageReceived(BMessage *msg) break; BString authorsText(decor->Authors().String()); - authorsText.ReplaceAll(", ", "\n "); + authorsText.ReplaceAll(", ", "\n\t"); - BString infoText("Name: %decorName\n" - "Authors:\n %decorAuthors\n" + BString infoText(B_TRANSLATE("%decorName\n\n" + "Authors:\n\t%decorAuthors\n\n" "URL: %decorURL\n" - "License: %decorLic\n" - "Description:\n %decorDesc\n"); + "License: %decorLic\n\n" + "%decorDesc\n")); + infoText.ReplaceFirst("%decorName", decor->Name().String()); infoText.ReplaceFirst("%decorAuthors", authorsText.String()); @@ -193,7 +194,7 @@ LookAndFeelSettingsView::MessageReceived(BMessage *msg) infoText.ReplaceFirst("%decorURL", decor->SupportURL().String()); infoText.ReplaceFirst("%decorDesc", decor->ShortDescription().String()); - BAlert *infoAlert = new BAlert(B_TRANSLATE("About Decorator"), + BAlert *infoAlert = new BAlert(B_TRANSLATE("About decorator"), infoText.String(), B_TRANSLATE("OK")); infoAlert->SetFlags(infoAlert->Flags() | B_CLOSE_ON_ESCAPE); infoAlert->Go(); From 97ef596f2707c3eeee881fee7f8175d6f282fbfb Mon Sep 17 00:00:00 2001 From: John Scipione Date: Sun, 3 Mar 2013 14:49:41 -0500 Subject: [PATCH 026/104] Fix color preview drawing bug in Appearance. Fixes #9501 Also updated to use color constants intead of hardcoding colors. This draws a nice 3d-ish bevelled border around the color preview box. --- src/preferences/appearance/ColorPreview.cpp | 42 ++++++++++++++------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/src/preferences/appearance/ColorPreview.cpp b/src/preferences/appearance/ColorPreview.cpp index 81ce2bf201..6dcbc04e37 100644 --- a/src/preferences/appearance/ColorPreview.cpp +++ b/src/preferences/appearance/ColorPreview.cpp @@ -45,25 +45,39 @@ ColorPreview::Draw(BRect update) if (is_rect) { if (is_enabled) { - BRect r(Bounds()); - SetHighColor(184, 184, 184); - StrokeRect(r); + rgb_color background = ui_color(B_PANEL_BACKGROUND_COLOR); + rgb_color shadow = tint_color(background, B_DARKEN_1_TINT); + rgb_color darkShadow = tint_color(background, B_DARKEN_3_TINT); + rgb_color light = tint_color(background, B_LIGHTEN_MAX_TINT); - SetHighColor(255, 255, 255); - StrokeLine(BPoint(r.right, r.top + 1), r.RightBottom()); + BRect bounds(Bounds()); - r.InsetBy(1, 1); + BeginLineArray(4); + AddLine(BPoint(bounds.left, bounds.bottom), + BPoint(bounds.left, bounds.top), shadow); + AddLine(BPoint(bounds.left + 1.0, bounds.top), + BPoint(bounds.right, bounds.top), shadow); + AddLine(BPoint(bounds.right, bounds.top + 1.0), + BPoint(bounds.right, bounds.bottom), light); + AddLine(BPoint(bounds.right - 1.0, bounds.bottom), + BPoint(bounds.left + 1.0, bounds.bottom), light); + EndLineArray(); + bounds.InsetBy(1.0, 1.0); - SetHighColor(216, 216, 216); - StrokeLine(r.RightTop(), r.RightBottom()); + BeginLineArray(4); + AddLine(BPoint(bounds.left, bounds.bottom), + BPoint(bounds.left, bounds.top), darkShadow); + AddLine(BPoint(bounds.left + 1.0, bounds.top), + BPoint(bounds.right, bounds.top), darkShadow); + AddLine(BPoint(bounds.right, bounds.top + 1.0), + BPoint(bounds.right, bounds.bottom), background); + AddLine(BPoint(bounds.right - 1.0, bounds.bottom), + BPoint(bounds.left + 1.0, bounds.bottom), background); + EndLineArray(); + bounds.InsetBy(1.0, 1.0); - SetHighColor(96, 96, 96); - StrokeLine(r.LeftTop(), r.RightTop()); - StrokeLine(r.LeftTop(), r.LeftBottom()); - - r.InsetBy(1, 1); SetHighColor(color); - FillRect(r); + FillRect(bounds); } else { SetHighColor(color); FillRect(Bounds()); From 8a9200992e8faad457261a888a8689f5aa4bfda7 Mon Sep 17 00:00:00 2001 From: Ryan Leavengood Date: Sat, 2 Mar 2013 08:08:30 -0500 Subject: [PATCH 027/104] Fix Scrollbar arrow button alignment. The arrow symbol on the right and down buttons was off by one pixel. Because of the resurrected FakeScrollbar in the Appearance preflet I had to change this code in two places, which makes me unhappy. This needs to be pulled into BControlLook. Fixes #9104. --- src/kits/interface/ScrollBar.cpp | 12 ++++++------ src/preferences/appearance/FakeScrollBar.cpp | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/kits/interface/ScrollBar.cpp b/src/kits/interface/ScrollBar.cpp index 56099fa8ec..ea9918d841 100644 --- a/src/kits/interface/ScrollBar.cpp +++ b/src/kits/interface/ScrollBar.cpp @@ -1803,9 +1803,9 @@ BScrollBar::_DrawArrowButton(int32 direction, bool doubleArrows, BRect r, tri3.Set(r.right, r.bottom + 1); break; case ARROW_RIGHT: - tri1.Set(r.left, r.bottom + 1); - tri2.Set(r.left + r.Width() / 1.33, (r.top + r.bottom + 1) / 2); - tri3.Set(r.left, r.top); + tri1.Set(r.left + 1, r.bottom + 1); + tri2.Set(r.left + 1 + r.Width() / 1.33, (r.top + r.bottom + 1) / 2); + tri3.Set(r.left + 1, r.top); break; case ARROW_UP: tri1.Set(r.left, r.bottom); @@ -1813,9 +1813,9 @@ BScrollBar::_DrawArrowButton(int32 direction, bool doubleArrows, BRect r, tri3.Set(r.right + 1, r.bottom); break; default: - tri1.Set(r.left, r.top); - tri2.Set((r.left + r.right + 1) / 2, r.top + r.Height() / 1.33); - tri3.Set(r.right + 1, r.top); + tri1.Set(r.left, r.top + 1); + tri2.Set((r.left + r.right + 1) / 2, r.top + 1 + r.Height() / 1.33); + tri3.Set(r.right + 1, r.top + 1); break; } // offset triangle if down diff --git a/src/preferences/appearance/FakeScrollBar.cpp b/src/preferences/appearance/FakeScrollBar.cpp index fdbd1d1f16..7393b946f1 100644 --- a/src/preferences/appearance/FakeScrollBar.cpp +++ b/src/preferences/appearance/FakeScrollBar.cpp @@ -288,9 +288,9 @@ FakeScrollBar::_DrawArrowButton(int32 direction, bool doubleArrows, BRect r, break; case ARROW_RIGHT: - tri1.Set(r.left, r.bottom + 1); - tri2.Set(r.left + r.Width() / 1.33, (r.top + r.bottom + 1) / 2); - tri3.Set(r.left, r.top); + tri1.Set(r.left + 1, r.bottom + 1); + tri2.Set(r.left + 1 + r.Width() / 1.33, (r.top + r.bottom + 1) / 2); + tri3.Set(r.left + 1, r.top); break; case ARROW_UP: @@ -300,9 +300,9 @@ FakeScrollBar::_DrawArrowButton(int32 direction, bool doubleArrows, BRect r, break; default: - tri1.Set(r.left, r.top); - tri2.Set((r.left + r.right + 1) / 2, r.top + r.Height() / 1.33); - tri3.Set(r.right + 1, r.top); + tri1.Set(r.left, r.top + 1); + tri2.Set((r.left + r.right + 1) / 2, r.top + 1 + r.Height() / 1.33); + tri3.Set(r.right + 1, r.top + 1); break; } From f9b1a47fa329a440024cfcb45a82841ff6961f42 Mon Sep 17 00:00:00 2001 From: Ryan Leavengood Date: Sun, 3 Mar 2013 17:45:47 -0500 Subject: [PATCH 028/104] Use be_control_look for BScrollBar and FakeScrollBar. Remove all code which checks for be_control_look being NULL. Also fix the DrawArrowShape method in be_control_look so the arrow is aligned, as per the previous commit. In addition the code to offset the arrow when the scroll button is pressed was unnecessary. There is still some room for improvement, and I am not happy with the BControlLook behavior here, as noted in some TODOs. --- src/kits/interface/ControlLook.cpp | 19 +- src/kits/interface/ScrollBar.cpp | 336 +++---------------- src/preferences/appearance/FakeScrollBar.cpp | 70 +--- src/preferences/appearance/FakeScrollBar.h | 3 +- 4 files changed, 60 insertions(+), 368 deletions(-) diff --git a/src/kits/interface/ControlLook.cpp b/src/kits/interface/ControlLook.cpp index 4b0910e19b..3e00369bcb 100644 --- a/src/kits/interface/ControlLook.cpp +++ b/src/kits/interface/ControlLook.cpp @@ -740,14 +740,14 @@ BControlLook::DrawArrowShape(BView* view, BRect& rect, const BRect& updateRect, case B_LEFT_ARROW: tri1.Set(rect.right, rect.top); tri2.Set(rect.right - rect.Width() / 1.33, - (rect.top + rect.bottom + 1) /2 ); + (rect.top + rect.bottom + 1) / 2); tri3.Set(rect.right, rect.bottom + 1); break; case B_RIGHT_ARROW: - tri1.Set(rect.left, rect.bottom + 1); - tri2.Set(rect.left + rect.Width() / 1.33, + tri1.Set(rect.left + 1, rect.bottom + 1); + tri2.Set(rect.left + 1 + rect.Width() / 1.33, (rect.top + rect.bottom + 1) / 2); - tri3.Set(rect.left, rect.top); + tri3.Set(rect.left + 1, rect.top); break; case B_UP_ARROW: tri1.Set(rect.left, rect.bottom); @@ -757,17 +757,12 @@ BControlLook::DrawArrowShape(BView* view, BRect& rect, const BRect& updateRect, break; case B_DOWN_ARROW: default: - tri1.Set(rect.left, rect.top); + tri1.Set(rect.left, rect.top + 1); tri2.Set((rect.left + rect.right + 1) / 2, - rect.top + rect.Height() / 1.33); - tri3.Set(rect.right + 1, rect.top); + rect.top + 1 + rect.Height() / 1.33); + tri3.Set(rect.right + 1, rect.top + 1); break; } - // offset triangle if down - if ((flags & B_ACTIVATED) != 0) - view->MovePenTo(BPoint(1, 1)); - else - view->MovePenTo(BPoint(0, 0)); BShape arrowShape; arrowShape.MoveTo(tri1); diff --git a/src/kits/interface/ScrollBar.cpp b/src/kits/interface/ScrollBar.cpp index ea9918d841..44c2382333 100644 --- a/src/kits/interface/ScrollBar.cpp +++ b/src/kits/interface/ScrollBar.cpp @@ -943,176 +943,37 @@ BScrollBar::Draw(BRect updateRect) // background for thumb area BRect rect(fPrivateData->fThumbFrame); - if (be_control_look == NULL) { - if (fOrientation == B_HORIZONTAL) { - BeginLineArray(8); - - if (rect.left > thumbBG.left) { - AddLine(BPoint(thumbBG.left, thumbBG.bottom), - BPoint(thumbBG.left, thumbBG.top), - rect.left > thumbBG.left + 1 ? dark4 : dark); - } - if (rect.left > thumbBG.left + 1) { - AddLine(BPoint(thumbBG.left + 1, thumbBG.top + 1), - BPoint(thumbBG.left + 1, thumbBG.bottom), dark2); - AddLine(BPoint(thumbBG.left + 1, thumbBG.top), - BPoint(rect.left - 1, thumbBG.top), dark2); - AddLine(BPoint(rect.left - 1, thumbBG.bottom), - BPoint(thumbBG.left + 2, thumbBG.bottom), normal); - } - - if (rect.right < thumbBG.right - 1) { - AddLine(BPoint(rect.right + 2, thumbBG.top + 1), - BPoint(rect.right + 2, thumbBG.bottom), dark2); - AddLine(BPoint(rect.right + 1, thumbBG.top), - BPoint(thumbBG.right, thumbBG.top), dark2); - AddLine(BPoint(thumbBG.right - 1, thumbBG.bottom), - BPoint(rect.right + 3, thumbBG.bottom), normal); - } - if (rect.right < thumbBG.right) { - AddLine(BPoint(thumbBG.right, thumbBG.top), - BPoint(thumbBG.right, thumbBG.bottom), dark); - } - - EndLineArray(); - } else { - BeginLineArray(8); - - if (rect.top > thumbBG.top) { - AddLine(BPoint(thumbBG.left, thumbBG.top), - BPoint(thumbBG.right, thumbBG.top), - rect.top > thumbBG.top + 1 ? dark4 : dark); - } - if (rect.top > thumbBG.top + 1) { - AddLine(BPoint(thumbBG.left + 1, thumbBG.top + 1), - BPoint(thumbBG.right, thumbBG.top + 1), dark2); - AddLine(BPoint(thumbBG.left, rect.top - 1), - BPoint(thumbBG.left, thumbBG.top + 1), dark2); - AddLine(BPoint(thumbBG.right, rect.top - 1), - BPoint(thumbBG.right, thumbBG.top + 2), normal); - } - - if (rect.bottom < thumbBG.bottom - 1) { - AddLine(BPoint(thumbBG.left + 1, rect.bottom + 2), - BPoint(thumbBG.right, rect.bottom + 2), dark2); - AddLine(BPoint(thumbBG.left, rect.bottom + 1), - BPoint(thumbBG.left, thumbBG.bottom - 1), dark2); - AddLine(BPoint(thumbBG.right, rect.bottom + 3), - BPoint(thumbBG.right, thumbBG.bottom - 1), normal); - } - if (rect.bottom < thumbBG.bottom) { - AddLine(BPoint(thumbBG.left, thumbBG.bottom), - BPoint(thumbBG.right, thumbBG.bottom), dark); - } - - EndLineArray(); - } - } SetHighColor(dark1); - if (be_control_look != NULL) { - uint32 flags = 0; - if (!enabled) - flags |= BControlLook::B_DISABLED; + uint32 flags = 0; + if (!enabled) + flags |= BControlLook::B_DISABLED; - // fill background besides the thumb - if (fOrientation == B_HORIZONTAL) { - BRect leftOfThumb(thumbBG.left, thumbBG.top, rect.left - 1, - thumbBG.bottom); - BRect rightOfThumb(rect.right + 1, thumbBG.top, thumbBG.right, - thumbBG.bottom); + // fill background besides the thumb + if (fOrientation == B_HORIZONTAL) { + BRect leftOfThumb(thumbBG.left, thumbBG.top, rect.left - 1, + thumbBG.bottom); + BRect rightOfThumb(rect.right + 1, thumbBG.top, thumbBG.right, + thumbBG.bottom); - be_control_look->DrawScrollBarBackground(this, leftOfThumb, - rightOfThumb, updateRect, normal, flags, fOrientation); - } else { - BRect topOfThumb(thumbBG.left, thumbBG.top, - thumbBG.right, rect.top - 1); + be_control_look->DrawScrollBarBackground(this, leftOfThumb, + rightOfThumb, updateRect, normal, flags, fOrientation); + } else { + BRect topOfThumb(thumbBG.left, thumbBG.top, + thumbBG.right, rect.top - 1); - BRect bottomOfThumb(thumbBG.left, rect.bottom + 1, - thumbBG.right, thumbBG.bottom); + BRect bottomOfThumb(thumbBG.left, rect.bottom + 1, + thumbBG.right, thumbBG.bottom); - be_control_look->DrawScrollBarBackground(this, topOfThumb, - bottomOfThumb, updateRect, normal, flags, fOrientation); - } + be_control_look->DrawScrollBarBackground(this, topOfThumb, + bottomOfThumb, updateRect, normal, flags, fOrientation); } // Draw scroll thumb if (enabled) { - if (be_control_look == NULL) { - // fill and additional dark lines - thumbBG.InsetBy(1.0, 1.0); - if (fOrientation == B_HORIZONTAL) { - BRect leftOfThumb(thumbBG.left + 1, thumbBG.top, rect.left - 1, - thumbBG.bottom); - if (leftOfThumb.IsValid()) - FillRect(leftOfThumb); - - BRect rightOfThumb(rect.right + 3, thumbBG.top, thumbBG.right, - thumbBG.bottom); - if (rightOfThumb.IsValid()) - FillRect(rightOfThumb); - - // dark lines before and after thumb - if (rect.left > thumbBG.left) { - SetHighColor(dark); - StrokeLine(BPoint(rect.left - 1, rect.top), - BPoint(rect.left - 1, rect.bottom)); - } - if (rect.right < thumbBG.right) { - SetHighColor(dark4); - StrokeLine(BPoint(rect.right + 1, rect.top), - BPoint(rect.right + 1, rect.bottom)); - } - } else { - BRect topOfThumb(thumbBG.left, thumbBG.top + 1, - thumbBG.right, rect.top - 1); - if (topOfThumb.IsValid()) - FillRect(topOfThumb); - - BRect bottomOfThumb(thumbBG.left, rect.bottom + 3, - thumbBG.right, thumbBG.bottom); - if (bottomOfThumb.IsValid()) - FillRect(bottomOfThumb); - - // dark lines before and after thumb - if (rect.top > thumbBG.top) { - SetHighColor(dark); - StrokeLine(BPoint(rect.left, rect.top - 1), - BPoint(rect.right, rect.top - 1)); - } - if (rect.bottom < thumbBG.bottom) { - SetHighColor(dark4); - StrokeLine(BPoint(rect.left, rect.bottom + 1), - BPoint(rect.right, rect.bottom + 1)); - } - } - } - // fill the clickable surface of the thumb - if (be_control_look != NULL) { - be_control_look->DrawButtonBackground(this, rect, updateRect, - normal, 0, BControlLook::B_ALL_BORDERS, fOrientation); - } else { - BeginLineArray(4); - AddLine(BPoint(rect.left, rect.bottom), - BPoint(rect.left, rect.top), light); - AddLine(BPoint(rect.left + 1, rect.top), - BPoint(rect.right, rect.top), light); - AddLine(BPoint(rect.right, rect.top + 1), - BPoint(rect.right, rect.bottom), dark1); - AddLine(BPoint(rect.right - 1, rect.bottom), - BPoint(rect.left + 1, rect.bottom), dark1); - EndLineArray(); - - // fill - rect.InsetBy(1.0, 1.0); - /*if (fPrivateData->fButtonDown == THUMB) - SetHighColor(tint_color(normal, (B_NO_TINT + B_DARKEN_1_TINT) / 2)); - else*/ - SetHighColor(normal); - - FillRect(rect); - } + be_control_look->DrawButtonBackground(this, rect, updateRect, + normal, 0, BControlLook::B_ALL_BORDERS, fOrientation); // TODO: Add the other thumb styles - dots and lines } else { if (fMin >= fMax || fProportion >= 1.0 || fProportion < 0.0) { @@ -1749,152 +1610,31 @@ BScrollBar::_DrawDisabledBackground(BRect area, void -BScrollBar::_DrawArrowButton(int32 direction, bool doubleArrows, BRect r, +BScrollBar::_DrawArrowButton(int32 direction, bool doubleArrows, BRect rect, const BRect& updateRect, bool enabled, bool down) { - if (!updateRect.Intersects(r)) + if (!updateRect.Intersects(rect)) return; - rgb_color c = ui_color(B_PANEL_BACKGROUND_COLOR); - rgb_color light, dark, darker, normal, arrow; + uint32 flags = 0; + if (!enabled) + flags |= BControlLook::B_DISABLED; + if (down && fPrivateData->fDoRepeat) + flags |= BControlLook::B_ACTIVATED; - if (down && fPrivateData->fDoRepeat) { - light = tint_color(c, (B_DARKEN_1_TINT + B_DARKEN_2_TINT) / 2.0); - dark = darker = c; - normal = tint_color(c, B_DARKEN_1_TINT); - arrow = tint_color(c, B_DARKEN_MAX_TINT); + // TODO: Why does BControlLook need this as the base color for the + // scrollbar to look right? + rgb_color baseColor = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), + B_LIGHTEN_1_TINT); - } else { - // Add a usability perk - disable buttons if they would not do anything - // - like a left arrow if the value == fMin -// NOTE: disabled because of too much visual noise/distraction -/* if ((direction == ARROW_LEFT || direction == ARROW_UP) - && (fValue == fMin)) { - use_enabled_colors = false; - } else if ((direction == ARROW_RIGHT || direction == ARROW_DOWN) - && (fValue == fMax)) { - use_enabled_colors = false; - }*/ + be_control_look->DrawButtonBackground(this, rect, updateRect, baseColor, + flags, BControlLook::B_ALL_BORDERS, fOrientation); - if (enabled) { - light = tint_color(c, B_LIGHTEN_MAX_TINT); - dark = tint_color(c, B_DARKEN_1_TINT); - darker = tint_color(c, B_DARKEN_2_TINT); - normal = c; - arrow = tint_color(c, (B_DARKEN_MAX_TINT + B_DARKEN_4_TINT) / 2.0); - } else { - light = tint_color(c, B_LIGHTEN_MAX_TINT); - dark = tint_color(c, B_LIGHTEN_1_TINT); - darker = tint_color(c, B_DARKEN_2_TINT); - normal = tint_color(c, B_LIGHTEN_2_TINT); - arrow = tint_color(c, B_DARKEN_1_TINT); - } - } - - BPoint tri1, tri2, tri3; - float hInset = r.Width() / 3; - float vInset = r.Height() / 3; - r.InsetBy(hInset, vInset); - - switch (direction) { - case ARROW_LEFT: - tri1.Set(r.right, r.top); - tri2.Set(r.right - r.Width() / 1.33, (r.top + r.bottom + 1) /2 ); - tri3.Set(r.right, r.bottom + 1); - break; - case ARROW_RIGHT: - tri1.Set(r.left + 1, r.bottom + 1); - tri2.Set(r.left + 1 + r.Width() / 1.33, (r.top + r.bottom + 1) / 2); - tri3.Set(r.left + 1, r.top); - break; - case ARROW_UP: - tri1.Set(r.left, r.bottom); - tri2.Set((r.left + r.right + 1) / 2, r.bottom - r.Height() / 1.33); - tri3.Set(r.right + 1, r.bottom); - break; - default: - tri1.Set(r.left, r.top + 1); - tri2.Set((r.left + r.right + 1) / 2, r.top + 1 + r.Height() / 1.33); - tri3.Set(r.right + 1, r.top + 1); - break; - } - // offset triangle if down - if (down && fPrivateData->fDoRepeat) { - BPoint offset(1.0, 1.0); - tri1 = tri1 + offset; - tri2 = tri2 + offset; - tri3 = tri3 + offset; - } - - r.InsetBy(-(hInset - 1), -(vInset - 1)); - if (be_control_look != NULL) { - BRect temp(r.InsetByCopy(-1, -1)); - uint32 flags = 0; - if (down) - flags |= BControlLook::B_ACTIVATED; - be_control_look->DrawButtonBackground(this, temp, updateRect, - down ? c : normal, flags, BControlLook::B_ALL_BORDERS, - fOrientation); - } else { - SetHighColor(normal); - FillRect(r); - } - - BShape arrowShape; - arrowShape.MoveTo(tri1); - arrowShape.LineTo(tri2); - arrowShape.LineTo(tri3); - - SetHighColor(arrow); - SetPenSize(ceilf(hInset / 2.0)); - StrokeShape(&arrowShape); - SetPenSize(1.0); - - if (be_control_look != NULL) - return; - - r.InsetBy(-1, -1); - BeginLineArray(4); - if (direction == ARROW_LEFT || direction == ARROW_RIGHT) { - // horizontal - if (doubleArrows && direction == ARROW_LEFT) { - // draw in such a way that the arrows are - // more visually separated - AddLine(BPoint(r.left + 1, r.top), - BPoint(r.right - 1, r.top), light); - AddLine(BPoint(r.right, r.top), - BPoint(r.right, r.bottom), darker); - } else { - AddLine(BPoint(r.left + 1, r.top), - BPoint(r.right, r.top), light); - AddLine(BPoint(r.right, r.top + 1), - BPoint(r.right, r.bottom), dark); - } - AddLine(BPoint(r.left, r.bottom), - BPoint(r.left, r.top), light); - AddLine(BPoint(r.right - 1, r.bottom), - BPoint(r.left + 1, r.bottom), dark); - } else { - // vertical - if (doubleArrows && direction == ARROW_UP) { - // draw in such a way that the arrows are - // more visually separated - AddLine(BPoint(r.left, r.bottom - 1), - BPoint(r.left, r.top), light); - AddLine(BPoint(r.right, r.bottom), - BPoint(r.left, r.bottom), darker); - } else { - AddLine(BPoint(r.left, r.bottom), - BPoint(r.left, r.top), light); - AddLine(BPoint(r.right, r.bottom), - BPoint(r.left + 1, r.bottom), dark); - } - AddLine(BPoint(r.left + 1, r.top), - BPoint(r.right, r.top), light); - AddLine(BPoint(r.right, r.top + 1), - BPoint(r.right, r.bottom - 1), dark); - } - EndLineArray(); + // TODO: Why does BControlLook need this negative inset for the arrow to + // look right? + rect.InsetBy(-1, -1); + be_control_look->DrawArrowShape(this, rect, updateRect, + baseColor, direction, flags, B_DARKEN_MAX_TINT); } diff --git a/src/preferences/appearance/FakeScrollBar.cpp b/src/preferences/appearance/FakeScrollBar.cpp index 7393b946f1..e8a792928e 100644 --- a/src/preferences/appearance/FakeScrollBar.cpp +++ b/src/preferences/appearance/FakeScrollBar.cpp @@ -99,16 +99,16 @@ FakeScrollBar::Draw(BRect updateRect) BRect buttonFrame(bounds.left, bounds.top, bounds.left + bounds.Height(), bounds.bottom); - _DrawArrowButton(ARROW_LEFT, fDoubleArrows, buttonFrame, updateRect); + _DrawArrowButton(ARROW_LEFT, buttonFrame, updateRect); if (fDoubleArrows) { buttonFrame.OffsetBy(bounds.Height() + 1, 0.0); - _DrawArrowButton(ARROW_RIGHT, fDoubleArrows, buttonFrame, + _DrawArrowButton(ARROW_RIGHT, buttonFrame, updateRect); buttonFrame.OffsetTo(bounds.right - ((bounds.Height() * 2) + 1), bounds.top); - _DrawArrowButton(ARROW_LEFT, fDoubleArrows, buttonFrame, + _DrawArrowButton(ARROW_LEFT, buttonFrame, updateRect); thumbBG.left += bounds.Height() * 2 + 2; @@ -119,7 +119,7 @@ FakeScrollBar::Draw(BRect updateRect) } buttonFrame.OffsetTo(bounds.right - bounds.Height(), bounds.top); - _DrawArrowButton(ARROW_RIGHT, fDoubleArrows, buttonFrame, updateRect); + _DrawArrowButton(ARROW_RIGHT, buttonFrame, updateRect); SetDrawingMode(B_OP_COPY); @@ -261,63 +261,21 @@ FakeScrollBar::SetFromScrollBarInfo(const scroll_bar_info &info) void -FakeScrollBar::_DrawArrowButton(int32 direction, bool doubleArrows, BRect r, +FakeScrollBar::_DrawArrowButton(int32 direction, BRect rect, const BRect& updateRect) { - if (!updateRect.Intersects(r)) + if (!updateRect.Intersects(rect)) return; - rgb_color c = ui_color(B_PANEL_BACKGROUND_COLOR); - rgb_color light = tint_color(c, B_LIGHTEN_MAX_TINT); - rgb_color dark = tint_color(c, B_DARKEN_1_TINT); - rgb_color darker = tint_color(c, B_DARKEN_2_TINT); - rgb_color normal = c; - rgb_color arrow = tint_color(c, - (B_DARKEN_MAX_TINT + B_DARKEN_4_TINT) / 2.0); + uint32 flags = 0; - BPoint tri1, tri2, tri3; - float hInset = r.Width() / 3; - float vInset = r.Height() / 3; - r.InsetBy(hInset, vInset); + rgb_color baseColor = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), + B_LIGHTEN_1_TINT); - switch (direction) { - case ARROW_LEFT: - tri1.Set(r.right, r.top); - tri2.Set(r.right - r.Width() / 1.33, (r.top + r.bottom + 1) / 2); - tri3.Set(r.right, r.bottom + 1); - break; + be_control_look->DrawButtonBackground(this, rect, updateRect, baseColor, + flags, BControlLook::B_ALL_BORDERS, B_HORIZONTAL); - case ARROW_RIGHT: - tri1.Set(r.left + 1, r.bottom + 1); - tri2.Set(r.left + 1 + r.Width() / 1.33, (r.top + r.bottom + 1) / 2); - tri3.Set(r.left + 1, r.top); - break; - - case ARROW_UP: - tri1.Set(r.left, r.bottom); - tri2.Set((r.left + r.right + 1) / 2, r.bottom - r.Height() / 1.33); - tri3.Set(r.right + 1, r.bottom); - break; - - default: - tri1.Set(r.left, r.top + 1); - tri2.Set((r.left + r.right + 1) / 2, r.top + 1 + r.Height() / 1.33); - tri3.Set(r.right + 1, r.top + 1); - break; - } - - r.InsetBy(-(hInset - 1), -(vInset - 1)); - BRect temp(r.InsetByCopy(-1, -1)); - be_control_look->DrawButtonBackground(this, temp, updateRect, - normal, 0, BControlLook::B_ALL_BORDERS, B_HORIZONTAL); - - BShape arrowShape; - arrowShape.MoveTo(tri1); - arrowShape.LineTo(tri2); - arrowShape.LineTo(tri3); - - SetHighColor(arrow); - SetPenSize(ceilf(hInset / 2.0)); - StrokeShape(&arrowShape); - SetPenSize(1.0); + rect.InsetBy(-1, -1); + be_control_look->DrawArrowShape(this, rect, updateRect, + baseColor, direction, flags, B_DARKEN_MAX_TINT); } diff --git a/src/preferences/appearance/FakeScrollBar.h b/src/preferences/appearance/FakeScrollBar.h index 74e034b4cd..c02571ed82 100644 --- a/src/preferences/appearance/FakeScrollBar.h +++ b/src/preferences/appearance/FakeScrollBar.h @@ -34,8 +34,7 @@ public: void SetFromScrollBarInfo(const scroll_bar_info &info); private: - void _DrawArrowButton(int32 direction, - bool doubleArrows, BRect r, + void _DrawArrowButton(int32 direction, BRect r, const BRect& updateRect); bool fDrawArrows; From dca92a6c75716c3572e1a37c8a96947c6c3188b3 Mon Sep 17 00:00:00 2001 From: Ryan Leavengood Date: Sun, 3 Mar 2013 17:49:41 -0500 Subject: [PATCH 029/104] Removed unused colors from BScrollBar Draw. --- src/kits/interface/ScrollBar.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/kits/interface/ScrollBar.cpp b/src/kits/interface/ScrollBar.cpp index 44c2382333..1d6fd3988f 100644 --- a/src/kits/interface/ScrollBar.cpp +++ b/src/kits/interface/ScrollBar.cpp @@ -859,21 +859,17 @@ BScrollBar::Draw(BRect updateRect) bool enabled = fPrivateData->fEnabled && fMin < fMax && fProportion < 1.0 && fProportion >= 0.0; - rgb_color light, light1, dark, dark1, dark2, dark4; + rgb_color light, dark, dark1, dark2; if (enabled) { light = tint_color(normal, B_LIGHTEN_MAX_TINT); - light1 = tint_color(normal, B_LIGHTEN_1_TINT); dark = tint_color(normal, B_DARKEN_3_TINT); dark1 = tint_color(normal, B_DARKEN_1_TINT); dark2 = tint_color(normal, B_DARKEN_2_TINT); - dark4 = tint_color(normal, B_DARKEN_4_TINT); } else { light = tint_color(normal, B_LIGHTEN_MAX_TINT); - light1 = normal; dark = tint_color(normal, B_DARKEN_2_TINT); dark1 = tint_color(normal, B_LIGHTEN_2_TINT); dark2 = tint_color(normal, B_LIGHTEN_1_TINT); - dark4 = tint_color(normal, B_DARKEN_3_TINT); } SetDrawingMode(B_OP_OVER); From f44a56ca9a15c0ec2f1fb8c778e30871888499a6 Mon Sep 17 00:00:00 2001 From: Ryan Leavengood Date: Sun, 3 Mar 2013 23:10:51 -0500 Subject: [PATCH 030/104] Add back moving the pen to origin in BControlLook arrow drawing. Removing this did not affect scrollbar arrow buttons, but made the arrows disappear on the Deskbar. Clearly, BControlLook cannot be changed without extensive testing. --- src/kits/interface/ControlLook.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/kits/interface/ControlLook.cpp b/src/kits/interface/ControlLook.cpp index 3e00369bcb..33bbe6231c 100644 --- a/src/kits/interface/ControlLook.cpp +++ b/src/kits/interface/ControlLook.cpp @@ -777,6 +777,8 @@ BControlLook::DrawArrowShape(BView* view, BRect& rect, const BRect& updateRect, float penSize = view->PenSize(); drawing_mode mode = view->DrawingMode(); + view->MovePenTo(BPoint(0, 0)); + view->SetPenSize(ceilf(hInset / 2.0)); view->SetDrawingMode(B_OP_OVER); view->StrokeShape(&arrowShape); From f3ac8bc08985fe1ca60569001f7e914eaa3e62e3 Mon Sep 17 00:00:00 2001 From: John Scipione Date: Sun, 3 Mar 2013 23:36:08 -0500 Subject: [PATCH 031/104] Show the full window title in Deskbar in a tooltip ... if it gets truncated in vertical expando mode. --- src/apps/deskbar/ExpandoMenuBar.cpp | 36 +++++++++++++++++++++-------- src/apps/deskbar/ExpandoMenuBar.h | 2 +- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/src/apps/deskbar/ExpandoMenuBar.cpp b/src/apps/deskbar/ExpandoMenuBar.cpp index 21fbcffb02..6c23498f6e 100644 --- a/src/apps/deskbar/ExpandoMenuBar.cpp +++ b/src/apps/deskbar/ExpandoMenuBar.cpp @@ -412,22 +412,38 @@ TExpandoMenuBar::MouseMoved(BPoint where, uint32 code, const BMessage* message) case B_ENTERED_VIEW: case B_INSIDE_VIEW: { - TTeamMenuItem* item = TeamItemAtPoint(where); - if (item == fLastMousedOverItem) { - // already set the tooltip for this item, break out - break; - } - - if (item == NULL) { + BMenuItem* menuItem; + TTeamMenuItem* item = TeamItemAtPoint(where, &menuItem); + TWindowMenuItem* windowMenuItem + = dynamic_cast(menuItem); + if (item == NULL || menuItem == NULL) { // item is NULL, remove the tooltip and break out fLastMousedOverItem = NULL; SetToolTip((const char*)NULL); break; } + if (menuItem == fLastMousedOverItem) { + // already set the tooltip for this item, break out + break; + } + + if (windowMenuItem != NULL && fBarView->Vertical() + && fBarView->ExpandoState() && item->IsExpanded()) { + // expando mode window menu item + fLastMousedOverItem = menuItem; + if (strcmp(windowMenuItem->Label(), + windowMenuItem->FullTitle()) != 0) { + // label is truncated, set tooltip + SetToolTip(windowMenuItem->FullTitle()); + } else + SetToolTip((const char*)NULL); + break; + } + if (item->HasLabel()) { // item has a visible label, remove the tooltip and break out - fLastMousedOverItem = item; + fLastMousedOverItem = menuItem; SetToolTip((const char*)NULL); break; } @@ -435,8 +451,8 @@ TExpandoMenuBar::MouseMoved(BPoint where, uint32 code, const BMessage* message) // new item, set the tooltip to the item name SetToolTip(item->Name()); - // save the current item for the next MouseMoved() call - fLastMousedOverItem = item; + // save the current menuitem for the next MouseMoved() call + fLastMousedOverItem = menuItem; break; } diff --git a/src/apps/deskbar/ExpandoMenuBar.h b/src/apps/deskbar/ExpandoMenuBar.h index 79f628cda8..b50a085d08 100644 --- a/src/apps/deskbar/ExpandoMenuBar.h +++ b/src/apps/deskbar/ExpandoMenuBar.h @@ -107,7 +107,7 @@ class TExpandoMenuBar : public BMenuBar { TTeamMenuItem* fPreviousDragTargetItem; - TTeamMenuItem* fLastMousedOverItem; + BMenuItem* fLastMousedOverItem; BMenuItem* fLastClickItem; static bool sDoMonitor; From b09c265cb409f752fc611da4132ab6fbbee9ecba Mon Sep 17 00:00:00 2001 From: John Scipione Date: Mon, 4 Mar 2013 04:45:06 -0500 Subject: [PATCH 032/104] Update bitmap downscaling for BeOS icons. Implemented a simple down sampling algorithm in the scale_down() function. For non-integer scaling first scale up using the scale2x, scale3x, or scale4x algorithm doubling, tripling, or quadrupling the icon then use the downscaling algorithm to shrink to the desired size. This produces nicer looking results than bilinear scaling alone. Note that this only applies to bitmap-based BeOS icons and not vector-based HVIF icons. --- src/libs/icon/IconUtils.cpp | 165 ++++++++++++++++++++++++++++++------ 1 file changed, 137 insertions(+), 28 deletions(-) diff --git a/src/libs/icon/IconUtils.cpp b/src/libs/icon/IconUtils.cpp index 0971c02007..6d546e2a33 100644 --- a/src/libs/icon/IconUtils.cpp +++ b/src/libs/icon/IconUtils.cpp @@ -1,11 +1,12 @@ /* - * Copyright 2006-2011, Haiku. All rights reserved. + * Copyright 2006-2013, Haiku. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: - * Stephan Aßmus - * Ingo Weinhold - * John Scipione + * Stephan Aßmus, superstippi@gmx.de + * Axel Dörfler, axeld@pinc-software.de + * John Scipione, jscipione@gmail.com + * Ingo Weinhold, bonefish@cs.tu-berlin.de */ @@ -101,6 +102,70 @@ scale_bilinear(uint8* bits, int32 srcWidth, int32 srcHeight, int32 dstWidth, } +static void +scale_down(const uint8* srcBits, uint8* dstBits, int32 srcWidth, int32 srcHeight, + int32 dstWidth, int32 dstHeight) +{ + int32 l; + int32 c; + float t; + float u; + float tmp; + float d1, d2, d3, d4; + // coefficients + uint32 p1, p2, p3, p4; + // nearby pixels + uint8 red, green, blue, alpha; + // color components + + for (int32 i = 0; i < dstHeight; i++) { + for (int32 j = 0; j < dstWidth; j++) { + tmp = (float)(i) / (float)(dstHeight - 1) * (srcHeight - 1); + l = (int32)floorf(tmp); + if (l < 0) + l = 0; + else if (l >= srcHeight - 1) + l = srcHeight - 2; + u = tmp - l; + + tmp = (float)(j) / (float)(dstWidth - 1) * (srcWidth - 1); + c = (int32)floorf(tmp); + if (c < 0) + c = 0; + else if (c >= srcWidth - 1) + c = srcWidth - 2; + t = tmp - c; + + // coefficients + d1 = (1 - t) * (1 - u); + d2 = t * (1 - u); + d3 = t * u; + d4 = (1 - t) * u; + + // nearby pixels + p1 = *((uint32*)srcBits + (l * srcWidth) + c); + p2 = *((uint32*)srcBits + (l * srcWidth) + c + 1); + p3 = *((uint32*)srcBits + ((l + 1)* srcWidth) + c + 1); + p4 = *((uint32*)srcBits + ((l + 1)* srcWidth) + c); + + // color components + blue = (uint8)p1 * d1 + (uint8)p2 * d2 + (uint8)p3 * d3 + + (uint8)p4 * d4; + green = (uint8)(p1 >> 8) * d1 + (uint8)(p2 >> 8) * d2 + + (uint8)(p3 >> 8) * d3 + (uint8)(p4 >> 8) * d4; + red = (uint8)(p1 >> 16) * d1 + (uint8)(p2 >> 16) * d2 + + (uint8)(p3 >> 16) * d3 + (uint8)(p4 >> 16) * d4; + alpha = (uint8)(p1 >> 24) * d1 + (uint8)(p2 >> 24) * d2 + + (uint8)(p3 >> 24) * d3 + (uint8)(p4 >> 24) * d4; + + // destination RGBA pixel + *((uint32*)dstBits + (i * dstWidth) + j) + = (alpha << 24) | (red << 16) | (green << 8) | (blue); + } + } +} + + static void scale2x(const uint8* srcBits, uint8* dstBits, int32 srcWidth, int32 srcHeight, int32 srcBPR, int32 dstBPR) @@ -584,6 +649,39 @@ BIconUtils::ConvertFromCMAP8(const uint8* src, uint32 width, uint32 height, uint8* dst = (uint8*)result->Bits(); uint32 dstBPR = result->BytesPerRow(); + // check for integer multiple scale + if (dstWidth == 2 * width && dstHeight == 2 * height) { + // scale2x + BBitmap* converted = new BBitmap(BRect(0, 0, width - 1, height - 1), + result->ColorSpace()); + converted->ImportBits(src, height * srcBPR, srcBPR, 0, B_CMAP8); + uint8* convertedBits = (uint8*)converted->Bits(); + int32 convertedBPR = converted->BytesPerRow(); + scale2x(convertedBits, dst, width, height, convertedBPR, dstBPR); + delete converted; + return B_OK; + } else if (dstWidth == 3 * width && dstHeight == 3 * height) { + // scale3x + BBitmap* converted = new BBitmap(BRect(0, 0, width - 1, height - 1), + result->ColorSpace()); + converted->ImportBits(src, height * srcBPR, srcBPR, 0, B_CMAP8); + uint8* convertedBits = (uint8*)converted->Bits(); + int32 convertedBPR = converted->BytesPerRow(); + scale3x(convertedBits, dst, width, height, convertedBPR, dstBPR); + delete converted; + return B_OK; + } else if (dstWidth == 4 * width && dstHeight == 4 * height) { + // scale4x + BBitmap* converted = new BBitmap(BRect(0, 0, width - 1, height - 1), + result->ColorSpace()); + converted->ImportBits(src, height * srcBPR, srcBPR, 0, B_CMAP8); + uint8* convertedBits = (uint8*)converted->Bits(); + int32 convertedBPR = converted->BytesPerRow(); + scale4x(convertedBits, dst, width, height, convertedBPR, dstBPR); + delete converted; + return B_OK; + } + const rgb_color* colorMap = system_colors()->color_list; if (colorMap == NULL) return B_NO_INIT; @@ -591,6 +689,7 @@ BIconUtils::ConvertFromCMAP8(const uint8* src, uint32 width, uint32 height, const uint8* srcStart = src; uint8* dstStart = dst; + // convert from B_CMAP8 to B_RGB(A)32 without scaling for (uint32 y = 0; y < height; y++) { uint32* d = (uint32*)dst; const uint8* s = src; @@ -605,35 +704,45 @@ BIconUtils::ConvertFromCMAP8(const uint8* src, uint32 width, uint32 height, dst += dstBPR; } + if (width == dstWidth && height == dstHeight) + return B_OK; + // reset src and dst back to their original locations src = srcStart; dst = dstStart; - if ((dstWidth == 2 * width && dstHeight == 2 * height) - || (dstWidth == 3 * width && dstHeight == 3 * height) - || (dstWidth == 4 * width && dstHeight == 4 * height)) { - // we can do some special scaling here - - // first convert to B_RGBA32 - BBitmap* converted - = new BBitmap(BRect(0, 0, width - 1, height - 1), - result->ColorSpace()); - converted->ImportBits(src, height * srcBPR, srcBPR, 0, B_CMAP8); - uint8* convertedBits = (uint8*)converted->Bits(); - int32 convertedBPR = converted->BytesPerRow(); - - // scale using the scale2x/scale3x/scale4x algorithm - if (dstWidth == 2 * width && dstHeight == 2 * height) - scale2x(convertedBits, dst, width, height, convertedBPR, dstBPR); - else if (dstWidth == 3 * width && dstHeight == 3 * height) - scale3x(convertedBits, dst, width, height, convertedBPR, dstBPR); - else if (dstWidth == 4 * width && dstHeight == 4 * height) - scale4x(convertedBits, dst, width, height, convertedBPR, dstBPR); - - // cleanup - delete converted; + if (dstWidth > width && dstHeight > height + && dstWidth < 2 * width && dstHeight < 2 * height) { + // scale2x then downscale + BBitmap* temp = new BBitmap(BRect(0, 0, width * 2 - 1, height * 2 - 1), + result->ColorSpace()); + uint8* tempBits = (uint8*)temp->Bits(); + uint32 tempBPR = temp->BytesPerRow(); + scale2x(dst, tempBits, width, height, dstBPR, tempBPR); + scale_down(tempBits, dst, width * 2, height * 2, dstWidth, dstHeight); + delete temp; + } else if (dstWidth > 2 * width && dstHeight > 2 * height + && dstWidth < 3 * width && dstHeight < 3 * height) { + // scale3x then downscale + BBitmap* temp = new BBitmap(BRect(0, 0, width * 3 - 1, height * 3 - 1), + result->ColorSpace()); + uint8* tempBits = (uint8*)temp->Bits(); + uint32 tempBPR = temp->BytesPerRow(); + scale3x(dst, tempBits, width, height, dstBPR, tempBPR); + scale_down(tempBits, dst, width * 3, height * 3, dstWidth, dstHeight); + delete temp; + } else if (dstWidth > 3 * width && dstHeight > 3 * height + && dstWidth < 4 * width && dstHeight < 4 * height) { + // scale4x then downscale + BBitmap* temp = new BBitmap(BRect(0, 0, width * 4 - 1, height * 4 - 1), + result->ColorSpace()); + uint8* tempBits = (uint8*)temp->Bits(); + uint32 tempBPR = temp->BytesPerRow(); + scale4x(dst, tempBits, width, height, dstBPR, tempBPR); + scale_down(tempBits, dst, width * 3, height * 3, dstWidth, dstHeight); + delete temp; } else { - // bilinear scaling + // fall back to bilinear scaling scale_bilinear(dst, width, height, dstWidth, dstHeight, dstBPR); } From afecfa9ca86a2431c6ff990e6ccb24e3f807699d Mon Sep 17 00:00:00 2001 From: John Scipione Date: Mon, 4 Mar 2013 12:56:12 -0500 Subject: [PATCH 033/104] A few more bitmap icon updates, edge cases. * Support downscaling icons to a size smaller than the source. * For > 4x icon scaling do a scale4x followed by a bilinear scale. Note that I tried to do a combination of scale2x/scale3x with bilinear scaling and the results were worse than scale2x/scale3x with down scaling. The 24x24 icon case looks pretty bad either using bilinear or scale2x followed by a downscale because I am currently upscaling the 16x16 icon in Deskbar (we didn't up until now support bitmap icon downscaling so I had no choice). It might be a better idea to downscale the 32x32 version instead. Note that all of the above has to do with bitmap icons ONLY and none of it applies to HVIF icons that scale beautifully without these tricks. --- src/libs/icon/IconUtils.cpp | 55 ++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 29 deletions(-) diff --git a/src/libs/icon/IconUtils.cpp b/src/libs/icon/IconUtils.cpp index 6d546e2a33..81630e2bfc 100644 --- a/src/libs/icon/IconUtils.cpp +++ b/src/libs/icon/IconUtils.cpp @@ -641,43 +641,29 @@ BIconUtils::ConvertFromCMAP8(const uint8* src, uint32 width, uint32 height, uint32 dstWidth = result->Bounds().IntegerWidth() + 1; uint32 dstHeight = result->Bounds().IntegerHeight() + 1; - if (dstWidth < width || dstHeight < height) { - // TODO: implement down scaling - return B_ERROR; - } - uint8* dst = (uint8*)result->Bits(); uint32 dstBPR = result->BytesPerRow(); - // check for integer multiple scale - if (dstWidth == 2 * width && dstHeight == 2 * height) { - // scale2x + // check for downscaling or integer multiple scaling + if (dstWidth < width || dstHeight < height + || dstWidth == 2 * width && dstHeight == 2 * height + || dstWidth == 3 * width && dstHeight == 3 * height + || dstWidth == 4 * width && dstHeight == 4 * height) { BBitmap* converted = new BBitmap(BRect(0, 0, width - 1, height - 1), result->ColorSpace()); converted->ImportBits(src, height * srcBPR, srcBPR, 0, B_CMAP8); uint8* convertedBits = (uint8*)converted->Bits(); int32 convertedBPR = converted->BytesPerRow(); - scale2x(convertedBits, dst, width, height, convertedBPR, dstBPR); - delete converted; - return B_OK; - } else if (dstWidth == 3 * width && dstHeight == 3 * height) { - // scale3x - BBitmap* converted = new BBitmap(BRect(0, 0, width - 1, height - 1), - result->ColorSpace()); - converted->ImportBits(src, height * srcBPR, srcBPR, 0, B_CMAP8); - uint8* convertedBits = (uint8*)converted->Bits(); - int32 convertedBPR = converted->BytesPerRow(); - scale3x(convertedBits, dst, width, height, convertedBPR, dstBPR); - delete converted; - return B_OK; - } else if (dstWidth == 4 * width && dstHeight == 4 * height) { - // scale4x - BBitmap* converted = new BBitmap(BRect(0, 0, width - 1, height - 1), - result->ColorSpace()); - converted->ImportBits(src, height * srcBPR, srcBPR, 0, B_CMAP8); - uint8* convertedBits = (uint8*)converted->Bits(); - int32 convertedBPR = converted->BytesPerRow(); - scale4x(convertedBits, dst, width, height, convertedBPR, dstBPR); + + if (dstWidth < width || dstHeight < height) + scale_down(convertedBits, dst, width, height, dstWidth, dstHeight); + else if (dstWidth == 2 * width && dstHeight == 2 * height) + scale2x(convertedBits, dst, width, height, convertedBPR, dstBPR); + else if (dstWidth == 3 * width && dstHeight == 3 * height) + scale3x(convertedBits, dst, width, height, convertedBPR, dstBPR); + else if (dstWidth == 4 * width && dstHeight == 4 * height) + scale4x(convertedBits, dst, width, height, convertedBPR, dstBPR); + delete converted; return B_OK; } @@ -741,6 +727,17 @@ BIconUtils::ConvertFromCMAP8(const uint8* src, uint32 width, uint32 height, scale4x(dst, tempBits, width, height, dstBPR, tempBPR); scale_down(tempBits, dst, width * 3, height * 3, dstWidth, dstHeight); delete temp; + } else if (dstWidth > 4 * width && dstHeight > 4 * height) { + // scale4x then bilinear + BBitmap* temp = new BBitmap(BRect(0, 0, width * 4 - 1, height * 4 - 1), + result->ColorSpace()); + uint8* tempBits = (uint8*)temp->Bits(); + uint32 tempBPR = temp->BytesPerRow(); + scale4x(dst, tempBits, width, height, dstBPR, tempBPR); + result->ImportBits(tempBits, height * tempBPR, tempBPR, 0, + temp->ColorSpace()); + scale_bilinear(dst, width, height, dstWidth, dstHeight, dstBPR); + delete temp; } else { // fall back to bilinear scaling scale_bilinear(dst, width, height, dstWidth, dstHeight, dstBPR); From 880e147bd97b1606c3abe7b2bde9cdd93fa1c3a2 Mon Sep 17 00:00:00 2001 From: John Scipione Date: Mon, 4 Mar 2013 19:24:31 -0500 Subject: [PATCH 034/104] Node Monitor documentation updates to stop_watching(). * Add a note to stop_watching() about the asynchronous nature of node monitoring and its consequences. * Also update the breif description and parameters of stop_watching(). * Detail the return values of stop_watching() a bit better. * Add a note (an \attention actually) to B_STOP_WATCHING flag. * Fix a spelling mistake and other minor fixes. --- docs/user/storage/NodeMonitor.dox | 46 +++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 11 deletions(-) diff --git a/docs/user/storage/NodeMonitor.dox b/docs/user/storage/NodeMonitor.dox index 7cc288c43b..3df7e78ea5 100644 --- a/docs/user/storage/NodeMonitor.dox +++ b/docs/user/storage/NodeMonitor.dox @@ -35,6 +35,9 @@ \var B_STOP_WATCHING Flag for watch_node(). Unsubscribe from watching a node. + + \attention \c B_STOP_WATCHING does not apply to volume watching, you must + call stop_watching() instead. */ @@ -329,13 +332,13 @@ - \c B_WATCH_ALL - \c B_WATCH_MOUNT - Note, that the latter two cases are not mutual exclusive, i.e. mount and + Note that the latter two cases are not mutual exclusive, i.e. mount and node watching can be requested with a single call. \param node node_ref referring to the node to be watched. May be \c NULL, if only mount watching is requested. \param flags Flags indicating the actions to be performed. - \param target Messenger referring to the target. Must be valid. + \param target BMessenger object referring to the \a target. \return \c B_OK if everything went fine, an error code otherwise. */ @@ -368,7 +371,7 @@ - \c B_WATCH_ALL - \c B_WATCH_MOUNT - Note, that the latter two cases are not mutual exlusive, i.e. mount and + Note that the latter two cases are not mutual exclusive, i.e. mount and node watching can be requested with a single call. \param node node_ref referring to the node to be watched. May be \c NULL, @@ -387,20 +390,41 @@ \fn status_t stop_watching(BMessenger target) \brief Unsubscribes \a target from node and mount monitoring. - \param target Messenger referring to the target. Must be valid. + You may still receive notification messages after calling stop_watching() + because while node monitoring is asynchronous and all changes are atomic, + message sending is not atomic so there is a lag time from when you + stop monitoring and when the message is received in your message receiving + thread. You can check the timestamp of the message to determine if + it was sent after stop_watching() was called. - \return \c B_OK if everything went fine, an error code otherwise. + \param target BMessenger object referring to the \a target. + + \return A status code. + \retval B_OK Stopped sending notification messages to the \a target. + \retval B_BAD_VALUE \a target was invalid. + \retval B_ENTRY_NOT_FOUND Node not found. */ /*! \fn status_t stop_watching(const BHandler *handler, const BLooper *looper) - \brief Unsubscribes \a target from node and mount monitoring. + \brief Unsubscribes \a handler or \a looper target from node and mount + monitoring. - \param handler The target handler. May be \c NULL, if \a looper is not - \c NULL. Then the preferred handler of the looper is targeted. - \param looper The target looper. May be \c NULL, if \a handler is not - \c NULL. Then the handler's looper is the target looper. + You may still receive notification messages after calling stop_watching() + because while node monitoring is asynchronous and all changes are atomic, + message sending is not atomic so there is a lag time from when you + stop monitoring and when the message is received in your message receiving + thread. You can check the timestamp of the message to determine if + it was sent after stop_watching() was called. - \return \c B_OK if everything went fine, an error code otherwise. + \param handler The target handler, may be \c NULL. If \a looper is not + \c NULL then the looper's preferred handler is targeted. + \param looper The target looper, may be \c NULL. If \a handler is not + \c NULL then the handler's looper is targeted. + + \return A status code. + \retval B_OK Stopped sending notification messages to the target. + \retval B_BAD_VALUE Target from \a handler or \a looper was invalid. + \retval B_ENTRY_NOT_FOUND Node not found. */ From ff9b4ff8c918d6e8934b3e0d58bc31fce99a6cf2 Mon Sep 17 00:00:00 2001 From: John Scipione Date: Mon, 4 Mar 2013 22:22:03 -0500 Subject: [PATCH 035/104] Lock BMenuBar::_Track() atomically. Fixes #9481 --- src/kits/interface/MenuBar.cpp | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/kits/interface/MenuBar.cpp b/src/kits/interface/MenuBar.cpp index 8c7dc13fda..b582d87087 100644 --- a/src/kits/interface/MenuBar.cpp +++ b/src/kits/interface/MenuBar.cpp @@ -557,24 +557,22 @@ BMenuBar::_Track(int32* action, int32 startIndex, bool showMenu) { // TODO: Cleanup, merge some "if" blocks if possible fChosenItem = NULL; - - BWindow* window = Window(); fState = MENU_STATE_TRACKING; BPoint where; uint32 buttons; - if (window->Lock()) { + if (LockLooper()) { if (startIndex != -1) { be_app->ObscureCursor(); _SelectItem(ItemAt(startIndex), true, false); } GetMouse(&where, &buttons); - window->Unlock(); + UnlockLooper(); } while (fState != MENU_STATE_CLOSED) { bigtime_t snoozeAmount = 40000; - if (Window() == NULL || !window->Lock()) + if (!LockLooper()) break; BMenuItem* menuItem = NULL; @@ -587,7 +585,7 @@ BMenuBar::_Track(int32* action, int32 startIndex, bool showMenu) // call _Track() from the selected sub-menu when the mouse cursor // is over its window BMenu* menu = fSelected->Submenu(); - window->Unlock(); + UnlockLooper(); snoozeAmount = 30000; bool wasSticky = _IsStickyMode(); menu->_SetStickyMode(wasSticky); @@ -602,9 +600,9 @@ BMenuBar::_Track(int32* action, int32 startIndex, bool showMenu) // where to store the current mouse position ? // (Or just use the BView mouse hooks) BPoint newWhere; - if (window->Lock()) { + if (LockLooper()) { GetMouse(&newWhere, &buttons); - window->Unlock(); + UnlockLooper(); } // This code is needed to make menus @@ -619,7 +617,7 @@ BMenuBar::_Track(int32* action, int32 startIndex, bool showMenu) } else fState = MENU_STATE_CLOSED; } - if (!window->Lock()) + if (!LockLooper()) break; } else if (menuItem != NULL) { if (menuItem->Submenu() != NULL && menuItem != fSelected) { @@ -642,7 +640,7 @@ BMenuBar::_Track(int32* action, int32 startIndex, bool showMenu) fState = MENU_STATE_TRACKING; } - window->Unlock(); + UnlockLooper(); if (fState != MENU_STATE_CLOSED) { // If user doesn't move the mouse, loop here, @@ -680,14 +678,14 @@ BMenuBar::_Track(int32* action, int32 startIndex, bool showMenu) } } - if (window->Lock()) { + if (LockLooper()) { if (fSelected != NULL) _SelectItem(NULL); if (fChosenItem != NULL) fChosenItem->Invoke(); _RestoreFocus(); - window->Unlock(); + UnlockLooper(); } if (_IsStickyMode()) From a95895186d31c350fb8a67b030e062c946e852ca Mon Sep 17 00:00:00 2001 From: Ryan Leavengood Date: Mon, 4 Mar 2013 22:55:48 -0500 Subject: [PATCH 036/104] Change the cursor hiding so it isn't done constantly when enabled. --- src/apps/showimage/ShowImageView.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/apps/showimage/ShowImageView.cpp b/src/apps/showimage/ShowImageView.cpp index 3f8899575f..695b000ac0 100644 --- a/src/apps/showimage/ShowImageView.cpp +++ b/src/apps/showimage/ShowImageView.cpp @@ -244,13 +244,16 @@ ShowImageView::Pulse() } if (fHideCursor && !fHasSelection && !fShowingPopUpMenu && fIsActiveWin) { - if (fHideCursorCountDown <= 0) { + if (fHideCursorCountDown == 0) { + // Go negative so this isn't triggered again + fHideCursorCountDown--; + BPoint mousePos; uint32 buttons; GetMouse(&mousePos, &buttons, false); if (Bounds().Contains(mousePos)) be_app->ObscureCursor(); - } else + } else if (fHideCursorCountDown > 0) fHideCursorCountDown--; } From fa392c2a24c12e160de5d29fadf8a4a52deb5804 Mon Sep 17 00:00:00 2001 From: Ryan Leavengood Date: Tue, 5 Mar 2013 08:59:54 -0500 Subject: [PATCH 037/104] Remove unused ShowImage Undo code. --- src/apps/showimage/Jamfile | 1 - src/apps/showimage/ShowImageUndo.cpp | 93 -------------------------- src/apps/showimage/ShowImageUndo.h | 63 ----------------- src/apps/showimage/ShowImageView.cpp | 45 ------------- src/apps/showimage/ShowImageView.h | 3 - src/apps/showimage/ShowImageWindow.cpp | 14 ---- 6 files changed, 219 deletions(-) delete mode 100644 src/apps/showimage/ShowImageUndo.cpp delete mode 100644 src/apps/showimage/ShowImageUndo.h diff --git a/src/apps/showimage/Jamfile b/src/apps/showimage/Jamfile index 87aa25bced..3ff8552b08 100644 --- a/src/apps/showimage/Jamfile +++ b/src/apps/showimage/Jamfile @@ -17,7 +17,6 @@ Application ShowImage : ShowImageApp.cpp ShowImageSettings.cpp ShowImageStatusView.cpp - ShowImageUndo.cpp ShowImageView.cpp ShowImageWindow.cpp ToolBarIcons.cpp diff --git a/src/apps/showimage/ShowImageUndo.cpp b/src/apps/showimage/ShowImageUndo.cpp deleted file mode 100644 index d4c2ad7cf8..0000000000 --- a/src/apps/showimage/ShowImageUndo.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 2003-2009 Haiku Inc. All rights reserved. - * Distributed under the terms of the MIT License. - * - * Authors: - * Michael Wilber - */ - -#include "ShowImageUndo.h" - -#include -#include - - -ShowImageUndo::ShowImageUndo() - : - fWindow(NULL), - fUndoType(0), - fRestore(NULL), - fSelection(NULL) -{ -} - - -ShowImageUndo::~ShowImageUndo() -{ - InternalClear(); -} - - -void -ShowImageUndo::InternalClear() -{ - fUndoType = 0; - delete fRestore; - fRestore = NULL; - delete fSelection; - fSelection = NULL; -} - - -void -ShowImageUndo::Clear() -{ - InternalClear(); - SendUndoStateMessage(false); -} - - -void -ShowImageUndo::SendUndoStateMessage(bool bCanUndo) -{ - if (fWindow) { - if (!fWindow->IsLocked()) { - fprintf(stderr, - "ShowImageUndo::SendUndoStateMessage: window must be locked!"); - exit(-1); - } - BMessage msg(MSG_UNDO_STATE); - msg.AddBool("can_undo", bCanUndo); - fWindow->PostMessage(&msg); - } -} - - -void -ShowImageUndo::SetTo(BRect rect, BBitmap* restore, BBitmap* selection) -{ - // NOTE: THIS FUNCTION DOES NOT MAKE COPIES OF THE BITMAPS PASSED TO IT - InternalClear(); - - fUndoType = UNDO_UNDO; - fRect = rect; - fRestore = restore; - fSelection = selection; - - SendUndoStateMessage(true); -} - - -void -ShowImageUndo::Undo(BRect rect, BBitmap* restore, BBitmap* selection) -{ - // NOTE: THIS FUNCTION DOES NOT MAKE COPIES OF THE BITMAPS PASSED TO IT - fUndoType = UNDO_REDO; - fRect = rect; - delete fRestore; - fRestore = restore; - fSelection = selection; - // NOTE: fSelection isn't deleted here because ShowImageView - // takes ownership of it during an Undo -} - diff --git a/src/apps/showimage/ShowImageUndo.h b/src/apps/showimage/ShowImageUndo.h deleted file mode 100644 index 7cfc8d8159..0000000000 --- a/src/apps/showimage/ShowImageUndo.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2003-2009 Haiku Inc. All rights reserved. - * Distributed under the terms of the MIT License. - * - * Authors: - * Michael Wilber - */ -#ifndef SHOW_IMAGE_UNDO_H -#define SHOW_IMAGE_UNDO_H - - -#include -#include -#include -#include -#include - -#include "ShowImageConstants.h" - - -// for Undo -#define UNDO_UNDO 1 -#define UNDO_REDO 2 - - -class ShowImageUndo { -public: - ShowImageUndo(); - ~ShowImageUndo(); - - void SetWindow(BWindow* win) { fWindow = win; } - - void Clear(); - - // NOTE: THESE TWO FUNCTIONS DO NOT MAKE COPIES OF THE - // BITMAPS PASSED TO THEM - void SetTo(BRect rect, BBitmap* restore, BBitmap* selection); - void Undo(BRect rect, BBitmap* restore, BBitmap* selection); - - int32 GetType() { return fUndoType; } - BRect GetRect() { return fRect; } - BBitmap* GetRestoreBitmap() { return fRestore; } - BBitmap* GetSelectionBitmap() { return fSelection; } - -private: - void InternalClear(); - void SendUndoStateMessage(bool bCanUndo); - - BWindow* fWindow; - // Window to which notification messages are sent - int32 fUndoType; - // Nothing, Undo or Redo - BRect fRect; - // Area of background bitmap where change took place - BBitmap* fRestore; - // Changed portion of background bitmap, before change took place - BBitmap* fSelection; - // Selection present before change took place -}; - - -#endif // SHOW_IMAGE_UNDO_H - diff --git a/src/apps/showimage/ShowImageView.cpp b/src/apps/showimage/ShowImageView.cpp index 695b000ac0..3a39f8872b 100644 --- a/src/apps/showimage/ShowImageView.cpp +++ b/src/apps/showimage/ShowImageView.cpp @@ -368,7 +368,6 @@ ShowImageView::SetImage(const entry_ref* ref, BBitmap* bitmap, BitmapOwner* bitmapOwner) { // Delete the old one, and clear everything - fUndo.Clear(); _SetHasSelection(false); fCreatingSelection = false; _DeleteBitmap(); @@ -534,7 +533,6 @@ void ShowImageView::AttachedToWindow() { FitToBounds(); - fUndo.SetWindow(Window()); FixupScrollBars(); } @@ -1479,47 +1477,6 @@ ShowImageView::SetSelectionMode(bool selectionMode) } -void -ShowImageView::Undo() -{ - int32 undoType = fUndo.GetType(); - if (undoType != UNDO_UNDO && undoType != UNDO_REDO) - return; - - // backup current selection - BRect undoneSelRect; - BBitmap* undoneSelection; - undoneSelRect = fSelectionBox.Bounds(); - undoneSelection = _CopySelection(); - - if (undoType == UNDO_UNDO) { - BBitmap* undoRestore; - undoRestore = fUndo.GetRestoreBitmap(); - if (undoRestore) - _MergeWithBitmap(undoRestore, fUndo.GetRect()); - } - - // restore previous image/selection - BBitmap* undoSelection; - undoSelection = fUndo.GetSelectionBitmap(); - // NOTE: ShowImageView is responsible for deleting this bitmap - // (Which it will, as it would with a fSelectionBitmap that it - // allocated itself) - if (!undoSelection) - _SetHasSelection(false); - else { - fCopyFromRect = BRect(); - fSelectionBox.SetBounds(this, fUndo.GetRect()); - _SetHasSelection(true); - fSelectionBitmap = undoSelection; - } - - fUndo.Undo(undoneSelRect, NULL, undoneSelection); - - Invalidate(); -} - - void ShowImageView::SelectAll() { @@ -1732,7 +1689,6 @@ ShowImageView::_DoImageOperation(ImageProcessor::operation op, bool quiet) void ShowImageView::_UserDoImageOperation(ImageProcessor::operation op, bool quiet) { - fUndo.Clear(); _DoImageOperation(op, quiet); } @@ -1773,7 +1729,6 @@ ShowImageView::ResizeImage(int w, int h) // remove selection _SetHasSelection(false); - fUndo.Clear(); _DeleteBitmap(); fBitmap = scaled; diff --git a/src/apps/showimage/ShowImageView.h b/src/apps/showimage/ShowImageView.h index bdf4d106f6..33f312770e 100644 --- a/src/apps/showimage/ShowImageView.h +++ b/src/apps/showimage/ShowImageView.h @@ -24,7 +24,6 @@ #include "Filter.h" #include "SelectionBox.h" -#include "ShowImageUndo.h" class BitmapOwner; @@ -82,7 +81,6 @@ public: void SetSelectionMode(bool selectionMode); bool IsSelectionModeEnabled() const { return fSelectionMode; } - void Undo(); void SelectAll(); void ClearSelection(); @@ -182,7 +180,6 @@ private: void _ShowToolBarIfEnabled(bool show); private: - ShowImageUndo fUndo; entry_ref fCurrentRef; BitmapOwner* fBitmapOwner; diff --git a/src/apps/showimage/ShowImageWindow.cpp b/src/apps/showimage/ShowImageWindow.cpp index 8464ed20d7..fbd6a54663 100644 --- a/src/apps/showimage/ShowImageWindow.cpp +++ b/src/apps/showimage/ShowImageWindow.cpp @@ -418,8 +418,6 @@ ShowImageWindow::_AddMenus(BMenuBar* bar) bar->AddItem(menu); menu = new BMenu(B_TRANSLATE("Edit")); - _AddItemMenu(menu, B_TRANSLATE("Undo"), B_UNDO, 'Z', 0, this, false); - menu->AddSeparatorItem(); _AddItemMenu(menu, B_TRANSLATE("Copy"), B_COPY, 'C', 0, this, false); menu->AddSeparatorItem(); _AddItemMenu(menu, B_TRANSLATE("Selection mode"), MSG_SELECTION_MODE, 0, 0, @@ -767,18 +765,6 @@ ShowImageWindow::MessageReceived(BMessage* message) break; } - case MSG_UNDO_STATE: - { - bool enable; - if (message->FindBool("can_undo", &enable) == B_OK) - _EnableMenuItem(fBar, B_UNDO, enable); - break; - } - - case B_UNDO: - fImageView->Undo(); - break; - case B_COPY: fImageView->CopySelectionToClipboard(); break; From 3b3884d9eec9b931efab12d5b2b47d7e33827a65 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Wed, 16 Nov 2011 13:53:36 +0100 Subject: [PATCH 038/104] =?UTF-8?q?KeyStore=20and=20Key=20interface/stubs?= =?UTF-8?q?=20draft=20per=20Axel=20D=C3=B6rfler.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A draft API and (mostly) stubs to back it up. Initial import of yet unmodified sources. --- headers/os/app/Key.h | 93 ++++++++++++++ headers/os/app/KeyStore.h | 94 ++++++++++++++ src/kits/app/Jamfile | 4 + src/kits/app/Key.cpp | 258 ++++++++++++++++++++++++++++++++++++++ src/kits/app/KeyStore.cpp | 236 ++++++++++++++++++++++++++++++++++ 5 files changed, 685 insertions(+) create mode 100644 headers/os/app/Key.h create mode 100644 headers/os/app/KeyStore.h create mode 100644 src/kits/app/Key.cpp create mode 100644 src/kits/app/KeyStore.cpp diff --git a/headers/os/app/Key.h b/headers/os/app/Key.h new file mode 100644 index 0000000000..e3139f4f01 --- /dev/null +++ b/headers/os/app/Key.h @@ -0,0 +1,93 @@ +/* + * Copyright 2011, Haiku, Inc. + * Distributed under the terms of the MIT License. + */ +#ifndef _KEY_H +#define _KEY_H + + +#include +#include +#include +#include + + +enum BPasswordType { + B_WEB_PASSWORD, + B_NETWORK_PASSWORD, + B_VOLUME_PASSWORD, + B_GENERIC_PASSWORD +}; + + +class BKey { +public: + BKey(); + BKey(BPasswordType type, + const char* identifier, + const char* password); + BKey(BPasswordType type, + const char* identifier, + const char* secondaryIdentifier, + const char* password); + BKey(BKey& other); + virtual ~BKey(); + + void Unset(); + + status_t SetTo(BPasswordType type, + const char* identifier, + const char* password); + status_t SetTo(BPasswordType type, + const char* identifier, + const char* secondaryIdentifier, + const char* password); + + status_t SetPassword(const char* password); + const char* Password() const; + + status_t SetKey(const uint8* data, size_t length); + size_t KeyLength() const; + status_t GetKey(uint8* buffer, + size_t bufferLength) const; + + void SetIdentifier(const char* identifier); + const char* Identifier() const; + + void SetSecondaryIdentifier(const char* identifier); + const char* SecondaryIdentifier() const; + + void SetType(BPasswordType type); + BPasswordType Type() const; + + void SetData(const BMessage& data); + const BMessage& Data() const; + + const char* Owner() const; + bigtime_t CreationTime() const; + bool IsRegistered() const; + +// TODO: move to BKeyStore + status_t GetNextApplication(uint32& cookie, + BString& signature) const; + status_t RemoveApplication(const char* signature); + + BKey& operator=(const BKey& other); + + bool operator==(const BKey& other) const; + bool operator!=(const BKey& other) const; + +private: + mutable BMallocIO fPassword; + BString fIdentifier; + BString fSecondaryIdentifier; + BString fOwner; + BMessage fData; + bigtime_t fCreationTime; + BPasswordType fType; + BObjectList fApplications; + bool fRegistered; +}; + + +#endif // _KEY_H diff --git a/headers/os/app/KeyStore.h b/headers/os/app/KeyStore.h new file mode 100644 index 0000000000..b09e2b17c8 --- /dev/null +++ b/headers/os/app/KeyStore.h @@ -0,0 +1,94 @@ +/* + * Copyright 2011, Haiku, Inc. + * Distributed under the terms of the MIT License. + */ +#ifndef _KEY_STORE_H +#define _KEY_STORE_H + + +#include + + +class BKeyStore { +public: + BKeyStore(); + virtual ~BKeyStore(); + +// TODO: -> GetNextPassword() - there can always be more than one key +// with the same identifier/secondaryIdentifier (ie. different username) + status_t GetPassword(BPasswordType type, + const char* identifier, BKey& key); + status_t GetPassword(BPasswordType type, + const char* identifier, + const char* secondaryIdentifier, BKey& key); + status_t GetPassword(BPasswordType type, + const char* identifier, + const char* secondaryIdentifier, + bool secondaryIdentifierOptional, + BKey& key); + + status_t GetPassword(const char* keyring, + BPasswordType type, + const char* identifier, BKey& key); + status_t GetPassword(const char* keyring, + BPasswordType type, + const char* identifier, + const char* secondaryIdentifier, BKey& key); + status_t GetPassword(const char* keyring, + BPasswordType type, + const char* identifier, + const char* secondaryIdentifier, + bool secondaryIdentifierOptional, + BKey& key); + + status_t RegisterPassword(const BKey& key); + status_t RegisterPassword(const char* keyring, + const BKey& key); + status_t UnregisterPassword(const BKey& key); + status_t UnregisterPassword(const char* keyring, + const BKey& key); + + status_t GetNextPassword(uint32& cookie, BKey& key); + status_t GetNextPassword(BPasswordType type, + uint32& cookie, BKey& key); + status_t GetNextPassword(const char* keyring, + uint32& cookie, BKey& key); + status_t GetNextPassword(const char* keyring, + BPasswordType type, uint32& cookie, + BKey& key); + + // Keyrings + + status_t RegisterKeyring(const char* keyring, + const BKey& key); + status_t UnregisterKeyring(const char* keyring); + + status_t GetNextKeyring(uint32& cookie, + BString& keyring); + + // Master key + + status_t SetMasterPassword(const BKey& key); + status_t RemoveMasterPassword(); + + status_t AddKeyringToMaster(const char* keyring); + status_t RemoveKeyringFromMaster(const char* keyring); + + status_t GetNextMasterKeyring(uint32& cookie, + BString& keyring); + + // Access + + bool IsKeyringAccessible(const char* keyring); + status_t RevokeAccess(const char* keyring); + status_t RevokeMasterAccess(); + + // Service functions + + status_t GeneratePassword(BKey& key, size_t length, + uint32 flags); + float PasswordStrength(const char* key); +}; + + +#endif // _KEY_STORE_H diff --git a/src/kits/app/Jamfile b/src/kits/app/Jamfile index 1aec0536d7..85e267bd9e 100644 --- a/src/kits/app/Jamfile +++ b/src/kits/app/Jamfile @@ -57,5 +57,9 @@ MergeObject app_kit.o : ServerMemoryAllocator.cpp TokenSpace.cpp TypeConstants.cpp + + # KeyStore implementation + Key.cpp + KeyStore.cpp ; diff --git a/src/kits/app/Key.cpp b/src/kits/app/Key.cpp new file mode 100644 index 0000000000..650bb88a1b --- /dev/null +++ b/src/kits/app/Key.cpp @@ -0,0 +1,258 @@ +/* + * Copyright 2011, Axel Dörfler, axeld@pinc-software.de. + * Distributed under the terms of the MIT License. + */ + + +#include + + +static bool +CompareLists(BObjectList a, BObjectList b) +{ + if (a.CountItems() != b.CountItems()) + return false; + + for (int32 i = 0; i < a.CountItems(); i++) { + if (*a.ItemAt(i) != *b.ItemAt(i)) + return false; + } + + return true; +} + + +// #pragma mark - + + +BKey::BKey() +{ +} + + +BKey::BKey(BPasswordType type, const char* identifier, + const char* password) +{ + SetTo(type, identifier, NULL, password); +} + + +BKey::BKey(BPasswordType type, const char* identifier, + const char* secondaryIdentifier, const char* password) +{ + SetTo(type, identifier, secondaryIdentifier, password); +} + + +BKey::BKey(BKey& other) +{ +} + + +BKey::~BKey() +{ +} + + +status_t +BKey::SetTo(BPasswordType type, const char* identifier, + const char* password) +{ + return SetTo(type, identifier, NULL, password); +} + + +status_t +BKey::SetTo(BPasswordType type, const char* identifier, + const char* secondaryIdentifier, const char* password) +{ + SetType(type); + SetIdentifier(identifier); + SetSecondaryIdentifier(secondaryIdentifier); + return SetPassword(password); +} + + +status_t +BKey::SetPassword(const char* password) +{ + return SetKey((const uint8*)password, strlen(password) + 1); +} + + +const char* +BKey::Password() const +{ + return (const char*)fPassword.Buffer(); +} + + +status_t +BKey::SetKey(const uint8* data, size_t length) +{ + fPassword.SetSize(0); + ssize_t bytesWritten = fPassword.WriteAt(0, data, length); + if (bytesWritten < 0) + return (status_t)bytesWritten; + + return (size_t)bytesWritten == length ? B_OK : B_NO_MEMORY; +} + + +size_t +BKey::KeyLength() const +{ + return fPassword.BufferLength(); +} + + +status_t +BKey::GetKey(uint8* buffer, size_t bufferLength) const +{ + ssize_t bytesRead = fPassword.ReadAt(0, buffer, bufferLength); + if (bytesRead < 0) + return (status_t)bytesRead; + + return B_OK; +} + + +void +BKey::SetIdentifier(const char* identifier) +{ + fIdentifier = identifier; +} + + +const char* +BKey::Identifier() const +{ + return fIdentifier.String(); +} + + +void +BKey::SetSecondaryIdentifier(const char* identifier) +{ + fSecondaryIdentifier = identifier; +} + + +const char* +BKey::SecondaryIdentifier() const +{ + return fSecondaryIdentifier.String(); +} + + +void +BKey::SetType(BPasswordType type) +{ + fType = type; +} + + +BPasswordType +BKey::Type() const +{ + return fType; +} + + +void +BKey::SetData(const BMessage& data) +{ + fData = data; +} + + +const BMessage& +BKey::Data() const +{ + return fData; +} + + +const char* +BKey::Owner() const +{ + return fOwner.String(); +} + + +bigtime_t +BKey::CreationTime() const +{ + return fCreationTime; +} + + +bool +BKey::IsRegistered() const +{ + return fRegistered; +} + + +status_t +BKey::GetNextApplication(uint32& cookie, BString& signature) const +{ + BString* item = fApplications.ItemAt(cookie++); + if (item == NULL) + return B_ENTRY_NOT_FOUND; + + signature = *item; + return B_OK; +} + + +status_t +BKey::RemoveApplication(const char* signature) +{ + for (int32 i = 0; i < fApplications.CountItems(); i++) { + if (*fApplications.ItemAt(i) == signature) { + fApplications.RemoveItemAt(i); + return B_OK; + } + } + return B_ENTRY_NOT_FOUND; +} + + +BKey& +BKey::operator=(const BKey& other) +{ + SetKey((const uint8*)other.Password(), other.KeyLength()); + SetType(other.Type()); + SetData(other.Data()); + + fIdentifier = other.fIdentifier; + fSecondaryIdentifier = other.fSecondaryIdentifier; + fOwner = other.fOwner; + fCreationTime = other.CreationTime(); + fRegistered = other.IsRegistered(); + fApplications = other.fApplications; + + return *this; +} + + +bool +BKey::operator==(const BKey& other) const +{ + return KeyLength() == other.KeyLength() + && fIdentifier == other.fIdentifier + && fSecondaryIdentifier == other.fSecondaryIdentifier + && !memcmp(Password(), other.Password(), KeyLength()) + && fOwner == other.fOwner + && Data().HasSameData(other.Data()) + && Type() == other.Type() + && CompareLists(fApplications, other.fApplications); +} + + +bool +BKey::operator!=(const BKey& other) const +{ + return !(*this == other); +} diff --git a/src/kits/app/KeyStore.cpp b/src/kits/app/KeyStore.cpp new file mode 100644 index 0000000000..190b075514 --- /dev/null +++ b/src/kits/app/KeyStore.cpp @@ -0,0 +1,236 @@ +/* + * Copyright 2011, Axel Dörfler, axeld@pinc-software.de. + * Distributed under the terms of the MIT License. + */ + + +#include + + +BKeyStore::BKeyStore() +{ +} + + +BKeyStore::~BKeyStore() +{ +} + + +// #pragma mark - Passwords + + +status_t +BKeyStore::GetPassword(BPasswordType type, const char* identifier, + BKey& password) +{ + return GetPassword(NULL, type, identifier, NULL, true, password); +} + + +status_t +BKeyStore::GetPassword(BPasswordType type, const char* identifier, + const char* secondaryIdentifier, BKey& password) +{ + return GetPassword(NULL, type, identifier, secondaryIdentifier, true, + password); +} + + +status_t +BKeyStore::GetPassword(BPasswordType type, const char* identifier, + const char* secondaryIdentifier, bool secondaryIdentifierOptional, + BKey& password) +{ + return GetPassword(NULL, type, identifier, secondaryIdentifier, + secondaryIdentifierOptional, password); +} + + +status_t +BKeyStore::GetPassword(const char* keyring, BPasswordType type, + const char* identifier, BKey& password) +{ + return GetPassword(keyring, type, identifier, NULL, true, password); +} + + +status_t +BKeyStore::GetPassword(const char* keyring, BPasswordType type, + const char* identifier, const char* secondaryIdentifier, + BKey& password) +{ + return GetPassword(keyring, type, identifier, secondaryIdentifier, true, + password); +} + + +status_t +BKeyStore::GetPassword(const char* keyring, BPasswordType type, + const char* identifier, const char* secondaryIdentifier, + bool secondaryIdentifierOptional, BKey& password) +{ + return B_ERROR; +} + + +status_t +BKeyStore::RegisterPassword(const BKey& password) +{ + return RegisterPassword(NULL, password); +} + + +status_t +BKeyStore::RegisterPassword(const char* keyring, const BKey& password) +{ + return B_ERROR; +} + + +status_t +BKeyStore::UnregisterPassword(const BKey& password) +{ + return UnregisterPassword(NULL, password); +} + + +status_t +BKeyStore::UnregisterPassword(const char* keyring, const BKey& password) +{ + return B_ERROR; +} + + +status_t +BKeyStore::GetNextPassword(uint32& cookie, BKey& password) +{ + return GetNextPassword(NULL, cookie, password); +} + + +status_t +BKeyStore::GetNextPassword(BPasswordType type, uint32& cookie, + BKey& password) +{ + return GetNextPassword(NULL, type, cookie, password); +} + + +status_t +BKeyStore::GetNextPassword(const char* keyring, uint32& cookie, + BKey& password) +{ + return B_ERROR; +} + + +status_t +BKeyStore::GetNextPassword(const char* keyring, + BPasswordType type, uint32& cookie, BKey& password) +{ + return B_ERROR; +} + + +// #pragma mark - Keyrings + + +status_t +BKeyStore::RegisterKeyring(const char* keyring, const BKey& password) +{ + return B_ERROR; +} + + +status_t +BKeyStore::UnregisterKeyring(const char* keyring) +{ + return B_ERROR; +} + + +status_t +BKeyStore::GetNextKeyring(uint32& cookie, BString& keyring) +{ + return B_ERROR; +} + + +// #pragma mark - Master password + + +status_t +BKeyStore::SetMasterPassword(const BKey& password) +{ + return B_ERROR; +} + + +status_t +BKeyStore::RemoveMasterPassword() +{ + return B_ERROR; +} + + +status_t +BKeyStore::AddKeyringToMaster(const char* keyring) +{ + return B_ERROR; +} + + +status_t +BKeyStore::RemoveKeyringFromMaster(const char* keyring) +{ + return B_ERROR; +} + + +status_t +BKeyStore::GetNextMasterKeyring(uint32& cookie, BString& keyring) +{ + return B_ERROR; +} + + +// #pragma mark - Access + + +bool +BKeyStore::IsKeyringAccessible(const char* keyring) +{ + return false; +} + + +status_t +BKeyStore::RevokeAccess(const char* keyring) +{ + return B_ERROR; +} + + +status_t +BKeyStore::RevokeMasterAccess() +{ + return B_ERROR; +} + + +// #pragma mark - Service functions + + +status_t +BKeyStore::GeneratePassword(BKey& password, size_t length, uint32 flags) +{ + return B_ERROR; +} + + +float +BKeyStore::PasswordStrength(const char* password) +{ + return 0; +} From dc1acef865f290e8d565f078fc78be69991b5c10 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Thu, 22 Dec 2011 14:58:19 +0100 Subject: [PATCH 039/104] Flesh out the API and implement stubs. * Modified the API greatly to be based on BKey* instead of BPassword*. * Added BKeyPurpose and used it instead of BKeyType. It is supposed to indicate the purpose of a key so that an app can look up keys on a more granular level. The BKeyType on the other hand actually identifies the type (i.e. subclass of BKey) so an app knows how to handle a given key or may only enumerate/use keys it is compatible with. * Made everything based on a raw data buffer for now, only BPasswordKey is implemented yet which stores the (0 terminated) string into that data buffer. * Removed the additional data BMessage as I don't yet see where it fits in. While I could imagine adding meta data to a key may be nice it might be an interoperability concern when keys are shared by different apps. * Moved the app functions to the keystore as per the TODO, but not sure how to actually implement them. --- headers/os/app/Key.h | 89 +++++++++++-------- headers/os/app/KeyStore.h | 55 +++++++----- src/kits/app/Key.cpp | 182 +++++++++++++++++++++----------------- src/kits/app/KeyStore.cpp | 111 +++++++++++++---------- 4 files changed, 247 insertions(+), 190 deletions(-) diff --git a/headers/os/app/Key.h b/headers/os/app/Key.h index e3139f4f01..d4c74af78d 100644 --- a/headers/os/app/Key.h +++ b/headers/os/app/Key.h @@ -12,44 +12,46 @@ #include -enum BPasswordType { - B_WEB_PASSWORD, - B_NETWORK_PASSWORD, - B_VOLUME_PASSWORD, - B_GENERIC_PASSWORD +enum BKeyPurpose { + B_KEY_PURPOSE_ANY, + B_KEY_PURPOSE_GENERIC, + B_KEY_PURPOSE_WEB, + B_KEY_PURPOSE_NETWORK, + B_KEY_PURPOSE_VOLUME +}; + + +enum BKeyType { + B_KEY_TYPE_ANY, + B_KEY_TYPE_GENERIC, + B_KEY_TYPE_PASSWORD, + B_KEY_TYPE_CERTIFICATE }; class BKey { public: BKey(); - BKey(BPasswordType type, + BKey(BKeyPurpose purpose, const char* identifier, - const char* password); - BKey(BPasswordType type, - const char* identifier, - const char* secondaryIdentifier, - const char* password); + const char* secondaryIdentifier = NULL, + const uint8* data = NULL, + size_t length = 0); BKey(BKey& other); virtual ~BKey(); + virtual BKeyType Type() const { return B_KEY_TYPE_GENERIC; }; + void Unset(); - status_t SetTo(BPasswordType type, + status_t SetTo(BKeyPurpose purpose, const char* identifier, - const char* password); - status_t SetTo(BPasswordType type, - const char* identifier, - const char* secondaryIdentifier, - const char* password); + const char* secondaryIdentifier = NULL, + const uint8* data = NULL, + size_t length = 0); - status_t SetPassword(const char* password); - const char* Password() const; - - status_t SetKey(const uint8* data, size_t length); - size_t KeyLength() const; - status_t GetKey(uint8* buffer, - size_t bufferLength) const; + void SetPurpose(BKeyPurpose purpose); + BKeyPurpose Purpose() const; void SetIdentifier(const char* identifier); const char* Identifier() const; @@ -57,37 +59,50 @@ public: void SetSecondaryIdentifier(const char* identifier); const char* SecondaryIdentifier() const; - void SetType(BPasswordType type); - BPasswordType Type() const; - - void SetData(const BMessage& data); - const BMessage& Data() const; + status_t SetData(const uint8* data, size_t length); + size_t DataLength() const; + const uint8* Data() const; + status_t GetData(uint8* buffer, size_t bufferSize) const; const char* Owner() const; bigtime_t CreationTime() const; bool IsRegistered() const; -// TODO: move to BKeyStore - status_t GetNextApplication(uint32& cookie, - BString& signature) const; - status_t RemoveApplication(const char* signature); - BKey& operator=(const BKey& other); bool operator==(const BKey& other) const; bool operator!=(const BKey& other) const; private: - mutable BMallocIO fPassword; + BKeyPurpose fPurpose; BString fIdentifier; BString fSecondaryIdentifier; BString fOwner; - BMessage fData; bigtime_t fCreationTime; - BPasswordType fType; + mutable BMallocIO fData; BObjectList fApplications; bool fRegistered; }; +class BPasswordKey : public BKey { +public: + BPasswordKey(); + BPasswordKey(const char* password, + BKeyPurpose purpose, const char* identifier, + const char* secondaryIdentifier = NULL); + BPasswordKey(BPasswordKey& other); + virtual ~BPasswordKey(); + + virtual BKeyType Type() const { return B_KEY_TYPE_PASSWORD; }; + + status_t SetTo(const char* password, + BKeyPurpose purpose, + const char* identifier, + const char* secondaryIdentifier = NULL); + + status_t SetPassword(const char* password); + const char* Password() const; +}; + #endif // _KEY_H diff --git a/headers/os/app/KeyStore.h b/headers/os/app/KeyStore.h index b09e2b17c8..83a86b27ff 100644 --- a/headers/os/app/KeyStore.h +++ b/headers/os/app/KeyStore.h @@ -16,46 +16,46 @@ public: // TODO: -> GetNextPassword() - there can always be more than one key // with the same identifier/secondaryIdentifier (ie. different username) - status_t GetPassword(BPasswordType type, + status_t GetKey(BKeyType type, BKeyPurpose purpose, const char* identifier, BKey& key); - status_t GetPassword(BPasswordType type, + status_t GetKey(BKeyType type, BKeyPurpose purpose, const char* identifier, const char* secondaryIdentifier, BKey& key); - status_t GetPassword(BPasswordType type, + status_t GetKey(BKeyType type, BKeyPurpose purpose, const char* identifier, const char* secondaryIdentifier, bool secondaryIdentifierOptional, BKey& key); - status_t GetPassword(const char* keyring, - BPasswordType type, + status_t GetKey(const char* keyring, + BKeyType type, BKeyPurpose purpose, const char* identifier, BKey& key); - status_t GetPassword(const char* keyring, - BPasswordType type, + status_t GetKey(const char* keyring, + BKeyType type, BKeyPurpose purpose, const char* identifier, const char* secondaryIdentifier, BKey& key); - status_t GetPassword(const char* keyring, - BPasswordType type, + status_t GetKey(const char* keyring, + BKeyType type, BKeyPurpose purpose, const char* identifier, const char* secondaryIdentifier, bool secondaryIdentifierOptional, BKey& key); - status_t RegisterPassword(const BKey& key); - status_t RegisterPassword(const char* keyring, + status_t RegisterKey(const BKey& key); + status_t RegisterKey(const char* keyring, const BKey& key); - status_t UnregisterPassword(const BKey& key); - status_t UnregisterPassword(const char* keyring, + status_t UnregisterKey(const BKey& key); + status_t UnregisterKey(const char* keyring, const BKey& key); - status_t GetNextPassword(uint32& cookie, BKey& key); - status_t GetNextPassword(BPasswordType type, + status_t GetNextKey(uint32& cookie, BKey& key); + status_t GetNextKey(BKeyType type, BKeyPurpose purpose, uint32& cookie, BKey& key); - status_t GetNextPassword(const char* keyring, + status_t GetNextKey(const char* keyring, + uint32& cookie, BKey& key); + status_t GetNextKey(const char* keyring, + BKeyType type, BKeyPurpose purpose, uint32& cookie, BKey& key); - status_t GetNextPassword(const char* keyring, - BPasswordType type, uint32& cookie, - BKey& key); // Keyrings @@ -68,8 +68,8 @@ public: // Master key - status_t SetMasterPassword(const BKey& key); - status_t RemoveMasterPassword(); + status_t SetMasterKey(const BKey& key); + status_t RemoveMasterKey(); status_t AddKeyringToMaster(const char* keyring); status_t RemoveKeyringFromMaster(const char* keyring); @@ -83,11 +83,18 @@ public: status_t RevokeAccess(const char* keyring); status_t RevokeMasterAccess(); + // Applications + + status_t GetNextApplication(const BKey& key, + uint32& cookie, BString& signature) const; + status_t RemoveApplication(const BKey& key, + const char* signature); + // Service functions - status_t GeneratePassword(BKey& key, size_t length, - uint32 flags); - float PasswordStrength(const char* key); + status_t GeneratePassword(BPasswordKey& password, + size_t length, uint32 flags); + float PasswordStrength(const char* password); }; diff --git a/src/kits/app/Key.cpp b/src/kits/app/Key.cpp index 650bb88a1b..bfe187d963 100644 --- a/src/kits/app/Key.cpp +++ b/src/kits/app/Key.cpp @@ -22,7 +22,7 @@ CompareLists(BObjectList a, BObjectList b) } -// #pragma mark - +// #pragma mark - Generic BKey BKey::BKey() @@ -30,17 +30,10 @@ BKey::BKey() } -BKey::BKey(BPasswordType type, const char* identifier, - const char* password) +BKey::BKey(BKeyPurpose purpose, const char* identifier, + const char* secondaryIdentifier, const uint8* data, size_t length) { - SetTo(type, identifier, NULL, password); -} - - -BKey::BKey(BPasswordType type, const char* identifier, - const char* secondaryIdentifier, const char* password) -{ - SetTo(type, identifier, secondaryIdentifier, password); + SetTo(purpose, identifier, secondaryIdentifier, data, length); } @@ -55,65 +48,27 @@ BKey::~BKey() status_t -BKey::SetTo(BPasswordType type, const char* identifier, - const char* password) +BKey::SetTo(BKeyPurpose purpose, const char* identifier, + const char* secondaryIdentifier, const uint8* data, size_t length) { - return SetTo(type, identifier, NULL, password); -} - - -status_t -BKey::SetTo(BPasswordType type, const char* identifier, - const char* secondaryIdentifier, const char* password) -{ - SetType(type); + SetPurpose(purpose); SetIdentifier(identifier); SetSecondaryIdentifier(secondaryIdentifier); - return SetPassword(password); + return SetData(data, length); } -status_t -BKey::SetPassword(const char* password) +void +BKey::SetPurpose(BKeyPurpose purpose) { - return SetKey((const uint8*)password, strlen(password) + 1); + fPurpose = purpose; } -const char* -BKey::Password() const +BKeyPurpose +BKey::Purpose() const { - return (const char*)fPassword.Buffer(); -} - - -status_t -BKey::SetKey(const uint8* data, size_t length) -{ - fPassword.SetSize(0); - ssize_t bytesWritten = fPassword.WriteAt(0, data, length); - if (bytesWritten < 0) - return (status_t)bytesWritten; - - return (size_t)bytesWritten == length ? B_OK : B_NO_MEMORY; -} - - -size_t -BKey::KeyLength() const -{ - return fPassword.BufferLength(); -} - - -status_t -BKey::GetKey(uint8* buffer, size_t bufferLength) const -{ - ssize_t bytesRead = fPassword.ReadAt(0, buffer, bufferLength); - if (bytesRead < 0) - return (status_t)bytesRead; - - return B_OK; + return fPurpose; } @@ -145,34 +100,44 @@ BKey::SecondaryIdentifier() const } -void -BKey::SetType(BPasswordType type) +status_t +BKey::SetData(const uint8* data, size_t length) { - fType = type; + fData.SetSize(0); + ssize_t bytesWritten = fData.WriteAt(0, data, length); + if (bytesWritten < 0) + return (status_t)bytesWritten; + + return (size_t)bytesWritten == length ? B_OK : B_NO_MEMORY; } -BPasswordType -BKey::Type() const +size_t +BKey::DataLength() const { - return fType; + return fData.BufferLength(); } -void -BKey::SetData(const BMessage& data) -{ - fData = data; -} - - -const BMessage& +const uint8* BKey::Data() const { - return fData; + return (const uint8*)fData.Buffer(); } +status_t +BKey::GetData(uint8* buffer, size_t bufferSize) const +{ + ssize_t bytesRead = fData.ReadAt(0, buffer, bufferSize); + if (bytesRead < 0) + return (status_t)bytesRead; + + return B_OK; +} + + + const char* BKey::Owner() const { @@ -194,6 +159,8 @@ BKey::IsRegistered() const } +#if 0 +// To be moved to BKeyStore status_t BKey::GetNextApplication(uint32& cookie, BString& signature) const { @@ -215,16 +182,17 @@ BKey::RemoveApplication(const char* signature) return B_OK; } } + return B_ENTRY_NOT_FOUND; } +#endif BKey& BKey::operator=(const BKey& other) { - SetKey((const uint8*)other.Password(), other.KeyLength()); - SetType(other.Type()); - SetData(other.Data()); + SetPurpose(other.Purpose()); + SetData((const uint8*)other.Data(), other.DataLength()); fIdentifier = other.fIdentifier; fSecondaryIdentifier = other.fSecondaryIdentifier; @@ -240,13 +208,13 @@ BKey::operator=(const BKey& other) bool BKey::operator==(const BKey& other) const { - return KeyLength() == other.KeyLength() + return Type() == other.Type() + && DataLength() == other.DataLength() + && Purpose() == other.Purpose() + && fOwner == other.fOwner && fIdentifier == other.fIdentifier && fSecondaryIdentifier == other.fSecondaryIdentifier - && !memcmp(Password(), other.Password(), KeyLength()) - && fOwner == other.fOwner - && Data().HasSameData(other.Data()) - && Type() == other.Type() + && memcmp(Data(), other.Data(), DataLength()) == 0 && CompareLists(fApplications, other.fApplications); } @@ -256,3 +224,53 @@ BKey::operator!=(const BKey& other) const { return !(*this == other); } + + +// #pragma mark - BPasswordKey + + +BPasswordKey::BPasswordKey() +{ +} + + +BPasswordKey::BPasswordKey(const char* password, BKeyPurpose purpose, + const char* identifier, const char* secondaryIdentifier) + : + BKey(purpose, identifier, secondaryIdentifier, (const uint8*)password, + strlen(password) + 1) +{ +} + + +BPasswordKey::BPasswordKey(BPasswordKey& other) +{ +} + + +BPasswordKey::~BPasswordKey() +{ +} + + +status_t +BPasswordKey::SetTo(const char* password, BKeyPurpose purpose, + const char* identifier, const char* secondaryIdentifier) +{ + return BKey::SetTo(purpose, identifier, secondaryIdentifier, + (const uint8*)password, strlen(password) + 1); +} + + +status_t +BPasswordKey::SetPassword(const char* password) +{ + return SetData((const uint8*)password, strlen(password) + 1); +} + + +const char* +BPasswordKey::Password() const +{ + return (const char*)Data(); +} diff --git a/src/kits/app/KeyStore.cpp b/src/kits/app/KeyStore.cpp index 190b075514..c8417a2106 100644 --- a/src/kits/app/KeyStore.cpp +++ b/src/kits/app/KeyStore.cpp @@ -17,117 +17,115 @@ BKeyStore::~BKeyStore() } -// #pragma mark - Passwords +// #pragma mark - Key handling status_t -BKeyStore::GetPassword(BPasswordType type, const char* identifier, - BKey& password) +BKeyStore::GetKey(BKeyType type, BKeyPurpose purpose, const char* identifier, + BKey& key) { - return GetPassword(NULL, type, identifier, NULL, true, password); + return GetKey(NULL, type, purpose, identifier, NULL, true, key); } status_t -BKeyStore::GetPassword(BPasswordType type, const char* identifier, - const char* secondaryIdentifier, BKey& password) +BKeyStore::GetKey(BKeyType type, BKeyPurpose purpose, const char* identifier, + const char* secondaryIdentifier, BKey& key) { - return GetPassword(NULL, type, identifier, secondaryIdentifier, true, - password); + return GetKey(NULL, type, purpose, identifier, secondaryIdentifier, true, + key); } status_t -BKeyStore::GetPassword(BPasswordType type, const char* identifier, +BKeyStore::GetKey(BKeyType type, BKeyPurpose purpose, const char* identifier, const char* secondaryIdentifier, bool secondaryIdentifierOptional, - BKey& password) + BKey& key) { - return GetPassword(NULL, type, identifier, secondaryIdentifier, - secondaryIdentifierOptional, password); + return GetKey(NULL, type, purpose, identifier, secondaryIdentifier, + secondaryIdentifierOptional, key); } status_t -BKeyStore::GetPassword(const char* keyring, BPasswordType type, - const char* identifier, BKey& password) +BKeyStore::GetKey(const char* keyring, BKeyType type, BKeyPurpose purpose, + const char* identifier, BKey& key) { - return GetPassword(keyring, type, identifier, NULL, true, password); + return GetKey(keyring, type, purpose, identifier, NULL, true, key); } status_t -BKeyStore::GetPassword(const char* keyring, BPasswordType type, +BKeyStore::GetKey(const char* keyring, BKeyType type, BKeyPurpose purpose, + const char* identifier, const char* secondaryIdentifier, BKey& key) +{ + return GetKey(keyring, type, purpose, identifier, secondaryIdentifier, true, + key); +} + + +status_t +BKeyStore::GetKey(const char* keyring, BKeyType type, BKeyPurpose purpose, const char* identifier, const char* secondaryIdentifier, - BKey& password) -{ - return GetPassword(keyring, type, identifier, secondaryIdentifier, true, - password); -} - - -status_t -BKeyStore::GetPassword(const char* keyring, BPasswordType type, - const char* identifier, const char* secondaryIdentifier, - bool secondaryIdentifierOptional, BKey& password) + bool secondaryIdentifierOptional, BKey& key) { return B_ERROR; } status_t -BKeyStore::RegisterPassword(const BKey& password) +BKeyStore::RegisterKey(const BKey& key) { - return RegisterPassword(NULL, password); + return RegisterKey(NULL, key); } status_t -BKeyStore::RegisterPassword(const char* keyring, const BKey& password) +BKeyStore::RegisterKey(const char* keyring, const BKey& key) { return B_ERROR; } status_t -BKeyStore::UnregisterPassword(const BKey& password) +BKeyStore::UnregisterKey(const BKey& key) { - return UnregisterPassword(NULL, password); + return UnregisterKey(NULL, key); } status_t -BKeyStore::UnregisterPassword(const char* keyring, const BKey& password) +BKeyStore::UnregisterKey(const char* keyring, const BKey& key) { return B_ERROR; } status_t -BKeyStore::GetNextPassword(uint32& cookie, BKey& password) +BKeyStore::GetNextKey(uint32& cookie, BKey& key) { - return GetNextPassword(NULL, cookie, password); + return GetNextKey(NULL, cookie, key); } status_t -BKeyStore::GetNextPassword(BPasswordType type, uint32& cookie, - BKey& password) +BKeyStore::GetNextKey(BKeyType type, BKeyPurpose purpose, uint32& cookie, + BKey& key) { - return GetNextPassword(NULL, type, cookie, password); + return GetNextKey(NULL, type, purpose, cookie, key); } status_t -BKeyStore::GetNextPassword(const char* keyring, uint32& cookie, - BKey& password) +BKeyStore::GetNextKey(const char* keyring, uint32& cookie, BKey& key) { return B_ERROR; } status_t -BKeyStore::GetNextPassword(const char* keyring, - BPasswordType type, uint32& cookie, BKey& password) +BKeyStore::GetNextKey(const char* keyring, BKeyType type, BKeyPurpose purpose, + uint32& cookie, BKey& key) { return B_ERROR; } @@ -137,7 +135,7 @@ BKeyStore::GetNextPassword(const char* keyring, status_t -BKeyStore::RegisterKeyring(const char* keyring, const BKey& password) +BKeyStore::RegisterKeyring(const char* keyring, const BKey& key) { return B_ERROR; } @@ -157,18 +155,18 @@ BKeyStore::GetNextKeyring(uint32& cookie, BString& keyring) } -// #pragma mark - Master password +// #pragma mark - Master key status_t -BKeyStore::SetMasterPassword(const BKey& password) +BKeyStore::SetMasterKey(const BKey& key) { return B_ERROR; } status_t -BKeyStore::RemoveMasterPassword() +BKeyStore::RemoveMasterKey() { return B_ERROR; } @@ -219,11 +217,30 @@ BKeyStore::RevokeMasterAccess() } + +// #pragma mark - Applications + + +status_t +BKeyStore::GetNextApplication(const BKey& key, uint32& cookie, + BString& signature) const +{ + return B_ERROR; +} + + +status_t +BKeyStore::RemoveApplication(const BKey& key, const char* signature) +{ + return B_ERROR; +} + + // #pragma mark - Service functions status_t -BKeyStore::GeneratePassword(BKey& password, size_t length, uint32 flags) +BKeyStore::GeneratePassword(BPasswordKey& password, size_t length, uint32 flags) { return B_ERROR; } From b73982892dde263a77608f219c3e02c48790f0c5 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Tue, 3 Jan 2012 17:15:24 +0100 Subject: [PATCH 040/104] Rename [Un]Register* functions to Add/Remove*. --- headers/os/app/KeyStore.h | 14 ++++++-------- src/kits/app/KeyStore.cpp | 16 ++++++++-------- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/headers/os/app/KeyStore.h b/headers/os/app/KeyStore.h index 83a86b27ff..6dc2096e64 100644 --- a/headers/os/app/KeyStore.h +++ b/headers/os/app/KeyStore.h @@ -41,12 +41,10 @@ public: bool secondaryIdentifierOptional, BKey& key); - status_t RegisterKey(const BKey& key); - status_t RegisterKey(const char* keyring, - const BKey& key); - status_t UnregisterKey(const BKey& key); - status_t UnregisterKey(const char* keyring, - const BKey& key); + status_t AddKey(const BKey& key); + status_t AddKey(const char* keyring, const BKey& key); + status_t RemoveKey(const BKey& key); + status_t RemoveKey(const char* keyring, const BKey& key); status_t GetNextKey(uint32& cookie, BKey& key); status_t GetNextKey(BKeyType type, BKeyPurpose purpose, @@ -59,9 +57,9 @@ public: // Keyrings - status_t RegisterKeyring(const char* keyring, + status_t AddKeyring(const char* keyring, const BKey& key); - status_t UnregisterKeyring(const char* keyring); + status_t RemoveKeyring(const char* keyring); status_t GetNextKeyring(uint32& cookie, BString& keyring); diff --git a/src/kits/app/KeyStore.cpp b/src/kits/app/KeyStore.cpp index c8417a2106..a3fbc593bc 100644 --- a/src/kits/app/KeyStore.cpp +++ b/src/kits/app/KeyStore.cpp @@ -74,28 +74,28 @@ BKeyStore::GetKey(const char* keyring, BKeyType type, BKeyPurpose purpose, status_t -BKeyStore::RegisterKey(const BKey& key) +BKeyStore::AddKey(const BKey& key) { - return RegisterKey(NULL, key); + return AddKey(NULL, key); } status_t -BKeyStore::RegisterKey(const char* keyring, const BKey& key) +BKeyStore::AddKey(const char* keyring, const BKey& key) { return B_ERROR; } status_t -BKeyStore::UnregisterKey(const BKey& key) +BKeyStore::RemoveKey(const BKey& key) { - return UnregisterKey(NULL, key); + return RemoveKey(NULL, key); } status_t -BKeyStore::UnregisterKey(const char* keyring, const BKey& key) +BKeyStore::RemoveKey(const char* keyring, const BKey& key) { return B_ERROR; } @@ -135,14 +135,14 @@ BKeyStore::GetNextKey(const char* keyring, BKeyType type, BKeyPurpose purpose, status_t -BKeyStore::RegisterKeyring(const char* keyring, const BKey& key) +BKeyStore::AddKeyring(const char* keyring, const BKey& key) { return B_ERROR; } status_t -BKeyStore::UnregisterKeyring(const char* keyring) +BKeyStore::RemoveKeyring(const char* keyring) { return B_ERROR; } From 1c3996496b06a2da3ae25c358336302dfbce7ddb Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Wed, 4 Jan 2012 01:51:59 +0100 Subject: [PATCH 041/104] Implement all KeyStore methods except for password generation. * Add all relevant message constants. * Implement the messaging to send/retrieve key info. * Implement _Flatten/_Unflatten for sending flat BKey objects. * Remove application list from BKey, the key can't only differ by allowed applications as the identifiers would still collide, so the comparison isn't needed to uniquely identify the key. The applications can be enumerated via the BKeyStore instead. --- headers/os/app/Key.h | 7 +- headers/os/app/KeyStore.h | 4 + headers/private/app/RegistrarDefs.h | 19 +++ src/kits/app/Key.cpp | 80 +++++++----- src/kits/app/KeyStore.cpp | 188 +++++++++++++++++++++++++--- 5 files changed, 247 insertions(+), 51 deletions(-) diff --git a/headers/os/app/Key.h b/headers/os/app/Key.h index d4c74af78d..147104223b 100644 --- a/headers/os/app/Key.h +++ b/headers/os/app/Key.h @@ -73,14 +73,19 @@ public: bool operator==(const BKey& other) const; bool operator!=(const BKey& other) const; +protected: + virtual status_t _Flatten(BMessage& message) const; + virtual status_t _Unflatten(const BMessage& message); + private: + friend class BKeyStore; + BKeyPurpose fPurpose; BString fIdentifier; BString fSecondaryIdentifier; BString fOwner; bigtime_t fCreationTime; mutable BMallocIO fData; - BObjectList fApplications; bool fRegistered; }; diff --git a/headers/os/app/KeyStore.h b/headers/os/app/KeyStore.h index 6dc2096e64..3d23fcdf5d 100644 --- a/headers/os/app/KeyStore.h +++ b/headers/os/app/KeyStore.h @@ -93,6 +93,10 @@ public: status_t GeneratePassword(BPasswordKey& password, size_t length, uint32 flags); float PasswordStrength(const char* password); + +private: + status_t _SendKeyMessage(BMessage& message, + BMessage* reply) const; }; diff --git a/headers/private/app/RegistrarDefs.h b/headers/private/app/RegistrarDefs.h index c5144e2f91..548cd0f72b 100644 --- a/headers/private/app/RegistrarDefs.h +++ b/headers/private/app/RegistrarDefs.h @@ -122,6 +122,25 @@ enum { B_REG_GET_USER_GROUPS = 'rgug', B_REG_UPDATE_USER = 'ruus', B_REG_UPDATE_GROUP = 'rugr', + + // KeyStore requests + B_REG_GET_KEY = 'rgtK', + B_REG_GET_NEXT_KEY = 'rgnK', + B_REG_ADD_KEY = 'radK', + B_REG_REMOVE_KEY = 'rrmK', + B_REG_ADD_KEYRING = 'raKR', + B_REG_REMOVE_KEYRING = 'rrKR', + B_REG_GET_NEXT_KEYRING = 'rnKR', + B_REG_SET_MASTER_KEY = 'rsMK', + B_REG_REMOVE_MASTER_KEY = 'rrMK', + B_REG_ADD_KEYRING_TO_MASTER = 'rarM', + B_REG_REMOVE_KEYRING_FROM_MASTER = 'rrrM', + B_REG_GET_NEXT_MASTER_KEYRING = 'rnrM', + B_REG_IS_KEYRING_ACCESSIBLE = 'riaR', + B_REG_REVOKE_ACCESS = 'rvaR', + B_REG_REVOKE_MASTER_ACCESS = 'rvaM', + B_REG_GET_NEXT_APPLICATION = 'rnKA', + B_REG_REMOVE_APPLICATION = 'rrKA', }; // B_REG_MIME_SET_PARAM "which" constants diff --git a/src/kits/app/Key.cpp b/src/kits/app/Key.cpp index bfe187d963..a112e74c12 100644 --- a/src/kits/app/Key.cpp +++ b/src/kits/app/Key.cpp @@ -7,6 +7,8 @@ #include +#if 0 +// TODO: move this to the KeyStore or the registrar backend if needed static bool CompareLists(BObjectList a, BObjectList b) { @@ -20,6 +22,7 @@ CompareLists(BObjectList a, BObjectList b) return true; } +#endif // #pragma mark - Generic BKey @@ -159,35 +162,6 @@ BKey::IsRegistered() const } -#if 0 -// To be moved to BKeyStore -status_t -BKey::GetNextApplication(uint32& cookie, BString& signature) const -{ - BString* item = fApplications.ItemAt(cookie++); - if (item == NULL) - return B_ENTRY_NOT_FOUND; - - signature = *item; - return B_OK; -} - - -status_t -BKey::RemoveApplication(const char* signature) -{ - for (int32 i = 0; i < fApplications.CountItems(); i++) { - if (*fApplications.ItemAt(i) == signature) { - fApplications.RemoveItemAt(i); - return B_OK; - } - } - - return B_ENTRY_NOT_FOUND; -} -#endif - - BKey& BKey::operator=(const BKey& other) { @@ -199,7 +173,6 @@ BKey::operator=(const BKey& other) fOwner = other.fOwner; fCreationTime = other.CreationTime(); fRegistered = other.IsRegistered(); - fApplications = other.fApplications; return *this; } @@ -214,8 +187,7 @@ BKey::operator==(const BKey& other) const && fOwner == other.fOwner && fIdentifier == other.fIdentifier && fSecondaryIdentifier == other.fSecondaryIdentifier - && memcmp(Data(), other.Data(), DataLength()) == 0 - && CompareLists(fApplications, other.fApplications); + && memcmp(Data(), other.Data(), DataLength()) == 0; } @@ -226,6 +198,50 @@ BKey::operator!=(const BKey& other) const } +status_t +BKey::_Flatten(BMessage& message) const +{ + if (message.MakeEmpty() != B_OK + || message.AddUInt32("type", Type()) != B_OK + || message.AddUInt32("purpose", fPurpose) != B_OK + || message.AddString("identifier", fIdentifier) != B_OK + || message.AddString("secondaryIdentifier", fSecondaryIdentifier) + != B_OK + || message.AddString("owner", fOwner) != B_OK + || message.AddInt64("creationTime", fCreationTime) != B_OK + || message.AddData("data", B_RAW_TYPE, fData.Buffer(), + fData.BufferLength()) != B_OK) { + return B_ERROR; + } + + return B_OK; +} + + +status_t +BKey::_Unflatten(const BMessage& message) +{ + BKeyType type; + if (message.FindUInt32("type", (uint32*)&type) != B_OK || type != Type()) + return B_BAD_VALUE; + + const void* data = NULL; + ssize_t dataLength = 0; + if (message.FindUInt32("purpose", (uint32*)&fPurpose) != B_OK + || message.FindString("identifier", &fIdentifier) != B_OK + || message.FindString("secondaryIdentifier", &fSecondaryIdentifier) + != B_OK + || message.FindString("owner", &fOwner) != B_OK + || message.FindInt64("creationTime", &fCreationTime) != B_OK + || message.FindData("data", B_RAW_TYPE, &data, &dataLength) != B_OK + || dataLength < 0) { + return B_ERROR; + } + + return SetData((const uint8*)data, (size_t)dataLength); +} + + // #pragma mark - BPasswordKey diff --git a/src/kits/app/KeyStore.cpp b/src/kits/app/KeyStore.cpp index a3fbc593bc..621ccaf437 100644 --- a/src/kits/app/KeyStore.cpp +++ b/src/kits/app/KeyStore.cpp @@ -6,6 +6,12 @@ #include +#include +#include + + +using namespace BPrivate; + BKeyStore::BKeyStore() { @@ -69,7 +75,24 @@ BKeyStore::GetKey(const char* keyring, BKeyType type, BKeyPurpose purpose, const char* identifier, const char* secondaryIdentifier, bool secondaryIdentifierOptional, BKey& key) { - return B_ERROR; + BMessage message(B_REG_GET_KEY); + message.AddString("keyring", keyring); + message.AddUInt32("type", type); + message.AddUInt32("purpose", purpose); + message.AddString("identifier", identifier); + message.AddString("secondaryIdentifier", secondaryIdentifier); + message.AddBool("secondaryIdentifierOptional", secondaryIdentifierOptional); + + BMessage reply; + status_t result = _SendKeyMessage(message, &reply); + if (result != B_OK) + return result; + + BMessage keyMessage; + if (reply.FindMessage("key", &keyMessage) != B_OK) + return B_ERROR; + + return key._Unflatten(keyMessage); } @@ -83,7 +106,15 @@ BKeyStore::AddKey(const BKey& key) status_t BKeyStore::AddKey(const char* keyring, const BKey& key) { - return B_ERROR; + BMessage keyMessage; + if (key._Flatten(keyMessage) != B_OK) + return B_BAD_VALUE; + + BMessage message(B_REG_ADD_KEY); + message.AddString("keyring", keyring); + message.AddMessage("key", &keyMessage); + + return _SendKeyMessage(message, NULL); } @@ -97,7 +128,15 @@ BKeyStore::RemoveKey(const BKey& key) status_t BKeyStore::RemoveKey(const char* keyring, const BKey& key) { - return B_ERROR; + BMessage keyMessage; + if (key._Flatten(keyMessage) != B_OK) + return B_BAD_VALUE; + + BMessage message(B_REG_REMOVE_KEY); + message.AddString("keyring", keyring); + message.AddMessage("key", &keyMessage); + + return _SendKeyMessage(message, NULL); } @@ -119,7 +158,7 @@ BKeyStore::GetNextKey(BKeyType type, BKeyPurpose purpose, uint32& cookie, status_t BKeyStore::GetNextKey(const char* keyring, uint32& cookie, BKey& key) { - return B_ERROR; + return GetNextKey(keyring, B_KEY_TYPE_ANY, B_KEY_PURPOSE_ANY, cookie, key); } @@ -127,7 +166,22 @@ status_t BKeyStore::GetNextKey(const char* keyring, BKeyType type, BKeyPurpose purpose, uint32& cookie, BKey& key) { - return B_ERROR; + BMessage message(B_REG_GET_NEXT_KEY); + message.AddString("keyring", keyring); + message.AddUInt32("type", type); + message.AddUInt32("purpose", purpose); + message.AddUInt32("cookie", cookie); + + BMessage reply; + status_t result = _SendKeyMessage(message, &reply); + if (result != B_OK) + return result; + + BMessage keyMessage; + if (reply.FindMessage("key", &keyMessage) != B_OK) + return B_ERROR; + + return key._Unflatten(keyMessage); } @@ -137,21 +191,42 @@ BKeyStore::GetNextKey(const char* keyring, BKeyType type, BKeyPurpose purpose, status_t BKeyStore::AddKeyring(const char* keyring, const BKey& key) { - return B_ERROR; + BMessage keyMessage; + if (key._Flatten(keyMessage) != B_OK) + return B_BAD_VALUE; + + BMessage message(B_REG_ADD_KEYRING); + message.AddString("keyring", keyring); + message.AddMessage("key", &keyMessage); + + return _SendKeyMessage(message, NULL); } status_t BKeyStore::RemoveKeyring(const char* keyring) { - return B_ERROR; + BMessage message(B_REG_REMOVE_KEYRING); + message.AddString("keyring", keyring); + return _SendKeyMessage(message, NULL); } status_t BKeyStore::GetNextKeyring(uint32& cookie, BString& keyring) { - return B_ERROR; + BMessage message(B_REG_GET_NEXT_KEYRING); + message.AddUInt32("cookie", cookie); + + BMessage reply; + status_t result = _SendKeyMessage(message, &reply); + if (result != B_OK) + return result; + + if (reply.FindString("keyring", &keyring) != B_OK) + return B_ERROR; + + return B_OK; } @@ -161,35 +236,58 @@ BKeyStore::GetNextKeyring(uint32& cookie, BString& keyring) status_t BKeyStore::SetMasterKey(const BKey& key) { - return B_ERROR; + BMessage keyMessage; + if (key._Flatten(keyMessage) != B_OK) + return B_BAD_VALUE; + + BMessage message(B_REG_SET_MASTER_KEY); + message.AddMessage("key", &keyMessage); + + return _SendKeyMessage(message, NULL); } status_t BKeyStore::RemoveMasterKey() { - return B_ERROR; + BMessage message(B_REG_REMOVE_MASTER_KEY); + return _SendKeyMessage(message, NULL); } status_t BKeyStore::AddKeyringToMaster(const char* keyring) { - return B_ERROR; + BMessage message(B_REG_ADD_KEYRING_TO_MASTER); + message.AddString("keyring", keyring); + return _SendKeyMessage(message, NULL); } status_t BKeyStore::RemoveKeyringFromMaster(const char* keyring) { - return B_ERROR; + BMessage message(B_REG_REMOVE_KEYRING_FROM_MASTER); + message.AddString("keyring", keyring); + return _SendKeyMessage(message, NULL); } status_t BKeyStore::GetNextMasterKeyring(uint32& cookie, BString& keyring) { - return B_ERROR; + BMessage message(B_REG_GET_NEXT_MASTER_KEYRING); + message.AddUInt32("cookie", cookie); + + BMessage reply; + status_t result = _SendKeyMessage(message, &reply); + if (result != B_OK) + return result; + + if (reply.FindString("keyring", &keyring) != B_OK) + return B_ERROR; + + return B_OK; } @@ -199,21 +297,26 @@ BKeyStore::GetNextMasterKeyring(uint32& cookie, BString& keyring) bool BKeyStore::IsKeyringAccessible(const char* keyring) { - return false; + BMessage message(B_REG_IS_KEYRING_ACCESSIBLE); + message.AddString("keyring", keyring); + return _SendKeyMessage(message, NULL) == B_OK; } status_t BKeyStore::RevokeAccess(const char* keyring) { - return B_ERROR; + BMessage message(B_REG_REVOKE_ACCESS); + message.AddString("keyring", keyring); + return _SendKeyMessage(message, NULL); } status_t BKeyStore::RevokeMasterAccess() { - return B_ERROR; + BMessage message(B_REG_REVOKE_MASTER_ACCESS); + return _SendKeyMessage(message, NULL); } @@ -225,14 +328,38 @@ status_t BKeyStore::GetNextApplication(const BKey& key, uint32& cookie, BString& signature) const { - return B_ERROR; + BMessage keyMessage; + if (key._Flatten(keyMessage) != B_OK) + return B_BAD_VALUE; + + BMessage message(B_REG_GET_NEXT_APPLICATION); + message.AddMessage("key", &keyMessage); + message.AddUInt32("cookie", cookie); + + BMessage reply; + status_t result = _SendKeyMessage(message, &reply); + if (result != B_OK) + return result; + + if (reply.FindString("signature", &signature) != B_OK) + return B_ERROR; + + return B_OK; } status_t BKeyStore::RemoveApplication(const BKey& key, const char* signature) { - return B_ERROR; + BMessage keyMessage; + if (key._Flatten(keyMessage) != B_OK) + return B_BAD_VALUE; + + BMessage message(B_REG_REMOVE_APPLICATION); + message.AddMessage("key", &keyMessage); + message.AddString("signature", signature); + + return _SendKeyMessage(message, NULL); } @@ -251,3 +378,28 @@ BKeyStore::PasswordStrength(const char* password) { return 0; } + + +// #pragma mark - Private functions + + +status_t +BKeyStore::_SendKeyMessage(BMessage& message, BMessage* reply) const +{ + BMessage localReply; + if (reply == NULL) + reply = &localReply; + + if (BRoster::Private().SendTo(&message, reply, false) != B_OK) + return B_ERROR; + + if (reply->what != B_REG_SUCCESS) { + status_t result = B_ERROR; + if (reply->FindInt32("result", &result) != B_OK) + return B_ERROR; + + return result; + } + + return B_OK; +} From 005a15bbcd7fe2f63477eea4b111711c44e171aa Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Wed, 4 Jan 2012 13:53:39 +0100 Subject: [PATCH 042/104] Move keystore message constants and use a messenger. * The keystore backend will (at least for the time being) reside in a separate server. This one can be reached via normal messaging, so use a BMessenger for sending key messages. * Move the message constants from RegistrarDefs.h into a new KeyStoreDefs.h that also contains the server signature. * Update the message constants to reflect the new situation. --- headers/private/app/KeyStoreDefs.h | 49 +++++++++++++++++++++++++++++ headers/private/app/RegistrarDefs.h | 19 ----------- src/kits/app/KeyStore.cpp | 47 ++++++++++++++------------- 3 files changed, 75 insertions(+), 40 deletions(-) create mode 100644 headers/private/app/KeyStoreDefs.h diff --git a/headers/private/app/KeyStoreDefs.h b/headers/private/app/KeyStoreDefs.h new file mode 100644 index 0000000000..d1198a6d3a --- /dev/null +++ b/headers/private/app/KeyStoreDefs.h @@ -0,0 +1,49 @@ +/* + * Copyright 2012, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Michael Lotz, mmlr@mlotz.ch + */ +#ifndef _KEY_STORE_DEFS_H +#define _KEY_STORE_DEFS_H + + +namespace BPrivate { + + +const char* kKeyStoreServerSignature + = "application/x-vnd.Haiku-keystore_server"; + + +enum { + // Replies + KEY_STORE_SUCCESS = 'KRok', + KEY_STORE_ERROR = 'KRer', + KEY_STORE_RESULT = 'KRrs', + + // KeyStore requests + KEY_STORE_GET_KEY = 'KgtK', + KEY_STORE_GET_NEXT_KEY = 'KgnK', + KEY_STORE_ADD_KEY = 'KadK', + KEY_STORE_REMOVE_KEY = 'KrmK', + KEY_STORE_ADD_KEYRING = 'KaKR', + KEY_STORE_REMOVE_KEYRING = 'KrKR', + KEY_STORE_GET_NEXT_KEYRING = 'KnKR', + KEY_STORE_SET_MASTER_KEY = 'KsMK', + KEY_STORE_REMOVE_MASTER_KEY = 'KrMK', + KEY_STORE_ADD_KEYRING_TO_MASTER = 'KarM', + KEY_STORE_REMOVE_KEYRING_FROM_MASTER = 'KrrM', + KEY_STORE_GET_NEXT_MASTER_KEYRING = 'KnrM', + KEY_STORE_IS_KEYRING_ACCESSIBLE = 'KiaR', + KEY_STORE_REVOKE_ACCESS = 'KvaR', + KEY_STORE_REVOKE_MASTER_ACCESS = 'KvaM', + KEY_STORE_GET_NEXT_APPLICATION = 'KnKA', + KEY_STORE_REMOVE_APPLICATION = 'KrKA', +}; + + +} // namespace BPrivate + + +#endif // _KEY_STORE_DEFS_H diff --git a/headers/private/app/RegistrarDefs.h b/headers/private/app/RegistrarDefs.h index 548cd0f72b..c5144e2f91 100644 --- a/headers/private/app/RegistrarDefs.h +++ b/headers/private/app/RegistrarDefs.h @@ -122,25 +122,6 @@ enum { B_REG_GET_USER_GROUPS = 'rgug', B_REG_UPDATE_USER = 'ruus', B_REG_UPDATE_GROUP = 'rugr', - - // KeyStore requests - B_REG_GET_KEY = 'rgtK', - B_REG_GET_NEXT_KEY = 'rgnK', - B_REG_ADD_KEY = 'radK', - B_REG_REMOVE_KEY = 'rrmK', - B_REG_ADD_KEYRING = 'raKR', - B_REG_REMOVE_KEYRING = 'rrKR', - B_REG_GET_NEXT_KEYRING = 'rnKR', - B_REG_SET_MASTER_KEY = 'rsMK', - B_REG_REMOVE_MASTER_KEY = 'rrMK', - B_REG_ADD_KEYRING_TO_MASTER = 'rarM', - B_REG_REMOVE_KEYRING_FROM_MASTER = 'rrrM', - B_REG_GET_NEXT_MASTER_KEYRING = 'rnrM', - B_REG_IS_KEYRING_ACCESSIBLE = 'riaR', - B_REG_REVOKE_ACCESS = 'rvaR', - B_REG_REVOKE_MASTER_ACCESS = 'rvaM', - B_REG_GET_NEXT_APPLICATION = 'rnKA', - B_REG_REMOVE_APPLICATION = 'rrKA', }; // B_REG_MIME_SET_PARAM "which" constants diff --git a/src/kits/app/KeyStore.cpp b/src/kits/app/KeyStore.cpp index 621ccaf437..70091cb341 100644 --- a/src/kits/app/KeyStore.cpp +++ b/src/kits/app/KeyStore.cpp @@ -6,8 +6,9 @@ #include -#include -#include +#include + +#include using namespace BPrivate; @@ -75,7 +76,7 @@ BKeyStore::GetKey(const char* keyring, BKeyType type, BKeyPurpose purpose, const char* identifier, const char* secondaryIdentifier, bool secondaryIdentifierOptional, BKey& key) { - BMessage message(B_REG_GET_KEY); + BMessage message(KEY_STORE_GET_KEY); message.AddString("keyring", keyring); message.AddUInt32("type", type); message.AddUInt32("purpose", purpose); @@ -110,7 +111,7 @@ BKeyStore::AddKey(const char* keyring, const BKey& key) if (key._Flatten(keyMessage) != B_OK) return B_BAD_VALUE; - BMessage message(B_REG_ADD_KEY); + BMessage message(KEY_STORE_ADD_KEY); message.AddString("keyring", keyring); message.AddMessage("key", &keyMessage); @@ -132,7 +133,7 @@ BKeyStore::RemoveKey(const char* keyring, const BKey& key) if (key._Flatten(keyMessage) != B_OK) return B_BAD_VALUE; - BMessage message(B_REG_REMOVE_KEY); + BMessage message(KEY_STORE_REMOVE_KEY); message.AddString("keyring", keyring); message.AddMessage("key", &keyMessage); @@ -166,7 +167,7 @@ status_t BKeyStore::GetNextKey(const char* keyring, BKeyType type, BKeyPurpose purpose, uint32& cookie, BKey& key) { - BMessage message(B_REG_GET_NEXT_KEY); + BMessage message(KEY_STORE_GET_NEXT_KEY); message.AddString("keyring", keyring); message.AddUInt32("type", type); message.AddUInt32("purpose", purpose); @@ -195,7 +196,7 @@ BKeyStore::AddKeyring(const char* keyring, const BKey& key) if (key._Flatten(keyMessage) != B_OK) return B_BAD_VALUE; - BMessage message(B_REG_ADD_KEYRING); + BMessage message(KEY_STORE_ADD_KEYRING); message.AddString("keyring", keyring); message.AddMessage("key", &keyMessage); @@ -206,7 +207,7 @@ BKeyStore::AddKeyring(const char* keyring, const BKey& key) status_t BKeyStore::RemoveKeyring(const char* keyring) { - BMessage message(B_REG_REMOVE_KEYRING); + BMessage message(KEY_STORE_REMOVE_KEYRING); message.AddString("keyring", keyring); return _SendKeyMessage(message, NULL); } @@ -215,7 +216,7 @@ BKeyStore::RemoveKeyring(const char* keyring) status_t BKeyStore::GetNextKeyring(uint32& cookie, BString& keyring) { - BMessage message(B_REG_GET_NEXT_KEYRING); + BMessage message(KEY_STORE_GET_NEXT_KEYRING); message.AddUInt32("cookie", cookie); BMessage reply; @@ -240,7 +241,7 @@ BKeyStore::SetMasterKey(const BKey& key) if (key._Flatten(keyMessage) != B_OK) return B_BAD_VALUE; - BMessage message(B_REG_SET_MASTER_KEY); + BMessage message(KEY_STORE_SET_MASTER_KEY); message.AddMessage("key", &keyMessage); return _SendKeyMessage(message, NULL); @@ -250,7 +251,7 @@ BKeyStore::SetMasterKey(const BKey& key) status_t BKeyStore::RemoveMasterKey() { - BMessage message(B_REG_REMOVE_MASTER_KEY); + BMessage message(KEY_STORE_REMOVE_MASTER_KEY); return _SendKeyMessage(message, NULL); } @@ -258,7 +259,7 @@ BKeyStore::RemoveMasterKey() status_t BKeyStore::AddKeyringToMaster(const char* keyring) { - BMessage message(B_REG_ADD_KEYRING_TO_MASTER); + BMessage message(KEY_STORE_ADD_KEYRING_TO_MASTER); message.AddString("keyring", keyring); return _SendKeyMessage(message, NULL); } @@ -267,7 +268,7 @@ BKeyStore::AddKeyringToMaster(const char* keyring) status_t BKeyStore::RemoveKeyringFromMaster(const char* keyring) { - BMessage message(B_REG_REMOVE_KEYRING_FROM_MASTER); + BMessage message(KEY_STORE_REMOVE_KEYRING_FROM_MASTER); message.AddString("keyring", keyring); return _SendKeyMessage(message, NULL); } @@ -276,7 +277,7 @@ BKeyStore::RemoveKeyringFromMaster(const char* keyring) status_t BKeyStore::GetNextMasterKeyring(uint32& cookie, BString& keyring) { - BMessage message(B_REG_GET_NEXT_MASTER_KEYRING); + BMessage message(KEY_STORE_GET_NEXT_MASTER_KEYRING); message.AddUInt32("cookie", cookie); BMessage reply; @@ -297,7 +298,7 @@ BKeyStore::GetNextMasterKeyring(uint32& cookie, BString& keyring) bool BKeyStore::IsKeyringAccessible(const char* keyring) { - BMessage message(B_REG_IS_KEYRING_ACCESSIBLE); + BMessage message(KEY_STORE_IS_KEYRING_ACCESSIBLE); message.AddString("keyring", keyring); return _SendKeyMessage(message, NULL) == B_OK; } @@ -306,7 +307,7 @@ BKeyStore::IsKeyringAccessible(const char* keyring) status_t BKeyStore::RevokeAccess(const char* keyring) { - BMessage message(B_REG_REVOKE_ACCESS); + BMessage message(KEY_STORE_REVOKE_ACCESS); message.AddString("keyring", keyring); return _SendKeyMessage(message, NULL); } @@ -315,7 +316,7 @@ BKeyStore::RevokeAccess(const char* keyring) status_t BKeyStore::RevokeMasterAccess() { - BMessage message(B_REG_REVOKE_MASTER_ACCESS); + BMessage message(KEY_STORE_REVOKE_MASTER_ACCESS); return _SendKeyMessage(message, NULL); } @@ -332,7 +333,7 @@ BKeyStore::GetNextApplication(const BKey& key, uint32& cookie, if (key._Flatten(keyMessage) != B_OK) return B_BAD_VALUE; - BMessage message(B_REG_GET_NEXT_APPLICATION); + BMessage message(KEY_STORE_GET_NEXT_APPLICATION); message.AddMessage("key", &keyMessage); message.AddUInt32("cookie", cookie); @@ -355,7 +356,7 @@ BKeyStore::RemoveApplication(const BKey& key, const char* signature) if (key._Flatten(keyMessage) != B_OK) return B_BAD_VALUE; - BMessage message(B_REG_REMOVE_APPLICATION); + BMessage message(KEY_STORE_REMOVE_APPLICATION); message.AddMessage("key", &keyMessage); message.AddString("signature", signature); @@ -390,10 +391,14 @@ BKeyStore::_SendKeyMessage(BMessage& message, BMessage* reply) const if (reply == NULL) reply = &localReply; - if (BRoster::Private().SendTo(&message, reply, false) != B_OK) + BMessenger messenger(kKeyStoreServerSignature); + if (!messenger.IsValid()) return B_ERROR; - if (reply->what != B_REG_SUCCESS) { + if (messenger.SendMessage(&message, reply) != B_OK) + return B_ERROR; + + if (reply->what != KEY_STORE_SUCCESS) { status_t result = B_ERROR; if (reply->FindInt32("result", &result) != B_OK) return B_ERROR; From 8d9bc9e0eea57d70aee87c11b82603c69ae3eb53 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Wed, 4 Jan 2012 13:55:56 +0100 Subject: [PATCH 043/104] Add a skeleton keystore_server. It will handle the BKeyStore messages but is yet relatively empty. It only returns an error to two messages right now. --- src/servers/Jamfile | 1 + src/servers/keystore/Jamfile | 9 + src/servers/keystore/KeyStoreServer.cpp | 379 ++++++++++++++++++++++ src/servers/keystore/KeyStoreServer.h | 24 ++ src/servers/keystore/keystore_server.rdef | 13 + 5 files changed, 426 insertions(+) create mode 100644 src/servers/keystore/Jamfile create mode 100644 src/servers/keystore/KeyStoreServer.cpp create mode 100644 src/servers/keystore/KeyStoreServer.h create mode 100644 src/servers/keystore/keystore_server.rdef diff --git a/src/servers/Jamfile b/src/servers/Jamfile index 141a8ad6ee..a2bc798595 100644 --- a/src/servers/Jamfile +++ b/src/servers/Jamfile @@ -6,6 +6,7 @@ SubInclude HAIKU_TOP src servers cddb_daemon ; SubInclude HAIKU_TOP src servers debug ; SubInclude HAIKU_TOP src servers index ; SubInclude HAIKU_TOP src servers input ; +SubInclude HAIKU_TOP src servers keystore ; SubInclude HAIKU_TOP src servers mail ; SubInclude HAIKU_TOP src servers media ; SubInclude HAIKU_TOP src servers media_addon ; diff --git a/src/servers/keystore/Jamfile b/src/servers/keystore/Jamfile new file mode 100644 index 0000000000..0cbdaf6067 --- /dev/null +++ b/src/servers/keystore/Jamfile @@ -0,0 +1,9 @@ +SubDir HAIKU_TOP src servers keystore ; + +UsePrivateHeaders app ; + +Server keystore_server : + KeyStoreServer.cpp + : be $(TARGET_LIBSTDC++) + : keystore_server.rdef +; diff --git a/src/servers/keystore/KeyStoreServer.cpp b/src/servers/keystore/KeyStoreServer.cpp new file mode 100644 index 0000000000..b0d9436c9f --- /dev/null +++ b/src/servers/keystore/KeyStoreServer.cpp @@ -0,0 +1,379 @@ +/* + * Copyright 2012, Michael Lotz, mmlr@mlotz.ch. All Rights Reserved. + * Distributed under the terms of the MIT License. + */ + + +#include "KeyStoreServer.h" + +#include + +#include + +#include + + +using namespace BPrivate; + + +KeyStoreServer::KeyStoreServer() + : + BApplication(kKeyStoreServerSignature) +{ + _InitKeyStoreDatabase(); +} + + +KeyStoreServer::~KeyStoreServer() +{ +} + + +void +KeyStoreServer::MessageReceived(BMessage* message) +{ + switch (message->what) { + case KEY_STORE_GET_KEY: + { + BMessage reply(KEY_STORE_RESULT); + reply.AddInt32("result", B_NOT_ALLOWED); + message->SendReply(&reply); + break; + } + + case KEY_STORE_GET_NEXT_KEY: + { + BMessage reply(KEY_STORE_RESULT); + reply.AddInt32("result", B_ENTRY_NOT_FOUND); + message->SendReply(&reply); + break; + } + + default: + { + printf("unknown message received: %" B_PRIu32 " \"%.4s\"\n", + message->what, (const char*)&message->what); + break; + } + } + +#if 0 + // Get thread info that contains our team ID for replying. + thread_info threadInfo; + status_t result = get_thread_info(find_thread(NULL), &threadInfo); + if (result != B_OK) + return result; + + while (true) { + KMessage message; + port_message_info messageInfo; + status_t error = message.ReceiveFrom(fRequestPort, -1, &messageInfo); + if (error != B_OK) + return B_OK; + + bool isRoot = (messageInfo.sender == 0); + + switch (message.What()) { + case B_REG_GET_PASSWD_DB: + { + // lazily build the reply + try { + if (fPasswdDBReply->What() == 1) { + FlatStore store; + int32 count = fUserDB->WriteFlatPasswdDB(store); + if (fPasswdDBReply->AddInt32("count", count) != B_OK + || fPasswdDBReply->AddData("entries", B_RAW_TYPE, + store.Buffer(), store.BufferLength(), + false) != B_OK) { + error = B_NO_MEMORY; + } + + fPasswdDBReply->SetWhat(0); + } + } catch (...) { + error = B_NO_MEMORY; + } + + if (error == B_OK) { + message.SendReply(fPasswdDBReply, -1, -1, 0, registrarTeam); + } else { + fPasswdDBReply->SetTo(1); + KMessage reply(error); + message.SendReply(&reply, -1, -1, 0, registrarTeam); + } + + break; + } + + case B_REG_GET_GROUP_DB: + { + // lazily build the reply + try { + if (fGroupDBReply->What() == 1) { + FlatStore store; + int32 count = fGroupDB->WriteFlatGroupDB(store); + if (fGroupDBReply->AddInt32("count", count) != B_OK + || fGroupDBReply->AddData("entries", B_RAW_TYPE, + store.Buffer(), store.BufferLength(), + false) != B_OK) { + error = B_NO_MEMORY; + } + + fGroupDBReply->SetWhat(0); + } + } catch (...) { + error = B_NO_MEMORY; + } + + if (error == B_OK) { + message.SendReply(fGroupDBReply, -1, -1, 0, registrarTeam); + } else { + fGroupDBReply->SetTo(1); + KMessage reply(error); + message.SendReply(&reply, -1, -1, 0, registrarTeam); + } + + break; + } + + + case B_REG_GET_SHADOW_PASSWD_DB: + { + // only root may see the shadow passwd + if (!isRoot) + error = EPERM; + + // lazily build the reply + try { + if (error == B_OK && fShadowPwdDBReply->What() == 1) { + FlatStore store; + int32 count = fUserDB->WriteFlatShadowDB(store); + if (fShadowPwdDBReply->AddInt32("count", count) != B_OK + || fShadowPwdDBReply->AddData("entries", B_RAW_TYPE, + store.Buffer(), store.BufferLength(), + false) != B_OK) { + error = B_NO_MEMORY; + } + + fShadowPwdDBReply->SetWhat(0); + } + } catch (...) { + error = B_NO_MEMORY; + } + + if (error == B_OK) { + message.SendReply(fShadowPwdDBReply, -1, -1, 0, + registrarTeam); + } else { + fShadowPwdDBReply->SetTo(1); + KMessage reply(error); + message.SendReply(&reply, -1, -1, 0, registrarTeam); + } + + break; + } + + case B_REG_GET_USER: + { + User* user = NULL; + int32 uid; + const char* name; + + // find user + if (message.FindInt32("uid", &uid) == B_OK) { + user = fUserDB->UserByID(uid); + } else if (message.FindString("name", &name) == B_OK) { + user = fUserDB->UserByName(name); + } else { + error = B_BAD_VALUE; + } + + if (error == B_OK && user == NULL) + error = ENOENT; + + bool getShadowPwd = message.GetBool("shadow", false); + + // only root may see the shadow passwd + if (error == B_OK && getShadowPwd && !isRoot) + error = EPERM; + + // add user to message + KMessage reply; + if (error == B_OK) + error = user->WriteToMessage(reply, getShadowPwd); + + // send reply + reply.SetWhat(error); + message.SendReply(&reply, -1, -1, 0, registrarTeam); + + break; + } + + case B_REG_GET_GROUP: + { + Group* group = NULL; + int32 gid; + const char* name; + + // find group + if (message.FindInt32("gid", &gid) == B_OK) { + group = fGroupDB->GroupByID(gid); + } else if (message.FindString("name", &name) == B_OK) { + group = fGroupDB->GroupByName(name); + } else { + error = B_BAD_VALUE; + } + + if (error == B_OK && group == NULL) + error = ENOENT; + + // add group to message + KMessage reply; + if (error == B_OK) + error = group->WriteToMessage(reply); + + // send reply + reply.SetWhat(error); + message.SendReply(&reply, -1, -1, 0, registrarTeam); + + break; + } + + case B_REG_GET_USER_GROUPS: + { + // get user name + const char* name; + int32 maxCount; + if (message.FindString("name", &name) != B_OK + || message.FindInt32("max count", &maxCount) != B_OK + || maxCount <= 0) { + error = B_BAD_VALUE; + } + + // get groups + gid_t groups[NGROUPS_MAX + 1]; + int32 count = 0; + if (error == B_OK) { + maxCount = min_c(maxCount, NGROUPS_MAX + 1); + count = fGroupDB->GetUserGroups(name, groups, maxCount); + } + + // add groups to message + KMessage reply; + if (error == B_OK) { + if (reply.AddInt32("count", count) != B_OK + || reply.AddData("groups", B_INT32_TYPE, + groups, min_c(maxCount, count) * sizeof(gid_t), + false) != B_OK) { + error = B_NO_MEMORY; + } + } + + // send reply + reply.SetWhat(error); + message.SendReply(&reply, -1, -1, 0, registrarTeam); + + break; + } + + case B_REG_UPDATE_USER: + { + // find user + User* user = NULL; + int32 uid; + const char* name; + + if (message.FindInt32("uid", &uid) == B_OK) { + user = fUserDB->UserByID(uid); + } else if (message.FindString("name", &name) == B_OK) { + user = fUserDB->UserByName(name); + } else { + error = B_BAD_VALUE; + } + + // only can change anything + if (error == B_OK && !isRoot) + error = EPERM; + + // check addUser vs. existing user + bool addUser = message.GetBool("add user", false); + if (error == B_OK) { + if (addUser) { + if (user != NULL) + error = EEXIST; + } else if (user == NULL) + error = ENOENT; + } + + // apply all changes + if (error == B_OK) { + // clone the user object and update it from the message + User* oldUser = user; + user = NULL; + try { + user = (oldUser != NULL ? new User(*oldUser) + : new User); + user->UpdateFromMessage(message); + + // uid and name should remain the same + if (oldUser != NULL) { + if (oldUser->UID() != user->UID() + || oldUser->Name() != user->Name()) { + error = B_BAD_VALUE; + } + } + + // replace the old user and write DBs to disk + if (error == B_OK) { + fUserDB->AddUser(user); + fUserDB->WriteToDisk(); + fPasswdDBReply->SetTo(1); + fShadowPwdDBReply->SetTo(1); + } + } catch (...) { + error = B_NO_MEMORY; + } + + if (error == B_OK) + delete oldUser; + else + delete user; + } + + // send reply + KMessage reply; + reply.SetWhat(error); + message.SendReply(&reply, -1, -1, 0, registrarTeam); + + break; + } + case B_REG_UPDATE_GROUP: + debug_printf("B_REG_UPDATE_GROUP done: currently unsupported!\n"); + break; + default: + debug_printf("REG: invalid message: %lu\n", message.What()); + + } + } +#endif +} + + +status_t +KeyStoreServer::_InitKeyStoreDatabase() +{ + return B_ERROR; +} + + +int +main(int argc, char* argv[]) +{ + KeyStoreServer* app = new(std::nothrow) KeyStoreServer(); + if (app == NULL) + return 1; + + app->Run(); + delete app; + return 0; +} diff --git a/src/servers/keystore/KeyStoreServer.h b/src/servers/keystore/KeyStoreServer.h new file mode 100644 index 0000000000..4cfffeccd4 --- /dev/null +++ b/src/servers/keystore/KeyStoreServer.h @@ -0,0 +1,24 @@ +/* + * Copyright 2012, Michael Lotz, mmlr@mlotz.ch. All Rights Reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef _KEY_STORE_SERVER_H +#define _KEY_STORE_SERVER_H + + +#include + + +class KeyStoreServer : public BApplication { +public: + KeyStoreServer(); +virtual ~KeyStoreServer(); + +virtual void MessageReceived(BMessage* message); + +private: + status_t _InitKeyStoreDatabase(); +}; + + +#endif // _KEY_STORE_SERVER_H diff --git a/src/servers/keystore/keystore_server.rdef b/src/servers/keystore/keystore_server.rdef new file mode 100644 index 0000000000..fb48e7ab37 --- /dev/null +++ b/src/servers/keystore/keystore_server.rdef @@ -0,0 +1,13 @@ +resource app_signature "application/x-vnd.Haiku-keystore_server"; + +resource app_flags B_EXCLUSIVE_LAUNCH; + +resource app_version { + major = 1, + middle = 0, + minor = 0, + variety = B_APPV_ALPHA, + internal = 0, + short_info = "keystore_server", + long_info = "keystore_server ©2012 Haiku, Inc." +}; From c494c06109579891eacfd6f63506b0047963fde0 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Wed, 4 Jan 2012 13:57:17 +0100 Subject: [PATCH 044/104] Add B*Key::PrintToStream() method for debugging convenience. --- headers/os/app/Key.h | 4 ++++ src/kits/app/Key.cpp | 45 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/headers/os/app/Key.h b/headers/os/app/Key.h index 147104223b..ffd66c83ea 100644 --- a/headers/os/app/Key.h +++ b/headers/os/app/Key.h @@ -73,6 +73,8 @@ public: bool operator==(const BKey& other) const; bool operator!=(const BKey& other) const; + virtual void PrintToStream(); + protected: virtual status_t _Flatten(BMessage& message) const; virtual status_t _Unflatten(const BMessage& message); @@ -108,6 +110,8 @@ public: status_t SetPassword(const char* password); const char* Password() const; + + virtual void PrintToStream(); }; #endif // _KEY_H diff --git a/src/kits/app/Key.cpp b/src/kits/app/Key.cpp index a112e74c12..b575255d18 100644 --- a/src/kits/app/Key.cpp +++ b/src/kits/app/Key.cpp @@ -6,6 +6,8 @@ #include +#include + #if 0 // TODO: move this to the KeyStore or the registrar backend if needed @@ -198,6 +200,40 @@ BKey::operator!=(const BKey& other) const } +void +BKey::PrintToStream() +{ + if (Type() == B_KEY_TYPE_GENERIC) + printf("generic key:\n"); + + const char* purposeString = "unknown"; + switch (fPurpose) { + case B_KEY_PURPOSE_ANY: + purposeString = "any"; + break; + case B_KEY_PURPOSE_GENERIC: + purposeString = "generic"; + break; + case B_KEY_PURPOSE_WEB: + purposeString = "web"; + break; + case B_KEY_PURPOSE_NETWORK: + purposeString = "network"; + break; + case B_KEY_PURPOSE_VOLUME: + purposeString = "volume"; + break; + } + + printf("\tpurpose: %s\n", purposeString); + printf("\tidentifier: \"%s\"\n", fIdentifier.String()); + printf("\tsecondary identifier: \"%s\"\n", fSecondaryIdentifier.String()); + printf("\towner: \"%s\"\n", fOwner.String()); + printf("\tcreation time: %" B_PRIu64 "\n", fCreationTime); + printf("\traw data length: %" B_PRIuSIZE "\n", fData.BufferLength()); +} + + status_t BKey::_Flatten(BMessage& message) const { @@ -290,3 +326,12 @@ BPasswordKey::Password() const { return (const char*)Data(); } + + +void +BPasswordKey::PrintToStream() +{ + printf("password key:\n"); + BKey::PrintToStream(); + printf("\tpassword: \"%s\"\n", Password()); +} From 05480477ff0fa29c44932d1542ecac9cda45c5ad Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Wed, 4 Jan 2012 13:57:53 +0100 Subject: [PATCH 045/104] Add a simple command line tool to interact with the keystore. The app is yet almost empty but will gradually grow to include enumeration and possibly modification functions for the keystore. --- src/bin/Jamfile | 1 + src/bin/keystore.cpp | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 src/bin/keystore.cpp diff --git a/src/bin/Jamfile b/src/bin/Jamfile index 4d1f6530bb..e4f0116810 100644 --- a/src/bin/Jamfile +++ b/src/bin/Jamfile @@ -88,6 +88,7 @@ StdBinCommands draggers.cpp ffm.cpp iroster.cpp + keystore.cpp listattr.cpp listfont.cpp listres.cpp diff --git a/src/bin/keystore.cpp b/src/bin/keystore.cpp new file mode 100644 index 0000000000..2c95f47514 --- /dev/null +++ b/src/bin/keystore.cpp @@ -0,0 +1,37 @@ +/* + * Copyright 2012, Haiku Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Michael Lotz, mmlr@mlotz.ch + */ + + +#include + +#include + + +int +main(int argc, char* argv[]) +{ + BKeyStore keyStore; + BPasswordKey password; + uint32 cookie = 0; + + while (true) { + printf("trying to get next password with cookie: %" B_PRIu32 "\n", + cookie); + + status_t result = keyStore.GetNextKey(B_KEY_TYPE_PASSWORD, + B_KEY_PURPOSE_ANY, cookie, password); + if (result != B_OK) { + printf("failed with: %s\n", strerror(result)); + break; + } + + password.PrintToStream(); + } + + return 0; +} From 37ac7cb2de2781edeb00329881d012ba5761bb1a Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Wed, 4 Jan 2012 15:42:15 +0100 Subject: [PATCH 046/104] Update the cookie from the reply message. --- src/kits/app/KeyStore.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/kits/app/KeyStore.cpp b/src/kits/app/KeyStore.cpp index 70091cb341..55bc8def55 100644 --- a/src/kits/app/KeyStore.cpp +++ b/src/kits/app/KeyStore.cpp @@ -182,6 +182,7 @@ BKeyStore::GetNextKey(const char* keyring, BKeyType type, BKeyPurpose purpose, if (reply.FindMessage("key", &keyMessage) != B_OK) return B_ERROR; + reply.FindUInt32("cookie", &cookie); return key._Unflatten(keyMessage); } @@ -227,6 +228,7 @@ BKeyStore::GetNextKeyring(uint32& cookie, BString& keyring) if (reply.FindString("keyring", &keyring) != B_OK) return B_ERROR; + reply.FindUInt32("cookie", &cookie); return B_OK; } @@ -288,6 +290,7 @@ BKeyStore::GetNextMasterKeyring(uint32& cookie, BString& keyring) if (reply.FindString("keyring", &keyring) != B_OK) return B_ERROR; + reply.FindUInt32("cookie", &cookie); return B_OK; } @@ -345,6 +348,7 @@ BKeyStore::GetNextApplication(const BKey& key, uint32& cookie, if (reply.FindString("signature", &signature) != B_OK) return B_ERROR; + reply.FindUInt32("cookie", &cookie); return B_OK; } From 0dfaf59dbbc5319b1a52ef4108ea3ab64f8d2729 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Wed, 4 Jan 2012 15:43:13 +0100 Subject: [PATCH 047/104] Implement basic storage and lookup functions. * Add reading/writing a yet unprotected flat BMessage as the storage backend for the keys. * Factor out the identifier based lookup logic into _FindKey() and use that from _AddKey() to detect duplicates. * Add _FindKey() variant that does the lookup based on given type and purpose constraints. --- src/servers/keystore/KeyStoreServer.cpp | 228 +++++++++++++++++++++++- src/servers/keystore/KeyStoreServer.h | 20 ++- 2 files changed, 238 insertions(+), 10 deletions(-) diff --git a/src/servers/keystore/KeyStoreServer.cpp b/src/servers/keystore/KeyStoreServer.cpp index b0d9436c9f..cde0a84a45 100644 --- a/src/servers/keystore/KeyStoreServer.cpp +++ b/src/servers/keystore/KeyStoreServer.cpp @@ -8,6 +8,12 @@ #include +#include +#include +#include +#include +#include + #include #include @@ -20,7 +26,27 @@ KeyStoreServer::KeyStoreServer() : BApplication(kKeyStoreServerSignature) { - _InitKeyStoreDatabase(); + BPath path; + if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK) + return; + + BDirectory settingsDir(path.Path()); + path.Append("system"); + if (!settingsDir.Contains(path.Path())) + settingsDir.CreateDirectory(path.Path(), NULL); + + settingsDir.SetTo(path.Path()); + path.Append("keystore"); + if (!settingsDir.Contains(path.Path())) + settingsDir.CreateDirectory(path.Path(), NULL); + + settingsDir.SetTo(path.Path()); + path.Append("keystore_database"); + + fKeyStoreFile.SetTo(path.Path(), B_READ_WRITE + | (settingsDir.Contains(path.Path()) ? 0 : B_CREATE_FILE)); + + _ReadKeyStoreDatabase(); } @@ -32,20 +58,56 @@ KeyStoreServer::~KeyStoreServer() void KeyStoreServer::MessageReceived(BMessage* message) { + BMessage reply; + status_t result = B_MESSAGE_NOT_UNDERSTOOD; + switch (message->what) { case KEY_STORE_GET_KEY: { - BMessage reply(KEY_STORE_RESULT); - reply.AddInt32("result", B_NOT_ALLOWED); - message->SendReply(&reply); + result = B_NOT_ALLOWED; break; } case KEY_STORE_GET_NEXT_KEY: { - BMessage reply(KEY_STORE_RESULT); - reply.AddInt32("result", B_ENTRY_NOT_FOUND); - message->SendReply(&reply); + BKeyType type; + BKeyPurpose purpose; + uint32 cookie; + if (message->FindUInt32("type", (uint32*)&type) != B_OK + || message->FindUInt32("purpose", (uint32*)&purpose) != B_OK + || message->FindUInt32("cookie", &cookie) != B_OK) { + result = B_BAD_VALUE; + break; + } + + BMessage keyMessage; + result = _FindKey(type, purpose, cookie, keyMessage); + if (result == B_OK) { + cookie++; + reply.AddUInt32("cookie", cookie); + reply.AddMessage("key", &keyMessage); + } + + break; + } + + case KEY_STORE_ADD_KEY: + { + BMessage keyMessage; + BString identifier; + if (message->FindMessage("key", &keyMessage) != B_OK + || keyMessage.FindString("identifier", &identifier) != B_OK) { + result = B_BAD_VALUE; + break; + } + + BString secondaryIdentifier; + if (keyMessage.FindString("secondaryIdentifier", + &secondaryIdentifier) != B_OK) { + secondaryIdentifier = ""; + } + + result = _AddKey(identifier, secondaryIdentifier, keyMessage); break; } @@ -57,6 +119,17 @@ KeyStoreServer::MessageReceived(BMessage* message) } } + if (message->IsSourceWaiting()) { + if (result == B_OK) + reply.what = KEY_STORE_SUCCESS; + else { + reply.what = KEY_STORE_RESULT; + reply.AddInt32("result", result); + } + + message->SendReply(&reply); + } + #if 0 // Get thread info that contains our team ID for replying. thread_info threadInfo; @@ -360,9 +433,146 @@ KeyStoreServer::MessageReceived(BMessage* message) status_t -KeyStoreServer::_InitKeyStoreDatabase() +KeyStoreServer::_ReadKeyStoreDatabase() { - return B_ERROR; + status_t result = fDatabase.Unflatten(&fKeyStoreFile); + if (result != B_OK) { + printf("failed to read keystore database\n"); + fDatabase.MakeEmpty(); + _WriteKeyStoreDatabase(); + return result; + } + + return B_OK; +} + + +status_t +KeyStoreServer::_WriteKeyStoreDatabase() +{ + fKeyStoreFile.SetSize(0); + fKeyStoreFile.Seek(0, SEEK_SET); + return fDatabase.Flatten(&fKeyStoreFile); +} + + +status_t +KeyStoreServer::_FindKey(const BString& identifier, + const BString& secondaryIdentifier, bool secondaryIdentifierOptional, + BMessage* _foundKeyMessage) +{ + int32 count; + type_code type; + if (fDatabase.GetInfo(identifier, &type, &count) != B_OK) + return B_ENTRY_NOT_FOUND; + + // We have a matching primary identifier, need to check for the secondary + // identifier. + for (int32 i = 0; i < count; i++) { + BMessage candidate; + if (fDatabase.FindMessage(identifier, i, &candidate) != B_OK) + return B_ERROR; + + BString candidateIdentifier; + if (candidate.FindString("secondaryIdentifier", + &candidateIdentifier) != B_OK) { + candidateIdentifier = ""; + } + + if (candidateIdentifier == secondaryIdentifier) { + if (_foundKeyMessage != NULL) + *_foundKeyMessage = candidate; + return B_OK; + } + } + + // We didn't find an exact match. + if (secondaryIdentifierOptional) { + if (_foundKeyMessage == NULL) + return B_OK; + + // The secondary identifier is optional, so we just return the + // first entry. + return fDatabase.FindMessage(identifier, 0, _foundKeyMessage); + } + + return B_ENTRY_NOT_FOUND; +} + + +status_t +KeyStoreServer::_FindKey(BKeyType type, BKeyPurpose purpose, uint32 index, + BMessage& _foundKeyMessage) +{ + for (int32 keyIndex = 0;; keyIndex++) { + int32 count = 0; + char* identifier = NULL; + if (fDatabase.GetInfo(B_MESSAGE_TYPE, keyIndex, &identifier, NULL, + &count) != B_OK) { + break; + } + + if (type == B_KEY_TYPE_ANY && purpose == B_KEY_PURPOSE_ANY) { + // No need to inspect the actual keys. + if ((int32)index >= count) { + index -= count; + continue; + } + + return fDatabase.FindMessage(identifier, index, &_foundKeyMessage); + } + + // Go through the keys to check their type and purpose. + for (int32 subkeyIndex = 0; subkeyIndex < count; subkeyIndex++) { + BMessage subkey; + if (fDatabase.FindMessage(identifier, subkeyIndex, &subkey) != B_OK) + return B_ERROR; + + bool match = true; + if (type != B_KEY_TYPE_ANY) { + BKeyType subkeyType; + if (subkey.FindUInt32("type", (uint32*)&subkeyType) != B_OK) + return B_ERROR; + + match = subkeyType == type; + } + + if (match && purpose != B_KEY_PURPOSE_ANY) { + BKeyPurpose subkeyPurpose; + if (subkey.FindUInt32("purpose", (uint32*)&subkeyPurpose) + != B_OK) { + return B_ERROR; + } + + match = subkeyPurpose == purpose; + } + + if (match) { + if (index == 0) { + _foundKeyMessage = subkey; + return B_OK; + } + + index--; + } + } + } + + return B_ENTRY_NOT_FOUND; +} + + +status_t +KeyStoreServer::_AddKey(const BString& identifier, + const BString& secondaryIdentifier, const BMessage& keyMessage) +{ + // Check for collisions. + if (_FindKey(identifier, secondaryIdentifier, false, NULL) == B_OK) + return B_NAME_IN_USE; + + // We're fine, just add the new key. + fDatabase.AddMessage(identifier, &keyMessage); + return _WriteKeyStoreDatabase(); } diff --git a/src/servers/keystore/KeyStoreServer.h b/src/servers/keystore/KeyStoreServer.h index 4cfffeccd4..1d0c3b46d1 100644 --- a/src/servers/keystore/KeyStoreServer.h +++ b/src/servers/keystore/KeyStoreServer.h @@ -7,6 +7,8 @@ #include +#include +#include class KeyStoreServer : public BApplication { @@ -17,7 +19,23 @@ virtual ~KeyStoreServer(); virtual void MessageReceived(BMessage* message); private: - status_t _InitKeyStoreDatabase(); + status_t _ReadKeyStoreDatabase(); + status_t _WriteKeyStoreDatabase(); + + status_t _FindKey(const BString& identifier, + const BString& secondaryIdentifier, + bool secondaryIdentifierOptional, + BMessage* _foundKeyMessage); + status_t _FindKey(BKeyType type, BKeyPurpose purpose, + uint32 index, + BMessage& _foundKeyMessage); + + status_t _AddKey(const BString& identifier, + const BString& secondaryIdentifier, + const BMessage& keyMessage); + + BMessage fDatabase; + BFile fKeyStoreFile; }; From d962e21058c76cbd80f1deda9e5b3cbf855dfc99 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Wed, 4 Jan 2012 22:37:49 +0100 Subject: [PATCH 048/104] Add B_KEY_PURPOSE_KEYRING for keyring keys. --- headers/os/app/Key.h | 1 + src/kits/app/Key.cpp | 3 +++ 2 files changed, 4 insertions(+) diff --git a/headers/os/app/Key.h b/headers/os/app/Key.h index ffd66c83ea..0f4110e2c5 100644 --- a/headers/os/app/Key.h +++ b/headers/os/app/Key.h @@ -15,6 +15,7 @@ enum BKeyPurpose { B_KEY_PURPOSE_ANY, B_KEY_PURPOSE_GENERIC, + B_KEY_PURPOSE_KEYRING, B_KEY_PURPOSE_WEB, B_KEY_PURPOSE_NETWORK, B_KEY_PURPOSE_VOLUME diff --git a/src/kits/app/Key.cpp b/src/kits/app/Key.cpp index b575255d18..3d0df5ffb0 100644 --- a/src/kits/app/Key.cpp +++ b/src/kits/app/Key.cpp @@ -214,6 +214,9 @@ BKey::PrintToStream() case B_KEY_PURPOSE_GENERIC: purposeString = "generic"; break; + case B_KEY_PURPOSE_KEYRING: + purposeString = "keyring"; + break; case B_KEY_PURPOSE_WEB: purposeString = "web"; break; From 95eee1a36302940cff0bcf81d943b9d59c60bac2 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Wed, 4 Jan 2012 23:22:42 +0100 Subject: [PATCH 049/104] Make the keystore_server keyring aware. * Move the *Key() functions into a Keyring class. * Retrieve and select the right keyring for various commands. * Implement adding/removing/enumerating keyrings. * Rework the keystore database read/write to work with keyrings. * Sync BKeyStore::IsKeyringAccessible() with the changed message. * Remove leftover template code from registrar. --- src/kits/app/KeyStore.cpp | 11 +- src/servers/keystore/Jamfile | 2 + src/servers/keystore/KeyStoreServer.cpp | 646 +++++++++--------------- src/servers/keystore/KeyStoreServer.h | 21 +- src/servers/keystore/Keyring.cpp | 185 +++++++ src/servers/keystore/Keyring.h | 49 ++ 6 files changed, 482 insertions(+), 432 deletions(-) create mode 100644 src/servers/keystore/Keyring.cpp create mode 100644 src/servers/keystore/Keyring.h diff --git a/src/kits/app/KeyStore.cpp b/src/kits/app/KeyStore.cpp index 55bc8def55..91d9fc8be8 100644 --- a/src/kits/app/KeyStore.cpp +++ b/src/kits/app/KeyStore.cpp @@ -303,7 +303,16 @@ BKeyStore::IsKeyringAccessible(const char* keyring) { BMessage message(KEY_STORE_IS_KEYRING_ACCESSIBLE); message.AddString("keyring", keyring); - return _SendKeyMessage(message, NULL) == B_OK; + + BMessage reply; + if (_SendKeyMessage(message, &reply) != B_OK) + return false; + + bool accessible; + if (reply.FindBool("accessible", &accessible) != B_OK) + return false; + + return accessible; } diff --git a/src/servers/keystore/Jamfile b/src/servers/keystore/Jamfile index 0cbdaf6067..ed51642e49 100644 --- a/src/servers/keystore/Jamfile +++ b/src/servers/keystore/Jamfile @@ -3,7 +3,9 @@ SubDir HAIKU_TOP src servers keystore ; UsePrivateHeaders app ; Server keystore_server : + Keyring.cpp KeyStoreServer.cpp + : be $(TARGET_LIBSTDC++) : keystore_server.rdef ; diff --git a/src/servers/keystore/KeyStoreServer.cpp b/src/servers/keystore/KeyStoreServer.cpp index cde0a84a45..caca6a7255 100644 --- a/src/servers/keystore/KeyStoreServer.cpp +++ b/src/servers/keystore/KeyStoreServer.cpp @@ -5,6 +5,7 @@ #include "KeyStoreServer.h" +#include "Keyring.h" #include @@ -24,7 +25,9 @@ using namespace BPrivate; KeyStoreServer::KeyStoreServer() : - BApplication(kKeyStoreServerSignature) + BApplication(kKeyStoreServerSignature), + fDefaultKeyring(NULL), + fKeyrings(20, true) { BPath path; if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK) @@ -47,6 +50,9 @@ KeyStoreServer::KeyStoreServer() | (settingsDir.Contains(path.Path()) ? 0 : B_CREATE_FILE)); _ReadKeyStoreDatabase(); + + if (fDefaultKeyring == NULL) + fDefaultKeyring = new(std::nothrow) Keyring("", BMessage()); } @@ -59,12 +65,61 @@ void KeyStoreServer::MessageReceived(BMessage* message) { BMessage reply; - status_t result = B_MESSAGE_NOT_UNDERSTOOD; + status_t result = B_UNSUPPORTED; + + // Resolve the keyring for the relevant messages. + Keyring* keyring = NULL; + switch (message->what) { + case KEY_STORE_GET_KEY: + case KEY_STORE_GET_NEXT_KEY: + case KEY_STORE_ADD_KEY: + case KEY_STORE_REMOVE_KEY: + case KEY_STORE_IS_KEYRING_ACCESSIBLE: + case KEY_STORE_REVOKE_ACCESS: + { + BString keyringName; + if (message->FindString("keyring", &keyringName) != B_OK) + keyringName = ""; + + keyring = _FindKeyring(keyringName); + if (keyring == NULL) { + result = B_BAD_VALUE; + message->what = 0; + // So that we don't do anything in the second switch. + break; + } + + break; + } + } switch (message->what) { case KEY_STORE_GET_KEY: { - result = B_NOT_ALLOWED; + BString identifier; + if (message->FindString("identifier", &identifier) != B_OK) { + result = B_BAD_VALUE; + break; + } + + bool secondaryIdentifierOptional; + if (message->FindBool("secondaryIdentifierOptional", + &secondaryIdentifierOptional) != B_OK) { + secondaryIdentifierOptional = false; + } + + BString secondaryIdentifier; + if (message->FindString("secondaryIdentifier", + &secondaryIdentifier) != B_OK) { + secondaryIdentifier = ""; + secondaryIdentifierOptional = true; + } + + BMessage keyMessage; + result = keyring->FindKey(identifier, secondaryIdentifier, + secondaryIdentifierOptional, &keyMessage); + if (result == B_OK) + reply.AddMessage("key", &keyMessage); break; } @@ -81,7 +136,7 @@ KeyStoreServer::MessageReceived(BMessage* message) } BMessage keyMessage; - result = _FindKey(type, purpose, cookie, keyMessage); + result = keyring->FindKey(type, purpose, cookie, keyMessage); if (result == B_OK) { cookie++; reply.AddUInt32("cookie", cookie); @@ -107,7 +162,94 @@ KeyStoreServer::MessageReceived(BMessage* message) secondaryIdentifier = ""; } - result = _AddKey(identifier, secondaryIdentifier, keyMessage); + result = keyring->AddKey(identifier, secondaryIdentifier, keyMessage); + if (result == B_OK) + _WriteKeyStoreDatabase(); + + break; + } + + case KEY_STORE_REMOVE_KEY: + { + BMessage keyMessage; + BString identifier; + if (message->FindMessage("key", &keyMessage) != B_OK + || keyMessage.FindString("identifier", &identifier) != B_OK) { + result = B_BAD_VALUE; + break; + } + + result = keyring->RemoveKey(identifier, keyMessage); + if (result == B_OK) + _WriteKeyStoreDatabase(); + + break; + } + + case KEY_STORE_ADD_KEYRING: + { + BMessage keyMessage; + BString keyring; + if (message->FindString("keyring", &keyring) != B_OK + || message->FindMessage("key", &keyMessage) != B_OK) { + result = B_BAD_VALUE; + break; + } + + result = _AddKeyring(keyring, keyMessage); + if (result == B_OK) + _WriteKeyStoreDatabase(); + + break; + } + + case KEY_STORE_REMOVE_KEYRING: + { + BString keyringName; + if (message->FindString("keyring", &keyringName) != B_OK) + keyringName = ""; + + result = _RemoveKeyring(keyringName); + if (result == B_OK) + _WriteKeyStoreDatabase(); + + break; + } + + case KEY_STORE_GET_NEXT_KEYRING: + { + uint32 cookie; + if (message->FindUInt32("cookie", &cookie) != B_OK) { + result = B_BAD_VALUE; + break; + } + + if (cookie == 0) + keyring = fDefaultKeyring; + else + keyring = fKeyrings.ItemAt(cookie - 1); + + if (keyring == NULL) { + result = B_ENTRY_NOT_FOUND; + break; + } + + cookie++; + reply.AddUInt32("cookie", cookie); + reply.AddString("keyring", keyring->Name()); + result = B_OK; + break; + } + + case KEY_STORE_IS_KEYRING_ACCESSIBLE: + { + reply.AddBool("accessible", keyring->IsAccessible()); + result = B_OK; + } + + case 0: + { + // Just the error case from above. break; } @@ -129,320 +271,44 @@ KeyStoreServer::MessageReceived(BMessage* message) message->SendReply(&reply); } - -#if 0 - // Get thread info that contains our team ID for replying. - thread_info threadInfo; - status_t result = get_thread_info(find_thread(NULL), &threadInfo); - if (result != B_OK) - return result; - - while (true) { - KMessage message; - port_message_info messageInfo; - status_t error = message.ReceiveFrom(fRequestPort, -1, &messageInfo); - if (error != B_OK) - return B_OK; - - bool isRoot = (messageInfo.sender == 0); - - switch (message.What()) { - case B_REG_GET_PASSWD_DB: - { - // lazily build the reply - try { - if (fPasswdDBReply->What() == 1) { - FlatStore store; - int32 count = fUserDB->WriteFlatPasswdDB(store); - if (fPasswdDBReply->AddInt32("count", count) != B_OK - || fPasswdDBReply->AddData("entries", B_RAW_TYPE, - store.Buffer(), store.BufferLength(), - false) != B_OK) { - error = B_NO_MEMORY; - } - - fPasswdDBReply->SetWhat(0); - } - } catch (...) { - error = B_NO_MEMORY; - } - - if (error == B_OK) { - message.SendReply(fPasswdDBReply, -1, -1, 0, registrarTeam); - } else { - fPasswdDBReply->SetTo(1); - KMessage reply(error); - message.SendReply(&reply, -1, -1, 0, registrarTeam); - } - - break; - } - - case B_REG_GET_GROUP_DB: - { - // lazily build the reply - try { - if (fGroupDBReply->What() == 1) { - FlatStore store; - int32 count = fGroupDB->WriteFlatGroupDB(store); - if (fGroupDBReply->AddInt32("count", count) != B_OK - || fGroupDBReply->AddData("entries", B_RAW_TYPE, - store.Buffer(), store.BufferLength(), - false) != B_OK) { - error = B_NO_MEMORY; - } - - fGroupDBReply->SetWhat(0); - } - } catch (...) { - error = B_NO_MEMORY; - } - - if (error == B_OK) { - message.SendReply(fGroupDBReply, -1, -1, 0, registrarTeam); - } else { - fGroupDBReply->SetTo(1); - KMessage reply(error); - message.SendReply(&reply, -1, -1, 0, registrarTeam); - } - - break; - } - - - case B_REG_GET_SHADOW_PASSWD_DB: - { - // only root may see the shadow passwd - if (!isRoot) - error = EPERM; - - // lazily build the reply - try { - if (error == B_OK && fShadowPwdDBReply->What() == 1) { - FlatStore store; - int32 count = fUserDB->WriteFlatShadowDB(store); - if (fShadowPwdDBReply->AddInt32("count", count) != B_OK - || fShadowPwdDBReply->AddData("entries", B_RAW_TYPE, - store.Buffer(), store.BufferLength(), - false) != B_OK) { - error = B_NO_MEMORY; - } - - fShadowPwdDBReply->SetWhat(0); - } - } catch (...) { - error = B_NO_MEMORY; - } - - if (error == B_OK) { - message.SendReply(fShadowPwdDBReply, -1, -1, 0, - registrarTeam); - } else { - fShadowPwdDBReply->SetTo(1); - KMessage reply(error); - message.SendReply(&reply, -1, -1, 0, registrarTeam); - } - - break; - } - - case B_REG_GET_USER: - { - User* user = NULL; - int32 uid; - const char* name; - - // find user - if (message.FindInt32("uid", &uid) == B_OK) { - user = fUserDB->UserByID(uid); - } else if (message.FindString("name", &name) == B_OK) { - user = fUserDB->UserByName(name); - } else { - error = B_BAD_VALUE; - } - - if (error == B_OK && user == NULL) - error = ENOENT; - - bool getShadowPwd = message.GetBool("shadow", false); - - // only root may see the shadow passwd - if (error == B_OK && getShadowPwd && !isRoot) - error = EPERM; - - // add user to message - KMessage reply; - if (error == B_OK) - error = user->WriteToMessage(reply, getShadowPwd); - - // send reply - reply.SetWhat(error); - message.SendReply(&reply, -1, -1, 0, registrarTeam); - - break; - } - - case B_REG_GET_GROUP: - { - Group* group = NULL; - int32 gid; - const char* name; - - // find group - if (message.FindInt32("gid", &gid) == B_OK) { - group = fGroupDB->GroupByID(gid); - } else if (message.FindString("name", &name) == B_OK) { - group = fGroupDB->GroupByName(name); - } else { - error = B_BAD_VALUE; - } - - if (error == B_OK && group == NULL) - error = ENOENT; - - // add group to message - KMessage reply; - if (error == B_OK) - error = group->WriteToMessage(reply); - - // send reply - reply.SetWhat(error); - message.SendReply(&reply, -1, -1, 0, registrarTeam); - - break; - } - - case B_REG_GET_USER_GROUPS: - { - // get user name - const char* name; - int32 maxCount; - if (message.FindString("name", &name) != B_OK - || message.FindInt32("max count", &maxCount) != B_OK - || maxCount <= 0) { - error = B_BAD_VALUE; - } - - // get groups - gid_t groups[NGROUPS_MAX + 1]; - int32 count = 0; - if (error == B_OK) { - maxCount = min_c(maxCount, NGROUPS_MAX + 1); - count = fGroupDB->GetUserGroups(name, groups, maxCount); - } - - // add groups to message - KMessage reply; - if (error == B_OK) { - if (reply.AddInt32("count", count) != B_OK - || reply.AddData("groups", B_INT32_TYPE, - groups, min_c(maxCount, count) * sizeof(gid_t), - false) != B_OK) { - error = B_NO_MEMORY; - } - } - - // send reply - reply.SetWhat(error); - message.SendReply(&reply, -1, -1, 0, registrarTeam); - - break; - } - - case B_REG_UPDATE_USER: - { - // find user - User* user = NULL; - int32 uid; - const char* name; - - if (message.FindInt32("uid", &uid) == B_OK) { - user = fUserDB->UserByID(uid); - } else if (message.FindString("name", &name) == B_OK) { - user = fUserDB->UserByName(name); - } else { - error = B_BAD_VALUE; - } - - // only can change anything - if (error == B_OK && !isRoot) - error = EPERM; - - // check addUser vs. existing user - bool addUser = message.GetBool("add user", false); - if (error == B_OK) { - if (addUser) { - if (user != NULL) - error = EEXIST; - } else if (user == NULL) - error = ENOENT; - } - - // apply all changes - if (error == B_OK) { - // clone the user object and update it from the message - User* oldUser = user; - user = NULL; - try { - user = (oldUser != NULL ? new User(*oldUser) - : new User); - user->UpdateFromMessage(message); - - // uid and name should remain the same - if (oldUser != NULL) { - if (oldUser->UID() != user->UID() - || oldUser->Name() != user->Name()) { - error = B_BAD_VALUE; - } - } - - // replace the old user and write DBs to disk - if (error == B_OK) { - fUserDB->AddUser(user); - fUserDB->WriteToDisk(); - fPasswdDBReply->SetTo(1); - fShadowPwdDBReply->SetTo(1); - } - } catch (...) { - error = B_NO_MEMORY; - } - - if (error == B_OK) - delete oldUser; - else - delete user; - } - - // send reply - KMessage reply; - reply.SetWhat(error); - message.SendReply(&reply, -1, -1, 0, registrarTeam); - - break; - } - case B_REG_UPDATE_GROUP: - debug_printf("B_REG_UPDATE_GROUP done: currently unsupported!\n"); - break; - default: - debug_printf("REG: invalid message: %lu\n", message.What()); - - } - } -#endif } status_t KeyStoreServer::_ReadKeyStoreDatabase() { - status_t result = fDatabase.Unflatten(&fKeyStoreFile); + BMessage keyrings; + status_t result = keyrings.Unflatten(&fKeyStoreFile); if (result != B_OK) { printf("failed to read keystore database\n"); - fDatabase.MakeEmpty(); _WriteKeyStoreDatabase(); return result; } + int32 index = 0; + char* keyringName = NULL; + while (keyrings.GetInfo(B_MESSAGE_TYPE, index++, &keyringName, + NULL) == B_OK) { + + BMessage keyringData; + if (keyrings.FindMessage(keyringName, &keyringData) != B_OK) { + printf("failed to retrieve keyring data for keyring \"%s\"\n", + keyringName); + continue; + } + + Keyring* keyring = new(std::nothrow) Keyring(keyringName, keyringData); + if (keyring == NULL) { + printf("no memory for allocating keyring \"%s\"\n", keyringName); + continue; + } + + if (strlen(keyringName) == 0) + fDefaultKeyring = keyring; + else + fKeyrings.BinaryInsert(keyring, &Keyring::Compare); + } + return B_OK; } @@ -452,127 +318,65 @@ KeyStoreServer::_WriteKeyStoreDatabase() { fKeyStoreFile.SetSize(0); fKeyStoreFile.Seek(0, SEEK_SET); - return fDatabase.Flatten(&fKeyStoreFile); + + BMessage keyrings; + if (fDefaultKeyring != NULL) + keyrings.AddMessage("", &fDefaultKeyring->Data()); + + for (int32 i = 0; i < fKeyrings.CountItems(); i++) { + Keyring* keyring = fKeyrings.ItemAt(i); + if (keyring == NULL) + continue; + + keyrings.AddMessage(keyring->Name(), &keyring->Data()); + } + + return keyrings.Flatten(&fKeyStoreFile); +} + + +Keyring* +KeyStoreServer::_FindKeyring(const BString& name) +{ + if (name.IsEmpty()) + return fDefaultKeyring; + + return fKeyrings.BinarySearchByKey(name, &Keyring::Compare); } status_t -KeyStoreServer::_FindKey(const BString& identifier, - const BString& secondaryIdentifier, bool secondaryIdentifierOptional, - BMessage* _foundKeyMessage) +KeyStoreServer::_AddKeyring(const BString& name, const BMessage& keyMessage) { - int32 count; - type_code type; - if (fDatabase.GetInfo(identifier, &type, &count) != B_OK) - return B_ENTRY_NOT_FOUND; - - // We have a matching primary identifier, need to check for the secondary - // identifier. - for (int32 i = 0; i < count; i++) { - BMessage candidate; - if (fDatabase.FindMessage(identifier, i, &candidate) != B_OK) - return B_ERROR; - - BString candidateIdentifier; - if (candidate.FindString("secondaryIdentifier", - &candidateIdentifier) != B_OK) { - candidateIdentifier = ""; - } - - if (candidateIdentifier == secondaryIdentifier) { - if (_foundKeyMessage != NULL) - *_foundKeyMessage = candidate; - return B_OK; - } - } - - // We didn't find an exact match. - if (secondaryIdentifierOptional) { - if (_foundKeyMessage == NULL) - return B_OK; - - // The secondary identifier is optional, so we just return the - // first entry. - return fDatabase.FindMessage(identifier, 0, _foundKeyMessage); - } - - return B_ENTRY_NOT_FOUND; -} - - -status_t -KeyStoreServer::_FindKey(BKeyType type, BKeyPurpose purpose, uint32 index, - BMessage& _foundKeyMessage) -{ - for (int32 keyIndex = 0;; keyIndex++) { - int32 count = 0; - char* identifier = NULL; - if (fDatabase.GetInfo(B_MESSAGE_TYPE, keyIndex, &identifier, NULL, - &count) != B_OK) { - break; - } - - if (type == B_KEY_TYPE_ANY && purpose == B_KEY_PURPOSE_ANY) { - // No need to inspect the actual keys. - if ((int32)index >= count) { - index -= count; - continue; - } - - return fDatabase.FindMessage(identifier, index, &_foundKeyMessage); - } - - // Go through the keys to check their type and purpose. - for (int32 subkeyIndex = 0; subkeyIndex < count; subkeyIndex++) { - BMessage subkey; - if (fDatabase.FindMessage(identifier, subkeyIndex, &subkey) != B_OK) - return B_ERROR; - - bool match = true; - if (type != B_KEY_TYPE_ANY) { - BKeyType subkeyType; - if (subkey.FindUInt32("type", (uint32*)&subkeyType) != B_OK) - return B_ERROR; - - match = subkeyType == type; - } - - if (match && purpose != B_KEY_PURPOSE_ANY) { - BKeyPurpose subkeyPurpose; - if (subkey.FindUInt32("purpose", (uint32*)&subkeyPurpose) - != B_OK) { - return B_ERROR; - } - - match = subkeyPurpose == purpose; - } - - if (match) { - if (index == 0) { - _foundKeyMessage = subkey; - return B_OK; - } - - index--; - } - } - } - - return B_ENTRY_NOT_FOUND; -} - - -status_t -KeyStoreServer::_AddKey(const BString& identifier, - const BString& secondaryIdentifier, const BMessage& keyMessage) -{ - // Check for collisions. - if (_FindKey(identifier, secondaryIdentifier, false, NULL) == B_OK) + if (_FindKeyring(name) != NULL) return B_NAME_IN_USE; - // We're fine, just add the new key. - fDatabase.AddMessage(identifier, &keyMessage); - return _WriteKeyStoreDatabase(); + Keyring* keyring = new(std::nothrow) Keyring(name, BMessage()); + if (keyring == NULL) + return B_NO_MEMORY; + + if (!fKeyrings.BinaryInsert(keyring, &Keyring::Compare)) { + delete keyring; + return B_ERROR; + } + + return B_OK; +} + + +status_t +KeyStoreServer::_RemoveKeyring(const BString& name) +{ + Keyring* keyring = _FindKeyring(name); + if (keyring == NULL) + return B_ENTRY_NOT_FOUND; + + if (keyring == fDefaultKeyring) { + // The default keyring can't be removed. + return B_NOT_ALLOWED; + } + + return fKeyrings.RemoveItem(keyring) ? B_OK : B_ERROR; } diff --git a/src/servers/keystore/KeyStoreServer.h b/src/servers/keystore/KeyStoreServer.h index 1d0c3b46d1..2272bc85b4 100644 --- a/src/servers/keystore/KeyStoreServer.h +++ b/src/servers/keystore/KeyStoreServer.h @@ -9,6 +9,12 @@ #include #include #include +#include + + +class Keyring; + +typedef BObjectList KeyringList; class KeyStoreServer : public BApplication { @@ -22,19 +28,14 @@ private: status_t _ReadKeyStoreDatabase(); status_t _WriteKeyStoreDatabase(); - status_t _FindKey(const BString& identifier, - const BString& secondaryIdentifier, - bool secondaryIdentifierOptional, - BMessage* _foundKeyMessage); - status_t _FindKey(BKeyType type, BKeyPurpose purpose, - uint32 index, - BMessage& _foundKeyMessage); + Keyring* _FindKeyring(const BString& name); - status_t _AddKey(const BString& identifier, - const BString& secondaryIdentifier, + status_t _AddKeyring(const BString& name, const BMessage& keyMessage); + status_t _RemoveKeyring(const BString& name); - BMessage fDatabase; + Keyring* fDefaultKeyring; + KeyringList fKeyrings; BFile fKeyStoreFile; }; diff --git a/src/servers/keystore/Keyring.cpp b/src/servers/keystore/Keyring.cpp new file mode 100644 index 0000000000..6e0249514d --- /dev/null +++ b/src/servers/keystore/Keyring.cpp @@ -0,0 +1,185 @@ +/* + * Copyright 2012, Michael Lotz, mmlr@mlotz.ch. All Rights Reserved. + * Distributed under the terms of the MIT License. + */ + + +#include "Keyring.h" + + +Keyring::Keyring(const char* name, const BMessage& data) + : + fName(name), + fData(data) +{ +} + + +Keyring::~Keyring() +{ +} + + +bool +Keyring::IsAccessible() +{ + return true; +} + + +status_t +Keyring::FindKey(const BString& identifier, const BString& secondaryIdentifier, + bool secondaryIdentifierOptional, BMessage* _foundKeyMessage) +{ + int32 count; + type_code type; + if (fData.GetInfo(identifier, &type, &count) != B_OK) + return B_ENTRY_NOT_FOUND; + + // We have a matching primary identifier, need to check for the secondary + // identifier. + for (int32 i = 0; i < count; i++) { + BMessage candidate; + if (fData.FindMessage(identifier, i, &candidate) != B_OK) + return B_ERROR; + + BString candidateIdentifier; + if (candidate.FindString("secondaryIdentifier", + &candidateIdentifier) != B_OK) { + candidateIdentifier = ""; + } + + if (candidateIdentifier == secondaryIdentifier) { + if (_foundKeyMessage != NULL) + *_foundKeyMessage = candidate; + return B_OK; + } + } + + // We didn't find an exact match. + if (secondaryIdentifierOptional) { + if (_foundKeyMessage == NULL) + return B_OK; + + // The secondary identifier is optional, so we just return the + // first entry. + return fData.FindMessage(identifier, 0, _foundKeyMessage); + } + + return B_ENTRY_NOT_FOUND; +} + + +status_t +Keyring::FindKey(BKeyType type, BKeyPurpose purpose, uint32 index, + BMessage& _foundKeyMessage) +{ + for (int32 keyIndex = 0;; keyIndex++) { + int32 count = 0; + char* identifier = NULL; + if (fData.GetInfo(B_MESSAGE_TYPE, keyIndex, &identifier, NULL, + &count) != B_OK) { + break; + } + + if (type == B_KEY_TYPE_ANY && purpose == B_KEY_PURPOSE_ANY) { + // No need to inspect the actual keys. + if ((int32)index >= count) { + index -= count; + continue; + } + + return fData.FindMessage(identifier, index, &_foundKeyMessage); + } + + // Go through the keys to check their type and purpose. + for (int32 subkeyIndex = 0; subkeyIndex < count; subkeyIndex++) { + BMessage subkey; + if (fData.FindMessage(identifier, subkeyIndex, &subkey) != B_OK) + return B_ERROR; + + bool match = true; + if (type != B_KEY_TYPE_ANY) { + BKeyType subkeyType; + if (subkey.FindUInt32("type", (uint32*)&subkeyType) != B_OK) + return B_ERROR; + + match = subkeyType == type; + } + + if (match && purpose != B_KEY_PURPOSE_ANY) { + BKeyPurpose subkeyPurpose; + if (subkey.FindUInt32("purpose", (uint32*)&subkeyPurpose) + != B_OK) { + return B_ERROR; + } + + match = subkeyPurpose == purpose; + } + + if (match) { + if (index == 0) { + _foundKeyMessage = subkey; + return B_OK; + } + + index--; + } + } + } + + return B_ENTRY_NOT_FOUND; +} + + +status_t +Keyring::AddKey(const BString& identifier, const BString& secondaryIdentifier, + const BMessage& keyMessage) +{ + // Check for collisions. + if (FindKey(identifier, secondaryIdentifier, false, NULL) == B_OK) + return B_NAME_IN_USE; + + // We're fine, just add the new key. + return fData.AddMessage(identifier, &keyMessage); +} + + +status_t +Keyring::RemoveKey(const BString& identifier, + const BMessage& keyMessage) +{ + int32 count; + type_code type; + if (fData.GetInfo(identifier, &type, &count) != B_OK) + return B_ENTRY_NOT_FOUND; + + for (int32 i = 0; i < count; i++) { + BMessage candidate; + if (fData.FindMessage(identifier, i, &candidate) != B_OK) + return B_ERROR; + + // We require an exact match. + if (!candidate.HasSameData(keyMessage)) + continue; + + fData.RemoveData(identifier, i); + return B_OK; + } + + return B_ENTRY_NOT_FOUND; +} + + +int +Keyring::Compare(const Keyring* one, const Keyring* two) +{ + return strcmp(one->Name(), two->Name()); +} + + +int +Keyring::Compare(const BString* name, const Keyring* keyring) +{ + return strcmp(name->String(), keyring->Name()); +} diff --git a/src/servers/keystore/Keyring.h b/src/servers/keystore/Keyring.h new file mode 100644 index 0000000000..f7634943d7 --- /dev/null +++ b/src/servers/keystore/Keyring.h @@ -0,0 +1,49 @@ +/* + * Copyright 2012, Michael Lotz, mmlr@mlotz.ch. All Rights Reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef _KEYRING_H +#define _KEYRING_H + + +#include +#include + + +class Keyring { +public: + Keyring(const char* name, + const BMessage& data); + ~Keyring(); + + const char* Name() const { return fName; } + const BMessage& Data() const { return fData; } + + bool IsAccessible(); + + status_t FindKey(const BString& identifier, + const BString& secondaryIdentifier, + bool secondaryIdentifierOptional, + BMessage* _foundKeyMessage); + status_t FindKey(BKeyType type, BKeyPurpose purpose, + uint32 index, + BMessage& _foundKeyMessage); + + status_t AddKey(const BString& identifier, + const BString& secondaryIdentifier, + const BMessage& keyMessage); + status_t RemoveKey(const BString& identifier, + const BMessage& keyMessage); + +static int Compare(const Keyring* one, + const Keyring* two); +static int Compare(const BString* name, + const Keyring* keyring); + +private: + BString fName; + BMessage fData; +}; + + +#endif // _KEYRING_H From 687164ffa9d699e920b767965c2fe4ce0bc46b09 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Wed, 4 Jan 2012 23:25:05 +0100 Subject: [PATCH 050/104] Flesh out the keystore command line tool. * Implement adding/removing passwords and keyrings. * Implement enumerating passwords and keyrings. * Implement preliminary accessibility status check for keyrings. --- src/bin/keystore.cpp | 243 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 236 insertions(+), 7 deletions(-) diff --git a/src/bin/keystore.cpp b/src/bin/keystore.cpp index 2c95f47514..a2d79b2757 100644 --- a/src/bin/keystore.cpp +++ b/src/bin/keystore.cpp @@ -13,21 +13,95 @@ int -main(int argc, char* argv[]) +add_password(const char* keyring, const char* identifier, + const char* secondaryIdentifier, const char* passwordString) +{ + BKeyStore keyStore; + BPasswordKey password(passwordString, B_KEY_PURPOSE_GENERIC, identifier, + secondaryIdentifier); + + status_t result = keyStore.AddKey(keyring, password); + if (result != B_OK) { + printf("failed to add password: %s\n", strerror(result)); + return 2; + } + + return 0; +} + + +int +remove_password(const char* keyring, const char* identifier, + const char* secondaryIdentifier) { BKeyStore keyStore; BPasswordKey password; + + status_t result = keyStore.GetKey(keyring, B_KEY_TYPE_PASSWORD, + B_KEY_PURPOSE_ANY, identifier, secondaryIdentifier, false, password); + if (result != B_OK) { + printf("failed to get password \"%s\": %s\n", identifier, + strerror(result)); + return 2; + } + + result = keyStore.RemoveKey(keyring, password); + if (result != B_OK) { + printf("failed to remove password: %s\n", strerror(result)); + return 3; + } + + return 0; +} + + +int +add_keyring(const char* keyring, const char* passwordString) +{ + BKeyStore keyStore; + BPasswordKey password(passwordString, B_KEY_PURPOSE_KEYRING, NULL); + + status_t result = keyStore.AddKeyring(keyring, password); + if (result != B_OK) { + printf("failed to add keyring: %s\n", strerror(result)); + return 2; + } + + return 0; +} + + +int +remove_keyring(const char* keyring) +{ + BKeyStore keyStore; + + status_t result = keyStore.RemoveKeyring(keyring); + if (result != B_OK) { + printf("failed to remove keyring: %s\n", strerror(result)); + return 2; + } + + return 0; +} + + +int +list_passwords(const char* keyring) +{ + BKeyStore keyStore; uint32 cookie = 0; while (true) { - printf("trying to get next password with cookie: %" B_PRIu32 "\n", - cookie); - - status_t result = keyStore.GetNextKey(B_KEY_TYPE_PASSWORD, + BPasswordKey password; + status_t result = keyStore.GetNextKey(keyring, B_KEY_TYPE_PASSWORD, B_KEY_PURPOSE_ANY, cookie, password); - if (result != B_OK) { - printf("failed with: %s\n", strerror(result)); + if (result == B_ENTRY_NOT_FOUND) break; + + if (result != B_OK) { + printf("failed to get next key with: %s\n", strerror(result)); + return 2; } password.PrintToStream(); @@ -35,3 +109,158 @@ main(int argc, char* argv[]) return 0; } + + +int +list_keyrings() +{ + BKeyStore keyStore; + uint32 cookie = 0; + + while (true) { + BString keyring; + status_t result = keyStore.GetNextKeyring(cookie, keyring); + if (result == B_ENTRY_NOT_FOUND) + break; + + if (result != B_OK) { + printf("failed to get next key with: %s\n", strerror(result)); + return 2; + } + + printf("keyring: \"%s\"\n", keyring.String()); + } + + return 0; +} + + +int +show_status(const char* keyring) +{ + BKeyStore keyStore; + printf("keyring \"%s\" is %saccessible\n", keyring, + keyStore.IsKeyringAccessible(keyring) ? "" : "not "); + return 0; +} + + +int +print_usage(const char* name) +{ + printf("usage:\n"); + printf("\t%s list passwords []\n", name); + printf("\t\tLists all accessible passwords from the specified keyring or" + " from the default keyring if none is supplied.\n"); + printf("\t%s list keyrings\n", name); + printf("\t\tLists all accessible keyrings.\n\n"); + + printf("\t%s add password [] " + "\n", name); + printf("\t\tAdds the specified password to the default keyring.\n"); + printf("\t%s add password to []" + " \n", name); + printf("\t\tAdds the specified password to the specified keyring.\n\n"); + + printf("\t%s remove password []\n", name); + printf("\t\tRemoves the specified password from the default keyring.\n"); + printf("\t%s remove password from " + " []\n", name); + printf("\t\tRemoves the specified password from the specified keyring.\n\n"); + + printf("\t%s add keyring \n", name); + printf("\t\tAdds a new keyring with the specified name, protected by the" + " supplied password.\n\n"); + + printf("\t%s remove keyring \n", name); + printf("\t\tRemoves the specified keyring.\n\n"); + + printf("\t%s status \n", name); + printf("\t\tShows the access status of the specified keyring.\n\n"); + + return 1; +} + + +int +main(int argc, char* argv[]) +{ + if (argc < 3) + return print_usage(argv[0]); + + if (strcmp(argv[1], "list") == 0) { + if (strcmp(argv[2], "passwords") == 0) + return list_passwords(argc > 3 ? argv[3] : NULL); + if (strcmp(argv[2], "keyrings") == 0) + return list_keyrings(); + } else if (strcmp(argv[1], "add") == 0) { + if (strcmp(argv[2], "password") == 0) { + if (argc < 5) + return print_usage(argv[0]); + + const char* keyring = NULL; + const char* identifier = NULL; + const char* secondaryIdentifier = NULL; + const char* password = NULL; + if (argc >= 7 && argc <= 8 && strcmp(argv[3], "to") == 0) { + keyring = argv[4]; + identifier = argv[5]; + if (argc == 7) + password = argv[6]; + else { + secondaryIdentifier = argv[6]; + password = argv[7]; + } + } else if (argc <= 6) { + identifier = argv[3]; + if (argc == 5) + password = argv[4]; + else { + secondaryIdentifier = argv[4]; + password = argv[5]; + } + } + + if (password != NULL) { + return add_password(keyring, identifier, secondaryIdentifier, + password); + } + } else if (strcmp(argv[2], "keyring") == 0) { + if (argc < 5) + return print_usage(argv[0]); + + return add_keyring(argv[3], argv[4]); + } + } else if (strcmp(argv[1], "remove") == 0) { + if (strcmp(argv[2], "password") == 0) { + if (argc < 4) + return print_usage(argv[0]); + + const char* keyring = NULL; + const char* identifier = NULL; + const char* secondaryIdentifier = NULL; + if (argc >= 6 && argc <= 7 && strcmp(argv[3], "from") == 0) { + keyring = argv[4]; + identifier = argv[5]; + if (argc == 7) + secondaryIdentifier = argv[6]; + } else if (argc <= 5) { + identifier = argv[3]; + if (argc == 5) + secondaryIdentifier = argv[4]; + } + + if (identifier != NULL) { + return remove_password(keyring, identifier, + secondaryIdentifier); + } + } else if (strcmp(argv[2], "keyring") == 0) { + if (argc == 4) + return remove_keyring(argv[3]); + } + } else if (strcmp(argv[1], "status") == 0) { + return show_status(argv[2]); + } + + return print_usage(argv[0]); +} From f3f13a2fc9710f1237d145a5263d428b903840f9 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Wed, 4 Jan 2012 23:44:41 +0100 Subject: [PATCH 051/104] Make the keystore_server a background app. --- src/servers/keystore/keystore_server.rdef | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/servers/keystore/keystore_server.rdef b/src/servers/keystore/keystore_server.rdef index fb48e7ab37..b92601b5c5 100644 --- a/src/servers/keystore/keystore_server.rdef +++ b/src/servers/keystore/keystore_server.rdef @@ -1,6 +1,6 @@ resource app_signature "application/x-vnd.Haiku-keystore_server"; -resource app_flags B_EXCLUSIVE_LAUNCH; +resource app_flags B_EXCLUSIVE_LAUNCH | B_BACKGROUND_APP; resource app_version { major = 1, From 5d4a0da4557c1bbd3d8463201bc3f6ab93b06ae6 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Fri, 6 Jan 2012 11:10:51 +0100 Subject: [PATCH 052/104] Remove unneeded master access revoke command. Revoking master access currently simply means to revoke access to the default keyring. --- headers/private/app/KeyStoreDefs.h | 1 - src/kits/app/KeyStore.cpp | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/headers/private/app/KeyStoreDefs.h b/headers/private/app/KeyStoreDefs.h index d1198a6d3a..315944c18c 100644 --- a/headers/private/app/KeyStoreDefs.h +++ b/headers/private/app/KeyStoreDefs.h @@ -37,7 +37,6 @@ enum { KEY_STORE_GET_NEXT_MASTER_KEYRING = 'KnrM', KEY_STORE_IS_KEYRING_ACCESSIBLE = 'KiaR', KEY_STORE_REVOKE_ACCESS = 'KvaR', - KEY_STORE_REVOKE_MASTER_ACCESS = 'KvaM', KEY_STORE_GET_NEXT_APPLICATION = 'KnKA', KEY_STORE_REMOVE_APPLICATION = 'KrKA', }; diff --git a/src/kits/app/KeyStore.cpp b/src/kits/app/KeyStore.cpp index 91d9fc8be8..04309bb317 100644 --- a/src/kits/app/KeyStore.cpp +++ b/src/kits/app/KeyStore.cpp @@ -328,8 +328,7 @@ BKeyStore::RevokeAccess(const char* keyring) status_t BKeyStore::RevokeMasterAccess() { - BMessage message(KEY_STORE_REVOKE_MASTER_ACCESS); - return _SendKeyMessage(message, NULL); + return RevokeAccess(NULL); } From ac9b28f058fe4671b5034f6a3ed3f85091f53c5f Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Fri, 6 Jan 2012 11:13:58 +0100 Subject: [PATCH 053/104] Implement basic keyring access logic and key request dialog. * The keyring needs to be made accessible before allowing any operation. * Before executing commands the keyring is made accessible if possible (the command is aborted as needed). * Accessing a keyring opens up a preliminary key request dialog. * If the default keyring is accessible and a keyring key for the requested keyring is found, that key will be used to automatically make the requested keyring accessible. --- src/servers/keystore/Jamfile | 1 + src/servers/keystore/KeyRequestWindow.cpp | 212 ++++++++++++++++++++++ src/servers/keystore/KeyRequestWindow.h | 34 ++++ src/servers/keystore/KeyStoreServer.cpp | 62 +++++++ src/servers/keystore/KeyStoreServer.h | 4 + src/servers/keystore/Keyring.cpp | 32 +++- src/servers/keystore/Keyring.h | 3 + 7 files changed, 346 insertions(+), 2 deletions(-) create mode 100644 src/servers/keystore/KeyRequestWindow.cpp create mode 100644 src/servers/keystore/KeyRequestWindow.h diff --git a/src/servers/keystore/Jamfile b/src/servers/keystore/Jamfile index ed51642e49..e0ccaffba9 100644 --- a/src/servers/keystore/Jamfile +++ b/src/servers/keystore/Jamfile @@ -3,6 +3,7 @@ SubDir HAIKU_TOP src servers keystore ; UsePrivateHeaders app ; Server keystore_server : + KeyRequestWindow.cpp Keyring.cpp KeyStoreServer.cpp diff --git a/src/servers/keystore/KeyRequestWindow.cpp b/src/servers/keystore/KeyRequestWindow.cpp new file mode 100644 index 0000000000..22355609d9 --- /dev/null +++ b/src/servers/keystore/KeyRequestWindow.cpp @@ -0,0 +1,212 @@ +/* + * 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 + + +static const uint32 kMessageCancel = 'btcl'; +static const uint32 kMessageOk = 'btok'; + + +class KeyRequestView : public BView { +public: + KeyRequestView() + : + BView("KeyRequestView", B_WILL_DRAW), + fPassword(NULL) + { + SetViewColor(ui_color(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); + + fKeyringName = new(std::nothrow) BTextControl("Keyring:", "", NULL); + if (fKeyringName == NULL) + return; + + int32 row = 0; + layout->AddItem(fKeyringName->CreateLabelLayoutItem(), 0, row); + layout->AddItem(fKeyringName->CreateTextViewLayoutItem(), 1, row++); + + fPassword = new(std::nothrow) BTextControl("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++); + + fPersist = new(std::nothrow) BCheckBox("Not yet"); + layout->AddItem(BSpaceLayoutItem::CreateGlue(), 0, row); + layout->AddView(fPersist, 1, row++); + + BGroupView* buttons = new(std::nothrow) BGroupView(B_HORIZONTAL); + if (buttons == NULL) + return; + + fCancelButton = new(std::nothrow) BButton("Cancel", + new BMessage(kMessageCancel)); + buttons->GroupLayout()->AddView(fCancelButton); + + buttons->GroupLayout()->AddItem(BSpaceLayoutItem::CreateGlue()); + + fOkButton = new(std::nothrow) BButton("OK", new BMessage(kMessageOk)); + buttons->GroupLayout()->AddView(fOkButton); + + rootLayout->AddView(controls); + rootLayout->AddView(buttons); + } + + virtual void + AttachedToWindow() + { + fCancelButton->SetTarget(Window()); + fOkButton->SetTarget(Window()); + fOkButton->MakeDefault(true); + } + + void + SetUp(const BMessage& keyMessage) + { + BString keyringName; + if (keyMessage.FindString("keyring", &keyringName) == B_OK) + fKeyringName->SetText(keyringName); + } + + void + Complete(BMessage& keyMessage) + { + keyMessage.RemoveName("password"); + keyMessage.AddString("password", fPassword->Text()); + + keyMessage.RemoveName("persistent"); + keyMessage.AddBool("persistent", fPersist->Value() != 0); + } + +private: + BTextControl* fKeyringName; + BTextControl* fPassword; + BCheckBox* fPersist; + BButton* fCancelButton; + BButton* fOkButton; +}; + + +KeyRequestWindow::KeyRequestWindow() + : + BWindow(BRect(50, 50, 269, 302), "Access Keyring", + B_TITLED_WINDOW, B_NOT_RESIZABLE | B_ASYNCHRONOUS_CONTROLS + | B_NOT_ZOOMABLE | B_AUTO_UPDATE_SIZE_LIMITS), + fRequestView(NULL), + fDoneSem(-1), + fResult(B_ERROR) +{ + fDoneSem = create_sem(0, "keyring access 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); +} + + +void +KeyRequestWindow::DispatchMessage(BMessage* message, BHandler* handler) +{ + int8 key; + if (message->what == B_KEY_DOWN + && message->FindInt8("byte", 0, &key) == B_OK + && key == B_ESCAPE) { + PostMessage(kMessageCancel); + } + + BWindow::DispatchMessage(message, handler); +} + + +void +KeyRequestWindow::MessageReceived(BMessage* message) +{ + switch (message->what) { + case kMessageCancel: + case kMessageOk: + fResult = message->what == kMessageOk ? B_OK : B_CANCELED; + release_sem(fDoneSem); + return; + } + + BWindow::MessageReceived(message); +} + + +status_t +KeyRequestWindow::RequestKey(BMessage& keyMessage) +{ + fRequestView->SetUp(keyMessage); + + CenterOnScreen(); + Show(); + + while (acquire_sem(fDoneSem) == B_INTERRUPTED) + ; + + status_t result = fResult; + fRequestView->Complete(keyMessage); + + LockLooper(); + Quit(); + return result; +} diff --git a/src/servers/keystore/KeyRequestWindow.h b/src/servers/keystore/KeyRequestWindow.h new file mode 100644 index 0000000000..c5f89c79c1 --- /dev/null +++ b/src/servers/keystore/KeyRequestWindow.h @@ -0,0 +1,34 @@ +/* + * Copyright 2012, Michael Lotz, mmlr@mlotz.ch. All Rights Reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef _KEY_REQUEST_WINDOW_H +#define _KEY_REQUEST_WINDOW_H + + +#include +#include + + +class KeyRequestView; + + +class KeyRequestWindow : public BWindow { +public: + KeyRequestWindow(); +virtual ~KeyRequestWindow(); + +virtual void DispatchMessage(BMessage* message, + BHandler* handler); +virtual void MessageReceived(BMessage* message); + + status_t RequestKey(BMessage& keyMessage); + +private: + KeyRequestView* fRequestView; + sem_id fDoneSem; + status_t fResult; +}; + + +#endif // _KEY_REQUEST_WINDOW_H diff --git a/src/servers/keystore/KeyStoreServer.cpp b/src/servers/keystore/KeyStoreServer.cpp index caca6a7255..f007cc0e4f 100644 --- a/src/servers/keystore/KeyStoreServer.cpp +++ b/src/servers/keystore/KeyStoreServer.cpp @@ -5,6 +5,8 @@ #include "KeyStoreServer.h" + +#include "KeyRequestWindow.h" #include "Keyring.h" #include @@ -89,6 +91,24 @@ KeyStoreServer::MessageReceived(BMessage* message) break; } + switch (message->what) { + case KEY_STORE_GET_KEY: + case KEY_STORE_GET_NEXT_KEY: + case KEY_STORE_ADD_KEY: + case KEY_STORE_REMOVE_KEY: + { + // These need keyring access to do anything. + while (!keyring->IsAccessible()) { + status_t accessResult = _AccessKeyring(*keyring); + if (accessResult != B_OK) { + result = accessResult; + message->what = 0; + break; + } + } + } + } + break; } } @@ -247,6 +267,12 @@ KeyStoreServer::MessageReceived(BMessage* message) result = B_OK; } + case KEY_STORE_REVOKE_ACCESS: + { + keyring->RevokeAccess(); + result = B_OK; + } + case 0: { // Just the error case from above. @@ -380,6 +406,42 @@ KeyStoreServer::_RemoveKeyring(const BString& name) } +status_t +KeyStoreServer::_AccessKeyring(Keyring& keyring) +{ + // If we are accessing a keyring that has been added to master access we + // get the key from the default keyring and unlock with that. + BMessage keyMessage; + if (&keyring != fDefaultKeyring && fDefaultKeyring->IsAccessible()) { + if (fDefaultKeyring->FindKey("Keyrings", keyring.Name(), false, + &keyMessage) == B_OK) { + // We found a key for this keyring, try to access with it. + if (keyring.Access(keyMessage) == B_OK) + return B_OK; + } + } + + // No key, we need to request one from the user. + keyMessage.AddString("keyring", keyring.Name()); + status_t result = _RequestKey(keyMessage); + if (result != B_OK) + return result; + + return keyring.Access(keyMessage); +} + + +status_t +KeyStoreServer::_RequestKey(BMessage& keyMessage) +{ + KeyRequestWindow* requestWindow = new(std::nothrow) KeyRequestWindow(); + if (requestWindow == NULL) + return B_NO_MEMORY; + + return requestWindow->RequestKey(keyMessage); +} + + int main(int argc, char* argv[]) { diff --git a/src/servers/keystore/KeyStoreServer.h b/src/servers/keystore/KeyStoreServer.h index 2272bc85b4..b0bff8a8dd 100644 --- a/src/servers/keystore/KeyStoreServer.h +++ b/src/servers/keystore/KeyStoreServer.h @@ -34,6 +34,10 @@ private: const BMessage& keyMessage); status_t _RemoveKeyring(const BString& name); + status_t _AccessKeyring(Keyring& keyring); + + status_t _RequestKey(BMessage& keyMessage); + Keyring* fDefaultKeyring; KeyringList fKeyrings; BFile fKeyStoreFile; diff --git a/src/servers/keystore/Keyring.cpp b/src/servers/keystore/Keyring.cpp index 6e0249514d..e337f41b48 100644 --- a/src/servers/keystore/Keyring.cpp +++ b/src/servers/keystore/Keyring.cpp @@ -10,7 +10,8 @@ Keyring::Keyring(const char* name, const BMessage& data) : fName(name), - fData(data) + fData(data), + fAccessible(false) { } @@ -20,10 +21,25 @@ Keyring::~Keyring() } +status_t +Keyring::Access(const BMessage& keyMessage) +{ + fAccessible = true; + return B_OK; +} + + +void +Keyring::RevokeAccess() +{ + fAccessible = false; +} + + bool Keyring::IsAccessible() { - return true; + return fAccessible; } @@ -31,6 +47,9 @@ status_t Keyring::FindKey(const BString& identifier, const BString& secondaryIdentifier, bool secondaryIdentifierOptional, BMessage* _foundKeyMessage) { + if (!fAccessible) + return B_NOT_ALLOWED; + int32 count; type_code type; if (fData.GetInfo(identifier, &type, &count) != B_OK) @@ -74,6 +93,9 @@ status_t Keyring::FindKey(BKeyType type, BKeyPurpose purpose, uint32 index, BMessage& _foundKeyMessage) { + if (!fAccessible) + return B_NOT_ALLOWED; + for (int32 keyIndex = 0;; keyIndex++) { int32 count = 0; char* identifier = NULL; @@ -136,6 +158,9 @@ status_t Keyring::AddKey(const BString& identifier, const BString& secondaryIdentifier, const BMessage& keyMessage) { + if (!fAccessible) + return B_NOT_ALLOWED; + // Check for collisions. if (FindKey(identifier, secondaryIdentifier, false, NULL) == B_OK) return B_NAME_IN_USE; @@ -149,6 +174,9 @@ status_t Keyring::RemoveKey(const BString& identifier, const BMessage& keyMessage) { + if (!fAccessible) + return B_NOT_ALLOWED; + int32 count; type_code type; if (fData.GetInfo(identifier, &type, &count) != B_OK) diff --git a/src/servers/keystore/Keyring.h b/src/servers/keystore/Keyring.h index f7634943d7..eb3ad609a9 100644 --- a/src/servers/keystore/Keyring.h +++ b/src/servers/keystore/Keyring.h @@ -19,6 +19,8 @@ public: const char* Name() const { return fName; } const BMessage& Data() const { return fData; } + status_t Access(const BMessage& keyMessage); + void RevokeAccess(); bool IsAccessible(); status_t FindKey(const BString& identifier, @@ -43,6 +45,7 @@ static int Compare(const BString* name, private: BString fName; BMessage fData; + bool fAccessible; }; From f17ed511654fceaefd90bd56e57f306cd70fb449 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Fri, 6 Jan 2012 11:22:55 +0100 Subject: [PATCH 054/104] Add access revokation to the keystore command line util. --- src/bin/keystore.cpp | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/src/bin/keystore.cpp b/src/bin/keystore.cpp index a2d79b2757..204c184083 100644 --- a/src/bin/keystore.cpp +++ b/src/bin/keystore.cpp @@ -145,6 +145,21 @@ show_status(const char* keyring) } +int +revoke_access(const char* keyring) +{ + BKeyStore keyStore; + status_t result = keyStore.RevokeAccess(keyring); + if (result != B_OK) { + printf("failed to revoke access to keyring \"%s\": %s\n", keyring, + strerror(result)); + return 2; + } + + return 0; +} + + int print_usage(const char* name) { @@ -185,15 +200,21 @@ print_usage(const char* name) int main(int argc, char* argv[]) { - if (argc < 3) + if (argc < 2) return print_usage(argv[0]); if (strcmp(argv[1], "list") == 0) { + if (argc < 3) + return print_usage(argv[0]); + if (strcmp(argv[2], "passwords") == 0) return list_passwords(argc > 3 ? argv[3] : NULL); if (strcmp(argv[2], "keyrings") == 0) return list_keyrings(); } else if (strcmp(argv[1], "add") == 0) { + if (argc < 3) + return print_usage(argv[0]); + if (strcmp(argv[2], "password") == 0) { if (argc < 5) return print_usage(argv[0]); @@ -232,6 +253,9 @@ main(int argc, char* argv[]) return add_keyring(argv[3], argv[4]); } } else if (strcmp(argv[1], "remove") == 0) { + if (argc < 3) + return print_usage(argv[0]); + if (strcmp(argv[2], "password") == 0) { if (argc < 4) return print_usage(argv[0]); @@ -259,7 +283,15 @@ main(int argc, char* argv[]) return remove_keyring(argv[3]); } } else if (strcmp(argv[1], "status") == 0) { - return show_status(argv[2]); + if (argc != 2 && argc != 3) + return print_usage(argv[0]); + + return show_status(argc == 3 ? argv[2] : ""); + } else if (strcmp(argv[1], "revoke") == 0) { + if (argc != 2 && argc != 3) + return print_usage(argv[0]); + + return revoke_access(argc == 3 ? argv[2] : ""); } return print_usage(argv[0]); From 40516a14f97e27e8eae107ae7106b13cbbcc6114 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Fri, 6 Jan 2012 11:23:18 +0100 Subject: [PATCH 055/104] Add the keystore_server and the keystore command to the image. --- build/jam/HaikuImage | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/jam/HaikuImage b/build/jam/HaikuImage index fade9a3075..6dbb81f3d2 100644 --- a/build/jam/HaikuImage +++ b/build/jam/HaikuImage @@ -18,7 +18,7 @@ SYSTEM_BIN = [ FFilterByBuildFeatures hd head hey hostname id ident ifconfig install installsound iroster isvolume ideinfo@ide idestatus@ide - join kernel_debugger keymap kill + join kernel_debugger keymap keystore kill less lessecho lesskey link linkcatkeys listarea listattr listimage listdev listport listres listsem listusb ln locale locate logger login logname ls lsindex @@ -84,7 +84,7 @@ PRIVATE_SYSTEM_LIBS = [ FFilterByBuildFeatures libilmimf.so ] ; SYSTEM_SERVERS = [ FFilterByBuildFeatures - app_server cddb_daemon debug_server input_server mail_daemon + app_server cddb_daemon debug_server input_server keystore_server mail_daemon media_addon_server media_server midi_server mount_server net_server notification_server power_daemon print_server print_addon_server registrar syslog_daemon From 6fb7a4569b10af8e7f333bc63c174317208f9a14 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sun, 8 Jan 2012 01:15:03 +0100 Subject: [PATCH 056/104] Add commands for adding/removig keyrings from/to the master. Also adds missing revoke usage string. --- src/bin/keystore.cpp | 55 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 53 insertions(+), 2 deletions(-) diff --git a/src/bin/keystore.cpp b/src/bin/keystore.cpp index 204c184083..8d6cf028c7 100644 --- a/src/bin/keystore.cpp +++ b/src/bin/keystore.cpp @@ -160,6 +160,36 @@ revoke_access(const char* keyring) } +int +add_keyring_to_master(const char* keyring) +{ + BKeyStore keyStore; + status_t result= keyStore.AddKeyringToMaster(keyring); + if (result != B_OK) { + printf("failed to add keyring \"%s\" to master: %s\n", keyring, + strerror(result)); + return 2; + } + + return 0; +} + + +int +remove_keyring_from_master(const char* keyring) +{ + BKeyStore keyStore; + status_t result= keyStore.RemoveKeyringFromMaster(keyring); + if (result != B_OK) { + printf("failed to remove keyring \"%s\" from master: %s\n", keyring, + strerror(result)); + return 2; + } + + return 0; +} + + int print_usage(const char* name) { @@ -190,8 +220,21 @@ print_usage(const char* name) printf("\t%s remove keyring \n", name); printf("\t\tRemoves the specified keyring.\n\n"); - printf("\t%s status \n", name); - printf("\t\tShows the access status of the specified keyring.\n\n"); + printf("\t%s status []\n", name); + printf("\t\tShows the access status of the specified keyring, or the" + " default keyring if none is supplied.\n\n"); + + printf("\t%s revoke []\n", name); + printf("\t\tRevoke access to the specified keyring, or to the default" + " keyring if none is supplied.\n\n"); + + printf("\t%s master add \n", name); + printf("\t\tAdd the access key for the specified keyring to the default" + " keyring.\n"); + + printf("\t%s master remove \n", name); + printf("\t\tRemove the access key for the specified keyring from the" + " default keyring.\n"); return 1; } @@ -292,6 +335,14 @@ main(int argc, char* argv[]) return print_usage(argv[0]); return revoke_access(argc == 3 ? argv[2] : ""); + } else if (strcmp(argv[1], "master") == 0) { + if (argc != 4) + return print_usage(argv[0]); + + if (strcmp(argv[2], "add") == 0) + return add_keyring_to_master(argv[3]); + if (strcmp(argv[2], "remove") == 0) + return remove_keyring_from_master(argv[3]); } return print_usage(argv[0]); From 94f897deeaa6eda4b7982a958287c5c8fa2ce435 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sun, 8 Jan 2012 01:17:02 +0100 Subject: [PATCH 057/104] Make Flatten/Unflatten public and remove IsRegistered(). The BKey doesn't know anything about the keyring concept, so the registered info isn't really useful. May be re-added later with keyring info as well. --- headers/os/app/Key.h | 9 ++-- src/kits/app/Key.cpp | 97 +++++++++++++++++++-------------------- src/kits/app/KeyStore.cpp | 16 +++---- 3 files changed, 59 insertions(+), 63 deletions(-) diff --git a/headers/os/app/Key.h b/headers/os/app/Key.h index 0f4110e2c5..35f166ec14 100644 --- a/headers/os/app/Key.h +++ b/headers/os/app/Key.h @@ -67,7 +67,9 @@ public: const char* Owner() const; bigtime_t CreationTime() const; - bool IsRegistered() const; + + virtual status_t Flatten(BMessage& message) const; + virtual status_t Unflatten(const BMessage& message); BKey& operator=(const BKey& other); @@ -76,10 +78,6 @@ public: virtual void PrintToStream(); -protected: - virtual status_t _Flatten(BMessage& message) const; - virtual status_t _Unflatten(const BMessage& message); - private: friend class BKeyStore; @@ -89,7 +87,6 @@ private: BString fOwner; bigtime_t fCreationTime; mutable BMallocIO fData; - bool fRegistered; }; diff --git a/src/kits/app/Key.cpp b/src/kits/app/Key.cpp index 3d0df5ffb0..a9d8d16e9e 100644 --- a/src/kits/app/Key.cpp +++ b/src/kits/app/Key.cpp @@ -52,6 +52,13 @@ BKey::~BKey() } +void +BKey::Unset() +{ + SetTo(B_KEY_PURPOSE_GENERIC, "", "", NULL, 0); +} + + status_t BKey::SetTo(BKeyPurpose purpose, const char* identifier, const char* secondaryIdentifier, const uint8* data, size_t length) @@ -157,10 +164,47 @@ BKey::CreationTime() const } -bool -BKey::IsRegistered() const +status_t +BKey::Flatten(BMessage& message) const { - return fRegistered; + if (message.MakeEmpty() != B_OK + || message.AddUInt32("type", Type()) != B_OK + || message.AddUInt32("purpose", fPurpose) != B_OK + || message.AddString("identifier", fIdentifier) != B_OK + || message.AddString("secondaryIdentifier", fSecondaryIdentifier) + != B_OK + || message.AddString("owner", fOwner) != B_OK + || message.AddInt64("creationTime", fCreationTime) != B_OK + || message.AddData("data", B_RAW_TYPE, fData.Buffer(), + fData.BufferLength()) != B_OK) { + return B_ERROR; + } + + return B_OK; +} + + +status_t +BKey::Unflatten(const BMessage& message) +{ + BKeyType type; + if (message.FindUInt32("type", (uint32*)&type) != B_OK || type != Type()) + return B_BAD_VALUE; + + const void* data = NULL; + ssize_t dataLength = 0; + if (message.FindUInt32("purpose", (uint32*)&fPurpose) != B_OK + || message.FindString("identifier", &fIdentifier) != B_OK + || message.FindString("secondaryIdentifier", &fSecondaryIdentifier) + != B_OK + || message.FindString("owner", &fOwner) != B_OK + || message.FindInt64("creationTime", &fCreationTime) != B_OK + || message.FindData("data", B_RAW_TYPE, &data, &dataLength) != B_OK + || dataLength < 0) { + return B_ERROR; + } + + return SetData((const uint8*)data, (size_t)dataLength); } @@ -173,8 +217,7 @@ BKey::operator=(const BKey& other) fIdentifier = other.fIdentifier; fSecondaryIdentifier = other.fSecondaryIdentifier; fOwner = other.fOwner; - fCreationTime = other.CreationTime(); - fRegistered = other.IsRegistered(); + fCreationTime = other.fCreationTime; return *this; } @@ -237,50 +280,6 @@ BKey::PrintToStream() } -status_t -BKey::_Flatten(BMessage& message) const -{ - if (message.MakeEmpty() != B_OK - || message.AddUInt32("type", Type()) != B_OK - || message.AddUInt32("purpose", fPurpose) != B_OK - || message.AddString("identifier", fIdentifier) != B_OK - || message.AddString("secondaryIdentifier", fSecondaryIdentifier) - != B_OK - || message.AddString("owner", fOwner) != B_OK - || message.AddInt64("creationTime", fCreationTime) != B_OK - || message.AddData("data", B_RAW_TYPE, fData.Buffer(), - fData.BufferLength()) != B_OK) { - return B_ERROR; - } - - return B_OK; -} - - -status_t -BKey::_Unflatten(const BMessage& message) -{ - BKeyType type; - if (message.FindUInt32("type", (uint32*)&type) != B_OK || type != Type()) - return B_BAD_VALUE; - - const void* data = NULL; - ssize_t dataLength = 0; - if (message.FindUInt32("purpose", (uint32*)&fPurpose) != B_OK - || message.FindString("identifier", &fIdentifier) != B_OK - || message.FindString("secondaryIdentifier", &fSecondaryIdentifier) - != B_OK - || message.FindString("owner", &fOwner) != B_OK - || message.FindInt64("creationTime", &fCreationTime) != B_OK - || message.FindData("data", B_RAW_TYPE, &data, &dataLength) != B_OK - || dataLength < 0) { - return B_ERROR; - } - - return SetData((const uint8*)data, (size_t)dataLength); -} - - // #pragma mark - BPasswordKey diff --git a/src/kits/app/KeyStore.cpp b/src/kits/app/KeyStore.cpp index 04309bb317..dea28718a1 100644 --- a/src/kits/app/KeyStore.cpp +++ b/src/kits/app/KeyStore.cpp @@ -93,7 +93,7 @@ BKeyStore::GetKey(const char* keyring, BKeyType type, BKeyPurpose purpose, if (reply.FindMessage("key", &keyMessage) != B_OK) return B_ERROR; - return key._Unflatten(keyMessage); + return key.Unflatten(keyMessage); } @@ -108,7 +108,7 @@ status_t BKeyStore::AddKey(const char* keyring, const BKey& key) { BMessage keyMessage; - if (key._Flatten(keyMessage) != B_OK) + if (key.Flatten(keyMessage) != B_OK) return B_BAD_VALUE; BMessage message(KEY_STORE_ADD_KEY); @@ -130,7 +130,7 @@ status_t BKeyStore::RemoveKey(const char* keyring, const BKey& key) { BMessage keyMessage; - if (key._Flatten(keyMessage) != B_OK) + if (key.Flatten(keyMessage) != B_OK) return B_BAD_VALUE; BMessage message(KEY_STORE_REMOVE_KEY); @@ -183,7 +183,7 @@ BKeyStore::GetNextKey(const char* keyring, BKeyType type, BKeyPurpose purpose, return B_ERROR; reply.FindUInt32("cookie", &cookie); - return key._Unflatten(keyMessage); + return key.Unflatten(keyMessage); } @@ -194,7 +194,7 @@ status_t BKeyStore::AddKeyring(const char* keyring, const BKey& key) { BMessage keyMessage; - if (key._Flatten(keyMessage) != B_OK) + if (key.Flatten(keyMessage) != B_OK) return B_BAD_VALUE; BMessage message(KEY_STORE_ADD_KEYRING); @@ -240,7 +240,7 @@ status_t BKeyStore::SetMasterKey(const BKey& key) { BMessage keyMessage; - if (key._Flatten(keyMessage) != B_OK) + if (key.Flatten(keyMessage) != B_OK) return B_BAD_VALUE; BMessage message(KEY_STORE_SET_MASTER_KEY); @@ -341,7 +341,7 @@ BKeyStore::GetNextApplication(const BKey& key, uint32& cookie, BString& signature) const { BMessage keyMessage; - if (key._Flatten(keyMessage) != B_OK) + if (key.Flatten(keyMessage) != B_OK) return B_BAD_VALUE; BMessage message(KEY_STORE_GET_NEXT_APPLICATION); @@ -365,7 +365,7 @@ status_t BKeyStore::RemoveApplication(const BKey& key, const char* signature) { BMessage keyMessage; - if (key._Flatten(keyMessage) != B_OK) + if (key.Flatten(keyMessage) != B_OK) return B_BAD_VALUE; BMessage message(KEY_STORE_REMOVE_APPLICATION); From 1dd765c92c41aeebcc877371e90a795ed4a78703 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sun, 8 Jan 2012 01:32:11 +0100 Subject: [PATCH 058/104] Store the key message from access/creation. * Allow creating a Keyring with a key message. * Store the key message when accessing. * Add a few missing consts. --- src/servers/keystore/KeyStoreServer.cpp | 2 +- src/servers/keystore/Keyring.cpp | 21 ++++++++++++++++----- src/servers/keystore/Keyring.h | 11 +++++++---- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/servers/keystore/KeyStoreServer.cpp b/src/servers/keystore/KeyStoreServer.cpp index f007cc0e4f..c84a8074fc 100644 --- a/src/servers/keystore/KeyStoreServer.cpp +++ b/src/servers/keystore/KeyStoreServer.cpp @@ -377,7 +377,7 @@ KeyStoreServer::_AddKeyring(const BString& name, const BMessage& keyMessage) if (_FindKeyring(name) != NULL) return B_NAME_IN_USE; - Keyring* keyring = new(std::nothrow) Keyring(name, BMessage()); + Keyring* keyring = new(std::nothrow) Keyring(name, BMessage(), &keyMessage); if (keyring == NULL) return B_NO_MEMORY; diff --git a/src/servers/keystore/Keyring.cpp b/src/servers/keystore/Keyring.cpp index e337f41b48..fc77baf9ea 100644 --- a/src/servers/keystore/Keyring.cpp +++ b/src/servers/keystore/Keyring.cpp @@ -7,11 +7,13 @@ #include "Keyring.h" -Keyring::Keyring(const char* name, const BMessage& data) +Keyring::Keyring(const char* name, const BMessage& data, + const BMessage* keyMessage) : fName(name), fData(data), - fAccessible(false) + fKeyMessage(*keyMessage), + fAccessible(keyMessage != NULL) { } @@ -24,6 +26,7 @@ Keyring::~Keyring() status_t Keyring::Access(const BMessage& keyMessage) { + fKeyMessage = keyMessage; fAccessible = true; return B_OK; } @@ -32,20 +35,28 @@ Keyring::Access(const BMessage& keyMessage) void Keyring::RevokeAccess() { + fKeyMessage.MakeEmpty(); fAccessible = false; } bool -Keyring::IsAccessible() +Keyring::IsAccessible() const { return fAccessible; } +const BMessage& +Keyring::KeyMessage() const +{ + return fKeyMessage; +} + + status_t Keyring::FindKey(const BString& identifier, const BString& secondaryIdentifier, - bool secondaryIdentifierOptional, BMessage* _foundKeyMessage) + bool secondaryIdentifierOptional, BMessage* _foundKeyMessage) const { if (!fAccessible) return B_NOT_ALLOWED; @@ -91,7 +102,7 @@ Keyring::FindKey(const BString& identifier, const BString& secondaryIdentifier, status_t Keyring::FindKey(BKeyType type, BKeyPurpose purpose, uint32 index, - BMessage& _foundKeyMessage) + BMessage& _foundKeyMessage) const { if (!fAccessible) return B_NOT_ALLOWED; diff --git a/src/servers/keystore/Keyring.h b/src/servers/keystore/Keyring.h index eb3ad609a9..bdd426db1a 100644 --- a/src/servers/keystore/Keyring.h +++ b/src/servers/keystore/Keyring.h @@ -13,7 +13,8 @@ class Keyring { public: Keyring(const char* name, - const BMessage& data); + const BMessage& data, + const BMessage* keyMessage = NULL); ~Keyring(); const char* Name() const { return fName; } @@ -21,15 +22,16 @@ public: status_t Access(const BMessage& keyMessage); void RevokeAccess(); - bool IsAccessible(); + bool IsAccessible() const; + const BMessage& KeyMessage() const; status_t FindKey(const BString& identifier, const BString& secondaryIdentifier, bool secondaryIdentifierOptional, - BMessage* _foundKeyMessage); + BMessage* _foundKeyMessage) const; status_t FindKey(BKeyType type, BKeyPurpose purpose, uint32 index, - BMessage& _foundKeyMessage); + BMessage& _foundKeyMessage) const; status_t AddKey(const BString& identifier, const BString& secondaryIdentifier, @@ -45,6 +47,7 @@ static int Compare(const BString* name, private: BString fName; BMessage fData; + BMessage fKeyMessage; bool fAccessible; }; From f16fef70bee3877ed2b72e9b5714bc6b4f93b4bd Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sun, 8 Jan 2012 01:33:34 +0100 Subject: [PATCH 059/104] Implement adding/removing keyrings from/to master. --- src/servers/keystore/KeyStoreServer.cpp | 54 ++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/src/servers/keystore/KeyStoreServer.cpp b/src/servers/keystore/KeyStoreServer.cpp index c84a8074fc..f2bb22e669 100644 --- a/src/servers/keystore/KeyStoreServer.cpp +++ b/src/servers/keystore/KeyStoreServer.cpp @@ -25,6 +25,9 @@ using namespace BPrivate; +static const char* kKeyringKeysIdentifier = "Keyrings"; + + KeyStoreServer::KeyStoreServer() : BApplication(kKeyStoreServerSignature), @@ -78,6 +81,8 @@ KeyStoreServer::MessageReceived(BMessage* message) case KEY_STORE_REMOVE_KEY: case KEY_STORE_IS_KEYRING_ACCESSIBLE: case KEY_STORE_REVOKE_ACCESS: + case KEY_STORE_ADD_KEYRING_TO_MASTER: + case KEY_STORE_REMOVE_KEYRING_FROM_MASTER: { BString keyringName; if (message->FindString("keyring", &keyringName) != B_OK) @@ -96,6 +101,7 @@ KeyStoreServer::MessageReceived(BMessage* message) case KEY_STORE_GET_NEXT_KEY: case KEY_STORE_ADD_KEY: case KEY_STORE_REMOVE_KEY: + case KEY_STORE_ADD_KEYRING_TO_MASTER: { // These need keyring access to do anything. while (!keyring->IsAccessible()) { @@ -140,6 +146,7 @@ KeyStoreServer::MessageReceived(BMessage* message) secondaryIdentifierOptional, &keyMessage); if (result == B_OK) reply.AddMessage("key", &keyMessage); + break; } @@ -265,12 +272,55 @@ KeyStoreServer::MessageReceived(BMessage* message) { reply.AddBool("accessible", keyring->IsAccessible()); result = B_OK; + break; } case KEY_STORE_REVOKE_ACCESS: { keyring->RevokeAccess(); result = B_OK; + break; + } + + case KEY_STORE_ADD_KEYRING_TO_MASTER: + case KEY_STORE_REMOVE_KEYRING_FROM_MASTER: + { + // We also need access to the default keyring. + while (!fDefaultKeyring->IsAccessible()) { + status_t accessResult = _AccessKeyring(*fDefaultKeyring); + if (accessResult != B_OK) { + result = accessResult; + message->what = 0; + break; + } + } + + if (message->what == 0) + break; + + BString secondaryIdentifier = keyring->Name(); + BMessage keyMessage = keyring->KeyMessage(); + keyMessage.RemoveName("identifier"); + keyMessage.AddString("identifier", kKeyringKeysIdentifier); + keyMessage.RemoveName("secondaryIdentifier"); + keyMessage.AddString("secondaryIdentifier", secondaryIdentifier); + + switch (message->what) { + case KEY_STORE_ADD_KEYRING_TO_MASTER: + result = fDefaultKeyring->AddKey(kKeyringKeysIdentifier, + secondaryIdentifier, keyMessage); + break; + + case KEY_STORE_REMOVE_KEYRING_FROM_MASTER: + result = fDefaultKeyring->RemoveKey(kKeyringKeysIdentifier, + keyMessage); + break; + } + + if (result == B_OK) + _WriteKeyStoreDatabase(); + + break; } case 0: @@ -413,8 +463,8 @@ KeyStoreServer::_AccessKeyring(Keyring& keyring) // get the key from the default keyring and unlock with that. BMessage keyMessage; if (&keyring != fDefaultKeyring && fDefaultKeyring->IsAccessible()) { - if (fDefaultKeyring->FindKey("Keyrings", keyring.Name(), false, - &keyMessage) == B_OK) { + if (fDefaultKeyring->FindKey(kKeyringKeysIdentifier, keyring.Name(), + false, &keyMessage) == B_OK) { // We found a key for this keyring, try to access with it. if (keyring.Access(keyMessage) == B_OK) return B_OK; From 90013c82e83a7a25e5d012daff40e38db5d5f741 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sun, 8 Jan 2012 01:34:20 +0100 Subject: [PATCH 060/104] Let the KeyRequestWindow return a flattened BPasswordKey. Also provide the keyring string separately instead of abusing the output key message. --- src/servers/keystore/KeyRequestWindow.cpp | 23 ++++++++++------------- src/servers/keystore/KeyRequestWindow.h | 3 ++- src/servers/keystore/KeyStoreServer.cpp | 7 +++---- src/servers/keystore/KeyStoreServer.h | 3 ++- 4 files changed, 17 insertions(+), 19 deletions(-) diff --git a/src/servers/keystore/KeyRequestWindow.cpp b/src/servers/keystore/KeyRequestWindow.cpp index 22355609d9..f8c7ecf1c5 100644 --- a/src/servers/keystore/KeyRequestWindow.cpp +++ b/src/servers/keystore/KeyRequestWindow.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -103,21 +104,16 @@ public: } void - SetUp(const BMessage& keyMessage) + SetUp(const BString& keyringName) { - BString keyringName; - if (keyMessage.FindString("keyring", &keyringName) == B_OK) - fKeyringName->SetText(keyringName); + fKeyringName->SetText(keyringName); } - void + status_t Complete(BMessage& keyMessage) { - keyMessage.RemoveName("password"); - keyMessage.AddString("password", fPassword->Text()); - - keyMessage.RemoveName("persistent"); - keyMessage.AddBool("persistent", fPersist->Value() != 0); + BPasswordKey password(fPassword->Text(), B_KEY_PURPOSE_KEYRING, ""); + return password.Flatten(keyMessage); } private: @@ -193,9 +189,9 @@ KeyRequestWindow::MessageReceived(BMessage* message) status_t -KeyRequestWindow::RequestKey(BMessage& keyMessage) +KeyRequestWindow::RequestKey(const BString& keyringName, BMessage& keyMessage) { - fRequestView->SetUp(keyMessage); + fRequestView->SetUp(keyringName); CenterOnScreen(); Show(); @@ -204,7 +200,8 @@ KeyRequestWindow::RequestKey(BMessage& keyMessage) ; status_t result = fResult; - fRequestView->Complete(keyMessage); + if (result == B_OK) + result = fRequestView->Complete(keyMessage); LockLooper(); Quit(); diff --git a/src/servers/keystore/KeyRequestWindow.h b/src/servers/keystore/KeyRequestWindow.h index c5f89c79c1..8c535d6e78 100644 --- a/src/servers/keystore/KeyRequestWindow.h +++ b/src/servers/keystore/KeyRequestWindow.h @@ -22,7 +22,8 @@ virtual void DispatchMessage(BMessage* message, BHandler* handler); virtual void MessageReceived(BMessage* message); - status_t RequestKey(BMessage& keyMessage); + status_t RequestKey(const BString& keyringName, + BMessage& keyMessage); private: KeyRequestView* fRequestView; diff --git a/src/servers/keystore/KeyStoreServer.cpp b/src/servers/keystore/KeyStoreServer.cpp index f2bb22e669..3eda433198 100644 --- a/src/servers/keystore/KeyStoreServer.cpp +++ b/src/servers/keystore/KeyStoreServer.cpp @@ -472,8 +472,7 @@ KeyStoreServer::_AccessKeyring(Keyring& keyring) } // No key, we need to request one from the user. - keyMessage.AddString("keyring", keyring.Name()); - status_t result = _RequestKey(keyMessage); + status_t result = _RequestKey(keyring.Name(), keyMessage); if (result != B_OK) return result; @@ -482,13 +481,13 @@ KeyStoreServer::_AccessKeyring(Keyring& keyring) status_t -KeyStoreServer::_RequestKey(BMessage& keyMessage) +KeyStoreServer::_RequestKey(const BString& keyringName, BMessage& keyMessage) { KeyRequestWindow* requestWindow = new(std::nothrow) KeyRequestWindow(); if (requestWindow == NULL) return B_NO_MEMORY; - return requestWindow->RequestKey(keyMessage); + return requestWindow->RequestKey(keyringName, keyMessage); } diff --git a/src/servers/keystore/KeyStoreServer.h b/src/servers/keystore/KeyStoreServer.h index b0bff8a8dd..7729f92f5c 100644 --- a/src/servers/keystore/KeyStoreServer.h +++ b/src/servers/keystore/KeyStoreServer.h @@ -36,7 +36,8 @@ private: status_t _AccessKeyring(Keyring& keyring); - status_t _RequestKey(BMessage& keyMessage); + status_t _RequestKey(const BString& keyringName, + BMessage& keyMessage); Keyring* fDefaultKeyring; KeyringList fKeyrings; From 51ab46a83c98631702ef1b4734af7db7ec0672ab Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sun, 8 Jan 2012 01:43:19 +0100 Subject: [PATCH 061/104] Remove the purpose argument from all GetKey() variants. The type is relevant and required as it determines the type of the handed in key. The purpose however isn't actually needed and rather inconvenient to get by depending on the situation. --- headers/os/app/KeyStore.h | 20 ++++++++------------ src/bin/keystore.cpp | 4 ++-- src/kits/app/KeyStore.cpp | 34 +++++++++++++++------------------- 3 files changed, 25 insertions(+), 33 deletions(-) diff --git a/headers/os/app/KeyStore.h b/headers/os/app/KeyStore.h index 3d23fcdf5d..625049549e 100644 --- a/headers/os/app/KeyStore.h +++ b/headers/os/app/KeyStore.h @@ -16,27 +16,23 @@ public: // TODO: -> GetNextPassword() - there can always be more than one key // with the same identifier/secondaryIdentifier (ie. different username) - status_t GetKey(BKeyType type, BKeyPurpose purpose, - const char* identifier, BKey& key); - status_t GetKey(BKeyType type, BKeyPurpose purpose, - const char* identifier, + status_t GetKey(BKeyType type, const char* identifier, + BKey& key); + status_t GetKey(BKeyType type, const char* identifier, const char* secondaryIdentifier, BKey& key); - status_t GetKey(BKeyType type, BKeyPurpose purpose, - const char* identifier, + status_t GetKey(BKeyType type, const char* identifier, const char* secondaryIdentifier, bool secondaryIdentifierOptional, BKey& key); status_t GetKey(const char* keyring, - BKeyType type, BKeyPurpose purpose, - const char* identifier, BKey& key); + BKeyType type, const char* identifier, + BKey& key); status_t GetKey(const char* keyring, - BKeyType type, BKeyPurpose purpose, - const char* identifier, + BKeyType type, const char* identifier, const char* secondaryIdentifier, BKey& key); status_t GetKey(const char* keyring, - BKeyType type, BKeyPurpose purpose, - const char* identifier, + BKeyType type, const char* identifier, const char* secondaryIdentifier, bool secondaryIdentifierOptional, BKey& key); diff --git a/src/bin/keystore.cpp b/src/bin/keystore.cpp index 8d6cf028c7..c4148f47a4 100644 --- a/src/bin/keystore.cpp +++ b/src/bin/keystore.cpp @@ -37,8 +37,8 @@ remove_password(const char* keyring, const char* identifier, BKeyStore keyStore; BPasswordKey password; - status_t result = keyStore.GetKey(keyring, B_KEY_TYPE_PASSWORD, - B_KEY_PURPOSE_ANY, identifier, secondaryIdentifier, false, password); + status_t result = keyStore.GetKey(keyring, B_KEY_TYPE_PASSWORD, identifier, + secondaryIdentifier, false, password); if (result != B_OK) { printf("failed to get password \"%s\": %s\n", identifier, strerror(result)); diff --git a/src/kits/app/KeyStore.cpp b/src/kits/app/KeyStore.cpp index dea28718a1..3278ba7e82 100644 --- a/src/kits/app/KeyStore.cpp +++ b/src/kits/app/KeyStore.cpp @@ -28,58 +28,54 @@ BKeyStore::~BKeyStore() status_t -BKeyStore::GetKey(BKeyType type, BKeyPurpose purpose, const char* identifier, - BKey& key) +BKeyStore::GetKey(BKeyType type, const char* identifier, BKey& key) { - return GetKey(NULL, type, purpose, identifier, NULL, true, key); + return GetKey(NULL, type, identifier, NULL, true, key); } status_t -BKeyStore::GetKey(BKeyType type, BKeyPurpose purpose, const char* identifier, +BKeyStore::GetKey(BKeyType type, const char* identifier, const char* secondaryIdentifier, BKey& key) { - return GetKey(NULL, type, purpose, identifier, secondaryIdentifier, true, - key); + return GetKey(NULL, type, identifier, secondaryIdentifier, true, key); } status_t -BKeyStore::GetKey(BKeyType type, BKeyPurpose purpose, const char* identifier, +BKeyStore::GetKey(BKeyType type, const char* identifier, const char* secondaryIdentifier, bool secondaryIdentifierOptional, BKey& key) { - return GetKey(NULL, type, purpose, identifier, secondaryIdentifier, + return GetKey(NULL, type, identifier, secondaryIdentifier, secondaryIdentifierOptional, key); } status_t -BKeyStore::GetKey(const char* keyring, BKeyType type, BKeyPurpose purpose, - const char* identifier, BKey& key) +BKeyStore::GetKey(const char* keyring, BKeyType type, const char* identifier, + BKey& key) { - return GetKey(keyring, type, purpose, identifier, NULL, true, key); + return GetKey(keyring, type, identifier, NULL, true, key); } status_t -BKeyStore::GetKey(const char* keyring, BKeyType type, BKeyPurpose purpose, - const char* identifier, const char* secondaryIdentifier, BKey& key) +BKeyStore::GetKey(const char* keyring, BKeyType type, const char* identifier, + const char* secondaryIdentifier, BKey& key) { - return GetKey(keyring, type, purpose, identifier, secondaryIdentifier, true, - key); + return GetKey(keyring, type, identifier, secondaryIdentifier, true, key); } status_t -BKeyStore::GetKey(const char* keyring, BKeyType type, BKeyPurpose purpose, - const char* identifier, const char* secondaryIdentifier, - bool secondaryIdentifierOptional, BKey& key) +BKeyStore::GetKey(const char* keyring, BKeyType type, const char* identifier, + const char* secondaryIdentifier, bool secondaryIdentifierOptional, + BKey& key) { BMessage message(KEY_STORE_GET_KEY); message.AddString("keyring", keyring); message.AddUInt32("type", type); - message.AddUInt32("purpose", purpose); message.AddString("identifier", identifier); message.AddString("secondaryIdentifier", secondaryIdentifier); message.AddBool("secondaryIdentifierOptional", secondaryIdentifierOptional); From 64ca113fe04c0f0380fdb7df17c412de694e74c2 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sun, 8 Jan 2012 01:55:14 +0100 Subject: [PATCH 062/104] Add keyring specific versions of the *Application() methods. --- headers/os/app/KeyStore.h | 5 +++++ src/kits/app/KeyStore.cpp | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/headers/os/app/KeyStore.h b/headers/os/app/KeyStore.h index 625049549e..7af178fbf8 100644 --- a/headers/os/app/KeyStore.h +++ b/headers/os/app/KeyStore.h @@ -81,8 +81,13 @@ public: status_t GetNextApplication(const BKey& key, uint32& cookie, BString& signature) const; + status_t GetNextApplication(const char* keyring, + const BKey& key, uint32& cookie, + BString& signature) const; status_t RemoveApplication(const BKey& key, const char* signature); + status_t RemoveApplication(const char* keyring, + const BKey& key, const char* signature); // Service functions diff --git a/src/kits/app/KeyStore.cpp b/src/kits/app/KeyStore.cpp index 3278ba7e82..64cca00cf8 100644 --- a/src/kits/app/KeyStore.cpp +++ b/src/kits/app/KeyStore.cpp @@ -335,12 +335,21 @@ BKeyStore::RevokeMasterAccess() status_t BKeyStore::GetNextApplication(const BKey& key, uint32& cookie, BString& signature) const +{ + return GetNextApplication(NULL, key, cookie, signature); +} + + +status_t +BKeyStore::GetNextApplication(const char* keyring, const BKey& key, + uint32& cookie, BString& signature) const { BMessage keyMessage; if (key.Flatten(keyMessage) != B_OK) return B_BAD_VALUE; BMessage message(KEY_STORE_GET_NEXT_APPLICATION); + message.AddString("keyring", keyring); message.AddMessage("key", &keyMessage); message.AddUInt32("cookie", cookie); @@ -359,12 +368,21 @@ BKeyStore::GetNextApplication(const BKey& key, uint32& cookie, status_t BKeyStore::RemoveApplication(const BKey& key, const char* signature) +{ + return RemoveApplication(NULL, key, signature); +} + + +status_t +BKeyStore::RemoveApplication(const char* keyring, const BKey& key, + const char* signature) { BMessage keyMessage; if (key.Flatten(keyMessage) != B_OK) return B_BAD_VALUE; BMessage message(KEY_STORE_REMOVE_APPLICATION); + message.AddString("keyring", keyring); message.AddMessage("key", &keyMessage); message.AddString("signature", signature); From a5a2a2754e841b3a1e683a456d1c46a935a873e0 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Fri, 3 Feb 2012 21:11:01 +0100 Subject: [PATCH 063/104] Make the keystore cli app a BApplication. We need the app to be registered so that the app info can be retrieved. --- src/bin/Jamfile | 2 +- src/bin/keystore/Jamfile | 6 ++++++ src/bin/{ => keystore}/keystore.cpp | 3 +++ src/bin/keystore/keystore.rdef | 2 ++ 4 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 src/bin/keystore/Jamfile rename src/bin/{ => keystore}/keystore.cpp (98%) create mode 100644 src/bin/keystore/keystore.rdef diff --git a/src/bin/Jamfile b/src/bin/Jamfile index e4f0116810..a06268af96 100644 --- a/src/bin/Jamfile +++ b/src/bin/Jamfile @@ -88,7 +88,6 @@ StdBinCommands draggers.cpp ffm.cpp iroster.cpp - keystore.cpp listattr.cpp listfont.cpp listres.cpp @@ -254,6 +253,7 @@ SubInclude HAIKU_TOP src bin hid_decode ; SubInclude HAIKU_TOP src bin iasl ; SubInclude HAIKU_TOP src bin ideinfo ; SubInclude HAIKU_TOP src bin keymap ; +SubInclude HAIKU_TOP src bin keystore ; SubInclude HAIKU_TOP src bin less ; SubInclude HAIKU_TOP src bin listdev ; SubInclude HAIKU_TOP src bin locale ; diff --git a/src/bin/keystore/Jamfile b/src/bin/keystore/Jamfile new file mode 100644 index 0000000000..8577d772a1 --- /dev/null +++ b/src/bin/keystore/Jamfile @@ -0,0 +1,6 @@ +SubDir HAIKU_TOP src bin keystore ; + +BinCommand keystore : + keystore.cpp + : be + : keystore.rdef ; diff --git a/src/bin/keystore.cpp b/src/bin/keystore/keystore.cpp similarity index 98% rename from src/bin/keystore.cpp rename to src/bin/keystore/keystore.cpp index c4148f47a4..2dd66cddf3 100644 --- a/src/bin/keystore.cpp +++ b/src/bin/keystore/keystore.cpp @@ -7,6 +7,7 @@ */ +#include #include #include @@ -243,6 +244,8 @@ print_usage(const char* name) int main(int argc, char* argv[]) { + BApplication app("application/x-vnd.Haiku-keystore-cli"); + if (argc < 2) return print_usage(argv[0]); diff --git a/src/bin/keystore/keystore.rdef b/src/bin/keystore/keystore.rdef new file mode 100644 index 0000000000..e98269230a --- /dev/null +++ b/src/bin/keystore/keystore.rdef @@ -0,0 +1,2 @@ +resource app_signature "application/x-vnd.Haiku-keystore-cli"; +resource app_flags B_MULTIPLE_LAUNCH; From 97b3abf1624641d7d6f14a7657ae572fa2a6ab2e Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Tue, 7 Feb 2012 16:21:23 +0100 Subject: [PATCH 064/104] Add access flags to fine tune application access. Not sure if these will actually be used, as they might just be a little overkill and not easily usable. --- src/servers/keystore/KeyStoreServer.cpp | 67 +++++++++++++++++++++++++ src/servers/keystore/KeyStoreServer.h | 2 + 2 files changed, 69 insertions(+) diff --git a/src/servers/keystore/KeyStoreServer.cpp b/src/servers/keystore/KeyStoreServer.cpp index 3eda433198..2324f18206 100644 --- a/src/servers/keystore/KeyStoreServer.cpp +++ b/src/servers/keystore/KeyStoreServer.cpp @@ -27,6 +27,31 @@ using namespace BPrivate; static const char* kKeyringKeysIdentifier = "Keyrings"; +static const uint32 kFlagGetKey = 0x0001; +static const uint32 kFlagEnumerateKeys = 0x0002; +static const uint32 kFlagAddKey = 0x0004; +static const uint32 kFlagRemoveKey = 0x0008; +static const uint32 kFlagAddKeyring = 0x0010; +static const uint32 kFlagRemoveKeyring = 0x0020; +static const uint32 kFlagEnumerateKeyrings = 0x0040; +static const uint32 kFlagSetMasterKey = 0x0080; +static const uint32 kFlagRemoveMasterKey = 0x0100; +static const uint32 kFlagAddKeyringsToMaster = 0x0200; +static const uint32 kFlagRemoveKeyringsFromMaster = 0x0400; +static const uint32 kFlagEnumerateMasterKeyrings = 0x0800; +static const uint32 kFlagQueryAccessibility = 0x1000; +static const uint32 kFlagRevokeAccess = 0x2000; +static const uint32 kFlagEnumerateApplications = 0x4000; +static const uint32 kFlagRemoveApplications = 0x8000; + +static const uint32 kDefaultAppFlags = kFlagGetKey | kFlagEnumerateKeys + | kFlagAddKey | kFlagRemoveKey | kFlagAddKeyring | kFlagRemoveKeyring + | kFlagEnumerateKeyrings | kFlagSetMasterKey | kFlagRemoveMasterKey + | kFlagAddKeyringsToMaster | kFlagRemoveKeyringsFromMaster + | kFlagEnumerateMasterKeyrings | kFlagQueryAccessibility + | kFlagQueryAccessibility | kFlagRevokeAccess | kFlagEnumerateApplications + | kFlagRemoveApplications; + KeyStoreServer::KeyStoreServer() : @@ -411,6 +436,48 @@ KeyStoreServer::_WriteKeyStoreDatabase() } +uint32 +KeyStoreServer::_AccessFlagsFor(uint32 command) const +{ + switch (command) { + case KEY_STORE_GET_KEY: + return kFlagGetKey; + case KEY_STORE_GET_NEXT_KEY: + return kFlagEnumerateKeys; + case KEY_STORE_ADD_KEY: + return kFlagAddKey; + case KEY_STORE_REMOVE_KEY: + return kFlagRemoveKey; + case KEY_STORE_ADD_KEYRING: + return kFlagAddKeyring; + case KEY_STORE_REMOVE_KEYRING: + return kFlagRemoveKeyring; + case KEY_STORE_GET_NEXT_KEYRING: + return kFlagEnumerateKeyrings; + case KEY_STORE_SET_MASTER_KEY: + return kFlagSetMasterKey; + case KEY_STORE_REMOVE_MASTER_KEY: + return kFlagRemoveMasterKey; + case KEY_STORE_ADD_KEYRING_TO_MASTER: + return kFlagAddKeyringsToMaster; + case KEY_STORE_REMOVE_KEYRING_FROM_MASTER: + return kFlagRemoveKeyringsFromMaster; + case KEY_STORE_GET_NEXT_MASTER_KEYRING: + return kFlagEnumerateMasterKeyrings; + case KEY_STORE_IS_KEYRING_ACCESSIBLE: + return kFlagQueryAccessibility; + case KEY_STORE_REVOKE_ACCESS: + return kFlagRevokeAccess; + case KEY_STORE_GET_NEXT_APPLICATION: + return kFlagEnumerateApplications; + case KEY_STORE_REMOVE_APPLICATION: + return kFlagRemoveApplications; + } + + return 0; +} + + Keyring* KeyStoreServer::_FindKeyring(const BString& name) { diff --git a/src/servers/keystore/KeyStoreServer.h b/src/servers/keystore/KeyStoreServer.h index 7729f92f5c..2ec5a4fad9 100644 --- a/src/servers/keystore/KeyStoreServer.h +++ b/src/servers/keystore/KeyStoreServer.h @@ -28,6 +28,8 @@ private: status_t _ReadKeyStoreDatabase(); status_t _WriteKeyStoreDatabase(); + uint32 _AccessFlagsFor(uint32 command) const; + Keyring* _FindKeyring(const BString& name); status_t _AddKeyring(const BString& name, From 1b3bb46aed33bd68bf5e4dba1625ad3211b31adc Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Tue, 7 Feb 2012 16:29:12 +0100 Subject: [PATCH 065/104] Restructure how keyrings are stored/restored. * Pass them through a flat buffer that can later be encrypted and decrypted in a central place. * Remove the data argument from the constructor as keyrings are now reading their data on their own. * Prepare for additional application info storage in the keyring. --- src/servers/keystore/KeyStoreServer.cpp | 28 +++--- src/servers/keystore/Keyring.cpp | 114 ++++++++++++++++++++++-- src/servers/keystore/Keyring.h | 9 +- 3 files changed, 130 insertions(+), 21 deletions(-) diff --git a/src/servers/keystore/KeyStoreServer.cpp b/src/servers/keystore/KeyStoreServer.cpp index 2324f18206..ac5fb69eff 100644 --- a/src/servers/keystore/KeyStoreServer.cpp +++ b/src/servers/keystore/KeyStoreServer.cpp @@ -82,7 +82,7 @@ KeyStoreServer::KeyStoreServer() _ReadKeyStoreDatabase(); if (fDefaultKeyring == NULL) - fDefaultKeyring = new(std::nothrow) Keyring("", BMessage()); + fDefaultKeyring = new(std::nothrow) Keyring(""); } @@ -388,19 +388,17 @@ KeyStoreServer::_ReadKeyStoreDatabase() int32 index = 0; char* keyringName = NULL; - while (keyrings.GetInfo(B_MESSAGE_TYPE, index++, &keyringName, - NULL) == B_OK) { - - BMessage keyringData; - if (keyrings.FindMessage(keyringName, &keyringData) != B_OK) { - printf("failed to retrieve keyring data for keyring \"%s\"\n", - keyringName); + while (keyrings.GetInfo(B_RAW_TYPE, index++, &keyringName, NULL) == B_OK) { + Keyring* keyring = new(std::nothrow) Keyring(keyringName); + if (keyring == NULL) { + printf("no memory for allocating keyring \"%s\"\n", keyringName); continue; } - Keyring* keyring = new(std::nothrow) Keyring(keyringName, keyringData); - if (keyring == NULL) { - printf("no memory for allocating keyring \"%s\"\n", keyringName); + status_t result = keyring->ReadFromMessage(keyrings); + if (result != B_OK) { + printf("failed to read keyring \"%s\" from data\n", keyringName); + delete keyring; continue; } @@ -422,14 +420,16 @@ KeyStoreServer::_WriteKeyStoreDatabase() BMessage keyrings; if (fDefaultKeyring != NULL) - keyrings.AddMessage("", &fDefaultKeyring->Data()); + fDefaultKeyring->WriteToMessage(keyrings); for (int32 i = 0; i < fKeyrings.CountItems(); i++) { Keyring* keyring = fKeyrings.ItemAt(i); if (keyring == NULL) continue; - keyrings.AddMessage(keyring->Name(), &keyring->Data()); + status_t result = keyring->WriteToMessage(keyrings); + if (result != B_OK) + return result; } return keyrings.Flatten(&fKeyStoreFile); @@ -494,7 +494,7 @@ KeyStoreServer::_AddKeyring(const BString& name, const BMessage& keyMessage) if (_FindKeyring(name) != NULL) return B_NAME_IN_USE; - Keyring* keyring = new(std::nothrow) Keyring(name, BMessage(), &keyMessage); + Keyring* keyring = new(std::nothrow) Keyring(name, &keyMessage); if (keyring == NULL) return B_NO_MEMORY; diff --git a/src/servers/keystore/Keyring.cpp b/src/servers/keystore/Keyring.cpp index fc77baf9ea..854b521f49 100644 --- a/src/servers/keystore/Keyring.cpp +++ b/src/servers/keystore/Keyring.cpp @@ -7,14 +7,13 @@ #include "Keyring.h" -Keyring::Keyring(const char* name, const BMessage& data, - const BMessage* keyMessage) +Keyring::Keyring(const char* name, const BMessage* keyMessage) : fName(name), - fData(data), - fKeyMessage(*keyMessage), - fAccessible(keyMessage != NULL) + fAccessible(false) { + if (keyMessage != NULL) + Access(*keyMessage); } @@ -23,10 +22,52 @@ Keyring::~Keyring() } +status_t +Keyring::ReadFromMessage(const BMessage& message) +{ + ssize_t size; + const void* data; + status_t result = message.FindData(fName, B_RAW_TYPE, &data, &size); + if (result != B_OK) + return result; + + if (size < 0) + return B_ERROR; + + fFlatBuffer.SetSize(0); + ssize_t written = fFlatBuffer.WriteAt(0, data, size); + if (written != size) { + fFlatBuffer.SetSize(0); + return written < 0 ? written : B_ERROR; + } + + return B_OK; +} + + +status_t +Keyring::WriteToMessage(BMessage& message) +{ + status_t result = _EncryptToFlatBuffer(); + if (result != B_OK) + return result; + + return message.AddData(fName, B_RAW_TYPE, fFlatBuffer.Buffer(), + fFlatBuffer.BufferLength()); +} + + status_t Keyring::Access(const BMessage& keyMessage) { fKeyMessage = keyMessage; + + status_t result = _DecryptFromFlatBuffer(); + if (result != B_OK) { + fKeyMessage.MakeEmpty(); + return result; + } + fAccessible = true; return B_OK; } @@ -35,7 +76,14 @@ Keyring::Access(const BMessage& keyMessage) void Keyring::RevokeAccess() { + if (!fAccessible) + return; + + _EncryptToFlatBuffer(); + fKeyMessage.MakeEmpty(); + fData.MakeEmpty(); + fApplications.MakeEmpty(); fAccessible = false; } @@ -222,3 +270,59 @@ Keyring::Compare(const BString* name, const Keyring* keyring) { return strcmp(name->String(), keyring->Name()); } + + +status_t +Keyring::_EncryptToFlatBuffer() +{ + if (!fAccessible) + return B_NOT_ALLOWED; + + BMessage container; + status_t result = container.AddMessage("data", &fData); + if (result != B_OK) + return result; + + result = container.AddMessage("applications", &fApplications); + if (result != B_OK) + return result; + + fFlatBuffer.SetSize(0); + fFlatBuffer.Seek(0, SEEK_SET); + + result = container.Flatten(&fFlatBuffer); + if (result != B_OK) + return result; + + // TODO: Actually encrypt the flat buffer... + + return B_OK; +} + + +status_t +Keyring::_DecryptFromFlatBuffer() +{ + if (fFlatBuffer.BufferLength() == 0) + return B_OK; + + // TODO: Actually decrypt the flat buffer... + + BMessage container; + fFlatBuffer.Seek(0, SEEK_SET); + status_t result = container.Unflatten(&fFlatBuffer); + if (result != B_OK) + return result; + + result = container.FindMessage("data", &fData); + if (result != B_OK) + return result; + + result = container.FindMessage("applications", &fApplications); + if (result != B_OK) { + fData.MakeEmpty(); + return result; + } + + return B_OK; +} diff --git a/src/servers/keystore/Keyring.h b/src/servers/keystore/Keyring.h index bdd426db1a..85c52ecd6c 100644 --- a/src/servers/keystore/Keyring.h +++ b/src/servers/keystore/Keyring.h @@ -13,12 +13,12 @@ class Keyring { public: Keyring(const char* name, - const BMessage& data, const BMessage* keyMessage = NULL); ~Keyring(); const char* Name() const { return fName; } - const BMessage& Data() const { return fData; } + status_t ReadFromMessage(const BMessage& message); + status_t WriteToMessage(BMessage& message); status_t Access(const BMessage& keyMessage); void RevokeAccess(); @@ -45,8 +45,13 @@ static int Compare(const BString* name, const Keyring* keyring); private: + status_t _EncryptToFlatBuffer(); + status_t _DecryptFromFlatBuffer(); + BString fName; + BMallocIO fFlatBuffer; BMessage fData; + BMessage fApplications; BMessage fKeyMessage; bool fAccessible; }; From 6ef5917d45654e4c72c75cee9cbfe8bce54ad027 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Tue, 7 Feb 2012 16:32:56 +0100 Subject: [PATCH 066/104] Only write and encrypt the flat buffer when modified. --- src/servers/keystore/Keyring.cpp | 20 +++++++++++++++++--- src/servers/keystore/Keyring.h | 1 + 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/servers/keystore/Keyring.cpp b/src/servers/keystore/Keyring.cpp index 854b521f49..144edcb5b5 100644 --- a/src/servers/keystore/Keyring.cpp +++ b/src/servers/keystore/Keyring.cpp @@ -10,7 +10,8 @@ Keyring::Keyring(const char* name, const BMessage* keyMessage) : fName(name), - fAccessible(false) + fAccessible(false), + fModified(false) { if (keyMessage != NULL) Access(*keyMessage); @@ -225,7 +226,12 @@ Keyring::AddKey(const BString& identifier, const BString& secondaryIdentifier, return B_NAME_IN_USE; // We're fine, just add the new key. - return fData.AddMessage(identifier, &keyMessage); + status_t result = fData.AddMessage(identifier, &keyMessage); + if (result != B_OK) + return result; + + fModified = true; + return B_OK; } @@ -250,7 +256,11 @@ Keyring::RemoveKey(const BString& identifier, if (!candidate.HasSameData(keyMessage)) continue; - fData.RemoveData(identifier, i); + status_t result = fData.RemoveData(identifier, i); + if (result != B_OK) + return result; + + fModified = true; return B_OK; } @@ -275,6 +285,9 @@ Keyring::Compare(const BString* name, const Keyring* keyring) status_t Keyring::_EncryptToFlatBuffer() { + if (!fModified) + return B_OK; + if (!fAccessible) return B_NOT_ALLOWED; @@ -296,6 +309,7 @@ Keyring::_EncryptToFlatBuffer() // TODO: Actually encrypt the flat buffer... + fModified = false; return B_OK; } diff --git a/src/servers/keystore/Keyring.h b/src/servers/keystore/Keyring.h index 85c52ecd6c..9539487419 100644 --- a/src/servers/keystore/Keyring.h +++ b/src/servers/keystore/Keyring.h @@ -54,6 +54,7 @@ private: BMessage fApplications; BMessage fKeyMessage; bool fAccessible; + bool fModified; }; From d389650a7af43f0b9930fd1257362e4ecd2d5a43 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Tue, 7 Feb 2012 16:34:29 +0100 Subject: [PATCH 067/104] Add application info handling into the Keyring class. --- src/servers/keystore/Keyring.cpp | 75 ++++++++++++++++++++++++++++++++ src/servers/keystore/Keyring.h | 7 +++ 2 files changed, 82 insertions(+) diff --git a/src/servers/keystore/Keyring.cpp b/src/servers/keystore/Keyring.cpp index 144edcb5b5..f6f5f2e18c 100644 --- a/src/servers/keystore/Keyring.cpp +++ b/src/servers/keystore/Keyring.cpp @@ -103,6 +103,81 @@ Keyring::KeyMessage() const } +status_t +Keyring::FindApplication(const char* signature, const char* path, + BMessage& appMessage) +{ + if (!fAccessible) + return B_NOT_ALLOWED; + + int32 count; + type_code type; + if (fApplications.GetInfo(signature, &type, &count) != B_OK) + return B_ENTRY_NOT_FOUND; + + for (int32 i = 0; i < count; i++) { + if (fApplications.FindMessage(signature, i, &appMessage) != B_OK) + continue; + + BString appPath; + if (appMessage.FindString("path", &appPath) != B_OK) + continue; + + if (appPath == path) + return B_OK; + } + + appMessage.MakeEmpty(); + return B_ENTRY_NOT_FOUND; +} + + +status_t +Keyring::AddApplication(const char* signature, const BMessage& appMessage) +{ + if (!fAccessible) + return B_NOT_ALLOWED; + + status_t result = fApplications.AddMessage(signature, &appMessage); + if (result != B_OK) + return result; + + fModified = true; + return B_OK; +} + + +status_t +Keyring::RemoveApplication(const char* signature, const char* path) +{ + if (!fAccessible) + return B_NOT_ALLOWED; + + int32 count; + type_code type; + if (fApplications.GetInfo(signature, &type, &count) != B_OK) + return B_ENTRY_NOT_FOUND; + + for (int32 i = 0; i < count; i++) { + BMessage appMessage; + if (fApplications.FindMessage(signature, i, &appMessage) != B_OK) + return B_ERROR; + + BString appPath; + if (appMessage.FindString("path", &appPath) != B_OK) + continue; + + if (appPath == path) { + fApplications.RemoveData(signature, i); + fModified = true; + return B_OK; + } + } + + return B_ENTRY_NOT_FOUND; +} + + status_t Keyring::FindKey(const BString& identifier, const BString& secondaryIdentifier, bool secondaryIdentifierOptional, BMessage* _foundKeyMessage) const diff --git a/src/servers/keystore/Keyring.h b/src/servers/keystore/Keyring.h index 9539487419..0c75263aa2 100644 --- a/src/servers/keystore/Keyring.h +++ b/src/servers/keystore/Keyring.h @@ -25,6 +25,13 @@ public: bool IsAccessible() const; const BMessage& KeyMessage() const; + status_t FindApplication(const char* signature, + const char* path, BMessage& appMessage); + status_t AddApplication(const char* signature, + const BMessage& appMessage); + status_t RemoveApplication(const char* signature, + const char* path); + status_t FindKey(const BString& identifier, const BString& secondaryIdentifier, bool secondaryIdentifierOptional, From aef629f2006ee84735dedd3fa8c92460b1272183 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Tue, 7 Feb 2012 16:36:04 +0100 Subject: [PATCH 068/104] Only clear the keystore database when prepartion worked. --- src/servers/keystore/KeyStoreServer.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/servers/keystore/KeyStoreServer.cpp b/src/servers/keystore/KeyStoreServer.cpp index ac5fb69eff..91f1e34365 100644 --- a/src/servers/keystore/KeyStoreServer.cpp +++ b/src/servers/keystore/KeyStoreServer.cpp @@ -415,9 +415,6 @@ KeyStoreServer::_ReadKeyStoreDatabase() status_t KeyStoreServer::_WriteKeyStoreDatabase() { - fKeyStoreFile.SetSize(0); - fKeyStoreFile.Seek(0, SEEK_SET); - BMessage keyrings; if (fDefaultKeyring != NULL) fDefaultKeyring->WriteToMessage(keyrings); @@ -432,6 +429,8 @@ KeyStoreServer::_WriteKeyStoreDatabase() return result; } + fKeyStoreFile.SetSize(0); + fKeyStoreFile.Seek(0, SEEK_SET); return keyrings.Flatten(&fKeyStoreFile); } From 76df966ee6a656a9b51896653b3c411a53688fe4 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Tue, 7 Feb 2012 16:38:44 +0100 Subject: [PATCH 069/104] Add a preliminary way to resolve the calling application. This will have to be reworked though, as by using the roster only BApplications can be resolved, as plain cli apps aren't registered with the registrar. --- src/servers/keystore/KeyStoreServer.cpp | 19 +++++++++++++++++++ src/servers/keystore/KeyStoreServer.h | 3 +++ 2 files changed, 22 insertions(+) diff --git a/src/servers/keystore/KeyStoreServer.cpp b/src/servers/keystore/KeyStoreServer.cpp index 91f1e34365..5042f2730c 100644 --- a/src/servers/keystore/KeyStoreServer.cpp +++ b/src/servers/keystore/KeyStoreServer.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -477,6 +478,24 @@ KeyStoreServer::_AccessFlagsFor(uint32 command) const } +status_t +KeyStoreServer::_ResolveCallingApp(const BMessage& message, + app_info& callingAppInfo) const +{ + team_id callingTeam = message.ReturnAddress().Team(); + status_t result = be_roster->GetRunningAppInfo(callingTeam, + &callingAppInfo); + if (result != B_OK) + return result; + + // Do some sanity checks. + if (callingAppInfo.team != callingTeam) + return B_ERROR; + + return B_OK; +} + + Keyring* KeyStoreServer::_FindKeyring(const BString& name) { diff --git a/src/servers/keystore/KeyStoreServer.h b/src/servers/keystore/KeyStoreServer.h index 2ec5a4fad9..00c9bfbc94 100644 --- a/src/servers/keystore/KeyStoreServer.h +++ b/src/servers/keystore/KeyStoreServer.h @@ -12,6 +12,7 @@ #include +struct app_info; class Keyring; typedef BObjectList KeyringList; @@ -29,6 +30,8 @@ private: status_t _WriteKeyStoreDatabase(); uint32 _AccessFlagsFor(uint32 command) const; + status_t _ResolveCallingApp(const BMessage& message, + app_info& callingAppInfo) const; Keyring* _FindKeyring(const BString& name); From f32874e61100f1d52ecff6cf97177157bbe88d22 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Tue, 7 Feb 2012 16:44:28 +0100 Subject: [PATCH 070/104] Add an application access request dialog. --- .../keystore/AppAccessRequestWindow.cpp | 204 ++++++++++++++++++ src/servers/keystore/AppAccessRequestWindow.h | 38 ++++ 2 files changed, 242 insertions(+) create mode 100644 src/servers/keystore/AppAccessRequestWindow.cpp create mode 100644 src/servers/keystore/AppAccessRequestWindow.h diff --git a/src/servers/keystore/AppAccessRequestWindow.cpp b/src/servers/keystore/AppAccessRequestWindow.cpp new file mode 100644 index 0000000000..8c7a8df61d --- /dev/null +++ b/src/servers/keystore/AppAccessRequestWindow.cpp @@ -0,0 +1,204 @@ +/* + * Copyright 2012, Michael Lotz, mmlr@mlotz.ch. All Rights Reserved. + * Distributed under the terms of the MIT License. + */ + + +#include "AppAccessRequestWindow.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +static const uint32 kMessageDisallow = 'btda'; +static const uint32 kMessageOnce = 'btao'; +static const uint32 kMessageAlways = 'btaa'; + + +class AppAccessRequestView : public BView { +public: + AppAccessRequestView(const char* keyringName, const char* signature, + const char* path, bool appIsNew, bool appWasUpdated) + : + BView("AppAccessRequestView", B_WILL_DRAW) + { + SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + + BGroupLayout* rootLayout = new(std::nothrow) BGroupLayout(B_VERTICAL); + if (rootLayout == NULL) + return; + + SetLayout(rootLayout); + + float inset = ceilf(be_plain_font->Size() * 0.7); + rootLayout->SetInsets(inset, inset, inset, inset); + rootLayout->SetSpacing(inset); + + BTextView* message = new(std::nothrow) BTextView("Message"); + if (message == NULL) + return; + + BString details; + details << "The application\n" << signature << " (" << path << ")\n" + << "requests access to keyring\n" << keyringName << "\n"; + if (appIsNew) + details << "This application hasn't been granted access before."; + else if (appWasUpdated) { + details << "This application has been updated since it was last" + << " granted access."; + } else { + details << "This application doesn't yet have the required" + " priviledges."; + } + + message->SetText(details); + + BGroupView* buttons = new(std::nothrow) BGroupView(B_HORIZONTAL); + if (buttons == NULL) + return; + + fDisallowButton = new(std::nothrow) BButton("Disallow", + new BMessage(kMessageDisallow)); + buttons->GroupLayout()->AddView(fDisallowButton); + + buttons->GroupLayout()->AddItem(BSpaceLayoutItem::CreateGlue()); + + fOnceButton = new(std::nothrow) BButton("Allow Once", + new BMessage(kMessageOnce)); + buttons->GroupLayout()->AddView(fOnceButton); + + fAlwaysButton = new(std::nothrow) BButton("Always Allow", + new BMessage(kMessageAlways)); + buttons->GroupLayout()->AddView(fAlwaysButton); + + rootLayout->AddView(message); + rootLayout->AddView(buttons); + } + + virtual void + AttachedToWindow() + { + fDisallowButton->SetTarget(Window()); + fOnceButton->SetTarget(Window()); + fAlwaysButton->SetTarget(Window()); + + // TODO: Decide for a sane default button (or none at all). + //fButton->MakeDefault(true); + } + +private: + BButton* fDisallowButton; + BButton* fOnceButton; + BButton* fAlwaysButton; +}; + + +AppAccessRequestWindow::AppAccessRequestWindow(const char* keyringName, + const char* signature, const char* path, bool appIsNew, bool appWasUpdated) + : + BWindow(BRect(50, 50, 269, 302), "Application Keyring Access", + B_TITLED_WINDOW, B_NOT_RESIZABLE | B_ASYNCHRONOUS_CONTROLS + | B_NOT_ZOOMABLE | B_AUTO_UPDATE_SIZE_LIMITS), + fRequestView(NULL), + fDoneSem(-1), + fResult(kMessageDisallow) +{ + fDoneSem = create_sem(0, "application keyring access dialog"); + if (fDoneSem < 0) + return; + + BLayout* layout = new(std::nothrow) BGroupLayout(B_HORIZONTAL); + if (layout == NULL) + return; + + SetLayout(layout); + + fRequestView = new(std::nothrow) AppAccessRequestView(keyringName, + signature, path, appIsNew, appWasUpdated); + if (fRequestView == NULL) + return; + + layout->AddView(fRequestView); +} + + +AppAccessRequestWindow::~AppAccessRequestWindow() +{ + if (fDoneSem >= 0) + delete_sem(fDoneSem); +} + + +void +AppAccessRequestWindow::DispatchMessage(BMessage* message, BHandler* handler) +{ + int8 key; + if (message->what == B_KEY_DOWN + && message->FindInt8("byte", 0, &key) == B_OK + && key == B_ESCAPE) { + PostMessage(kMessageDisallow); + } + + BWindow::DispatchMessage(message, handler); +} + + +void +AppAccessRequestWindow::MessageReceived(BMessage* message) +{ + switch (message->what) { + case kMessageDisallow: + case kMessageOnce: + case kMessageAlways: + fResult = message->what; + release_sem(fDoneSem); + return; + } + + BWindow::MessageReceived(message); +} + + +status_t +AppAccessRequestWindow::RequestAppAccess(bool& allowAlways) +{ + CenterOnScreen(); + Show(); + + while (acquire_sem(fDoneSem) == B_INTERRUPTED) + ; + + status_t result; + switch (fResult) { + default: + case kMessageDisallow: + result = B_NOT_ALLOWED; + allowAlways = false; + break; + case kMessageOnce: + result = B_OK; + allowAlways = false; + break; + case kMessageAlways: + result = B_OK; + allowAlways = true; + break; + } + + LockLooper(); + Quit(); + return result; +} diff --git a/src/servers/keystore/AppAccessRequestWindow.h b/src/servers/keystore/AppAccessRequestWindow.h new file mode 100644 index 0000000000..2dfbd875e8 --- /dev/null +++ b/src/servers/keystore/AppAccessRequestWindow.h @@ -0,0 +1,38 @@ +/* + * Copyright 2012, Michael Lotz, mmlr@mlotz.ch. All Rights Reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef _APP_ACCESS_REQUEST_WINDOW_H +#define _APP_ACCESS_REQUEST_WINDOW_H + + +#include +#include + + +class AppAccessRequestView; + + +class AppAccessRequestWindow : public BWindow { +public: + AppAccessRequestWindow( + const char* keyringName, + const char* signature, + const char* path, bool appIsNew, + bool appWasUpdated); +virtual ~AppAccessRequestWindow(); + +virtual void DispatchMessage(BMessage* message, + BHandler* handler); +virtual void MessageReceived(BMessage* message); + + status_t RequestAppAccess(bool& allowAlways); + +private: + AppAccessRequestView* fRequestView; + sem_id fDoneSem; + uint32 fResult; +}; + + +#endif // _APP_ACCESS_REQUEST_WINDOW_H From cfa813152623734173149bfb57c236d276729f67 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Tue, 7 Feb 2012 16:47:10 +0100 Subject: [PATCH 071/104] Resolve/validate the calling application, request if needed. The application is resolved and then looked up in the keyring. If the keyring doesn't provide a matching entry, an application access request is triggered. The mechanism doesn't yet do any actual checksums, but has provisions for differentiating between new and changed/updated applications. --- src/servers/keystore/Jamfile | 1 + src/servers/keystore/KeyStoreServer.cpp | 89 +++++++++++++++++++++++++ src/servers/keystore/KeyStoreServer.h | 10 +++ 3 files changed, 100 insertions(+) diff --git a/src/servers/keystore/Jamfile b/src/servers/keystore/Jamfile index e0ccaffba9..b89085a58e 100644 --- a/src/servers/keystore/Jamfile +++ b/src/servers/keystore/Jamfile @@ -3,6 +3,7 @@ SubDir HAIKU_TOP src servers keystore ; UsePrivateHeaders app ; Server keystore_server : + AppAccessRequestWindow.cpp KeyRequestWindow.cpp Keyring.cpp KeyStoreServer.cpp diff --git a/src/servers/keystore/KeyStoreServer.cpp b/src/servers/keystore/KeyStoreServer.cpp index 5042f2730c..f99f784cca 100644 --- a/src/servers/keystore/KeyStoreServer.cpp +++ b/src/servers/keystore/KeyStoreServer.cpp @@ -6,6 +6,7 @@ #include "KeyStoreServer.h" +#include "AppAccessRequestWindow.h" #include "KeyRequestWindow.h" #include "Keyring.h" @@ -97,6 +98,17 @@ KeyStoreServer::MessageReceived(BMessage* message) { BMessage reply; status_t result = B_UNSUPPORTED; + app_info callingAppInfo; + + uint32 accessFlags = _AccessFlagsFor(message->what); + if (accessFlags == 0) + message->what = 0; + + if (message->what != 0) { + result = _ResolveCallingApp(*message, callingAppInfo); + if (result != B_OK) + message->what = 0; + } // Resolve the keyring for the relevant messages. Keyring* keyring = NULL; @@ -138,6 +150,16 @@ KeyStoreServer::MessageReceived(BMessage* message) break; } } + + status_t validateResult = _ValidateAppAccess(*keyring, + callingAppInfo, accessFlags); + if (validateResult != B_OK) { + result = validateResult; + message->what = 0; + break; + } + + break; } } @@ -496,6 +518,73 @@ KeyStoreServer::_ResolveCallingApp(const BMessage& message, } +status_t +KeyStoreServer::_ValidateAppAccess(Keyring& keyring, const app_info& appInfo, + uint32 accessFlags) +{ + BMessage appMessage; + BPath path(&appInfo.ref); + status_t result = keyring.FindApplication(appInfo.signature, + path.Path(), appMessage); + if (result != B_OK && result != B_ENTRY_NOT_FOUND) + return result; + + // TODO: Implement running image checksum mechanism. + BString checksum = "dummy"; + + bool appIsNew = false; + bool appWasUpdated = false; + uint32 appFlags = 0; + BString appSum = ""; + if (result == B_OK) { + if (appMessage.FindUInt32("flags", &appFlags) != B_OK + || appMessage.FindString("checksum", &appSum) != B_OK) { + appIsNew = true; + appFlags = 0; + } else if (appSum != checksum) { + appWasUpdated = true; + appFlags = 0; + } + } else + appIsNew = true; + + if ((accessFlags & appFlags) == accessFlags) + return B_OK; + + bool allowAlways = false; + result = _RequestAppAccess(keyring.Name(), appInfo.signature, path.Path(), + appIsNew, appWasUpdated, accessFlags, allowAlways); + if (result != B_OK || !allowAlways) + return result; + + appMessage.MakeEmpty(); + appMessage.AddString("path", path.Path()); + appMessage.AddUInt32("flags", accessFlags); + appMessage.AddString("checksum", checksum); + + keyring.RemoveApplication(appInfo.signature, path.Path()); + if (keyring.AddApplication(appInfo.signature, appMessage) == B_OK) + _WriteKeyStoreDatabase(); + + return B_OK; +} + + +status_t +KeyStoreServer::_RequestAppAccess(const BString& keyringName, + const char* signature, const char* path, bool appIsNew, bool appWasUpdated, + uint32 accessFlags, bool& allowAlways) +{ + AppAccessRequestWindow* requestWindow + = new(std::nothrow) AppAccessRequestWindow(keyringName, signature, path, + appIsNew, appWasUpdated); + if (requestWindow == NULL) + return B_NO_MEMORY; + + return requestWindow->RequestAppAccess(allowAlways); +} + + Keyring* KeyStoreServer::_FindKeyring(const BString& name) { diff --git a/src/servers/keystore/KeyStoreServer.h b/src/servers/keystore/KeyStoreServer.h index 00c9bfbc94..0490a7da6a 100644 --- a/src/servers/keystore/KeyStoreServer.h +++ b/src/servers/keystore/KeyStoreServer.h @@ -33,6 +33,16 @@ private: status_t _ResolveCallingApp(const BMessage& message, app_info& callingAppInfo) const; + status_t _ValidateAppAccess(Keyring& keyring, + const app_info& appInfo, + uint32 accessFlags); + status_t _RequestAppAccess( + const BString& keyringName, + const char* signature, + const char* path, bool appIsNew, + bool appWasUpdated, uint32 accessFlags, + bool& allowAlways); + Keyring* _FindKeyring(const BString& name); status_t _AddKeyring(const BString& name, From 0778e1477dc3080ab2f40cb8159324eb88696779 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Tue, 7 Feb 2012 17:08:12 +0100 Subject: [PATCH 072/104] Add application iteration method. --- src/servers/keystore/Keyring.cpp | 24 ++++++++++++++++++++++++ src/servers/keystore/Keyring.h | 2 ++ 2 files changed, 26 insertions(+) diff --git a/src/servers/keystore/Keyring.cpp b/src/servers/keystore/Keyring.cpp index f6f5f2e18c..ed227ab647 100644 --- a/src/servers/keystore/Keyring.cpp +++ b/src/servers/keystore/Keyring.cpp @@ -103,6 +103,30 @@ Keyring::KeyMessage() const } +status_t +Keyring::GetNextApplication(uint32& cookie, BString& signature, + BString& path) +{ + char* nameFound = NULL; + status_t result = fApplications.GetInfo(B_MESSAGE_TYPE, cookie++, + &nameFound, NULL); + if (result != B_OK) + return B_ENTRY_NOT_FOUND; + + BMessage appMessage; + result = fApplications.FindMessage(nameFound, &appMessage); + if (result != B_OK) + return B_ENTRY_NOT_FOUND; + + result = appMessage.FindString("path", &path); + if (result != B_OK) + return B_ERROR; + + signature = nameFound; + return B_OK; +} + + status_t Keyring::FindApplication(const char* signature, const char* path, BMessage& appMessage) diff --git a/src/servers/keystore/Keyring.h b/src/servers/keystore/Keyring.h index 0c75263aa2..b5381f29f5 100644 --- a/src/servers/keystore/Keyring.h +++ b/src/servers/keystore/Keyring.h @@ -25,6 +25,8 @@ public: bool IsAccessible() const; const BMessage& KeyMessage() const; + status_t GetNextApplication(uint32& cookie, + BString& signature, BString& path); status_t FindApplication(const char* signature, const char* path, BMessage& appMessage); status_t AddApplication(const char* signature, From 67a46444549127d31e83e0c29351e564e4b70b16 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Tue, 7 Feb 2012 17:13:01 +0100 Subject: [PATCH 073/104] Allow for all entries of an application to be removed. --- src/servers/keystore/Keyring.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/servers/keystore/Keyring.cpp b/src/servers/keystore/Keyring.cpp index ed227ab647..4f705785ce 100644 --- a/src/servers/keystore/Keyring.cpp +++ b/src/servers/keystore/Keyring.cpp @@ -177,6 +177,16 @@ Keyring::RemoveApplication(const char* signature, const char* path) if (!fAccessible) return B_NOT_ALLOWED; + if (path == NULL) { + // We want all of the entries for this signature removed. + status_t result = fApplications.RemoveName(signature); + if (result != B_OK) + return B_ENTRY_NOT_FOUND; + + fModified = true; + return B_OK; + } + int32 count; type_code type; if (fApplications.GetInfo(signature, &type, &count) != B_OK) From b31a707a95add749b375eb8f29fd294507ce3f42 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Tue, 7 Feb 2012 17:14:00 +0100 Subject: [PATCH 074/104] Implement the application enumeration and removal commands. --- src/servers/keystore/KeyStoreServer.cpp | 42 +++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/servers/keystore/KeyStoreServer.cpp b/src/servers/keystore/KeyStoreServer.cpp index f99f784cca..4d6c93b3c4 100644 --- a/src/servers/keystore/KeyStoreServer.cpp +++ b/src/servers/keystore/KeyStoreServer.cpp @@ -121,6 +121,8 @@ KeyStoreServer::MessageReceived(BMessage* message) case KEY_STORE_REVOKE_ACCESS: case KEY_STORE_ADD_KEYRING_TO_MASTER: case KEY_STORE_REMOVE_KEYRING_FROM_MASTER: + case KEY_STORE_GET_NEXT_APPLICATION: + case KEY_STORE_REMOVE_APPLICATION: { BString keyringName; if (message->FindString("keyring", &keyringName) != B_OK) @@ -140,6 +142,8 @@ KeyStoreServer::MessageReceived(BMessage* message) case KEY_STORE_ADD_KEY: case KEY_STORE_REMOVE_KEY: case KEY_STORE_ADD_KEYRING_TO_MASTER: + case KEY_STORE_GET_NEXT_APPLICATION: + case KEY_STORE_REMOVE_APPLICATION: { // These need keyring access to do anything. while (!keyring->IsAccessible()) { @@ -371,6 +375,44 @@ KeyStoreServer::MessageReceived(BMessage* message) break; } + case KEY_STORE_GET_NEXT_APPLICATION: + { + uint32 cookie; + if (message->FindUInt32("cookie", &cookie) != B_OK) { + result = B_BAD_VALUE; + break; + } + + BString signature; + BString path; + result = keyring->GetNextApplication(cookie, signature, path); + if (result != B_OK) + break; + + reply.AddUInt32("cookie", cookie); + reply.AddString("signature", signature); + reply.AddString("path", path); + result = B_OK; + break; + } + + case KEY_STORE_REMOVE_APPLICATION: + { + const char* signature = NULL; + const char* path = NULL; + + if (message->FindString("signature", &signature) != B_OK) { + result = B_BAD_VALUE; + break; + } + + if (message->FindString("path", &path) != B_OK) + path = NULL; + + result = keyring->RemoveApplication(signature, path); + break; + } + case 0: { // Just the error case from above. From f17ddab827e51367e570e06d671752d1e3b4b2ac Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sun, 24 Jun 2012 00:31:10 +0200 Subject: [PATCH 075/104] Initialize the BKey to default values and set fCreationTime. * Using Unset() initializes the BKey to default values. * Also set fCreationTime to 0 for now. It is still unused but needs to have a stable value for the exact matches when comparing keys. --- src/kits/app/Key.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/kits/app/Key.cpp b/src/kits/app/Key.cpp index a9d8d16e9e..ffe5374c30 100644 --- a/src/kits/app/Key.cpp +++ b/src/kits/app/Key.cpp @@ -32,6 +32,7 @@ CompareLists(BObjectList a, BObjectList b) BKey::BKey() { + Unset(); } @@ -44,6 +45,7 @@ BKey::BKey(BKeyPurpose purpose, const char* identifier, BKey::BKey(BKey& other) { + *this = other; } @@ -63,6 +65,7 @@ status_t BKey::SetTo(BKeyPurpose purpose, const char* identifier, const char* secondaryIdentifier, const uint8* data, size_t length) { + fCreationTime = 0; SetPurpose(purpose); SetIdentifier(identifier); SetSecondaryIdentifier(secondaryIdentifier); From c8ae843f3dcba6c16eda5d2b5db1f981ee69f448 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sun, 24 Jun 2012 14:37:27 +0200 Subject: [PATCH 076/104] Rename keyring "access/revoke" to "unlock/lock". The unlock/lock concept just seems easier to grasp and is used in various similar tools as well. --- headers/os/app/KeyStore.h | 8 ++-- headers/private/app/KeyStoreDefs.h | 4 +- src/bin/keystore/keystore.cpp | 22 +++++----- src/kits/app/KeyStore.cpp | 20 ++++----- src/servers/keystore/KeyStoreServer.cpp | 55 ++++++++++++------------- src/servers/keystore/KeyStoreServer.h | 2 +- src/servers/keystore/Keyring.cpp | 34 +++++++-------- src/servers/keystore/Keyring.h | 8 ++-- 8 files changed, 76 insertions(+), 77 deletions(-) diff --git a/headers/os/app/KeyStore.h b/headers/os/app/KeyStore.h index 7af178fbf8..aae65f111f 100644 --- a/headers/os/app/KeyStore.h +++ b/headers/os/app/KeyStore.h @@ -71,11 +71,11 @@ public: status_t GetNextMasterKeyring(uint32& cookie, BString& keyring); - // Access + // Locking - bool IsKeyringAccessible(const char* keyring); - status_t RevokeAccess(const char* keyring); - status_t RevokeMasterAccess(); + bool IsKeyringUnlocked(const char* keyring); + status_t LockKeyring(const char* keyring); + status_t LockMasterKeyring(); // Applications diff --git a/headers/private/app/KeyStoreDefs.h b/headers/private/app/KeyStoreDefs.h index 315944c18c..257a35275d 100644 --- a/headers/private/app/KeyStoreDefs.h +++ b/headers/private/app/KeyStoreDefs.h @@ -35,8 +35,8 @@ enum { KEY_STORE_ADD_KEYRING_TO_MASTER = 'KarM', KEY_STORE_REMOVE_KEYRING_FROM_MASTER = 'KrrM', KEY_STORE_GET_NEXT_MASTER_KEYRING = 'KnrM', - KEY_STORE_IS_KEYRING_ACCESSIBLE = 'KiaR', - KEY_STORE_REVOKE_ACCESS = 'KvaR', + KEY_STORE_IS_KEYRING_UNLOCKED = 'KuKR', + KEY_STORE_LOCK_KEYRING = 'KlKR', KEY_STORE_GET_NEXT_APPLICATION = 'KnKA', KEY_STORE_REMOVE_APPLICATION = 'KrKA', }; diff --git a/src/bin/keystore/keystore.cpp b/src/bin/keystore/keystore.cpp index 2dd66cddf3..5445f5dbb3 100644 --- a/src/bin/keystore/keystore.cpp +++ b/src/bin/keystore/keystore.cpp @@ -140,19 +140,19 @@ int show_status(const char* keyring) { BKeyStore keyStore; - printf("keyring \"%s\" is %saccessible\n", keyring, - keyStore.IsKeyringAccessible(keyring) ? "" : "not "); + printf("keyring \"%s\" is %slocked\n", keyring, + keyStore.IsKeyringUnlocked(keyring) ? "un" : ""); return 0; } int -revoke_access(const char* keyring) +lock_keyring(const char* keyring) { BKeyStore keyStore; - status_t result = keyStore.RevokeAccess(keyring); + status_t result = keyStore.LockKeyring(keyring); if (result != B_OK) { - printf("failed to revoke access to keyring \"%s\": %s\n", keyring, + printf("failed to lock keyring \"%s\": %s\n", keyring, strerror(result)); return 2; } @@ -222,12 +222,12 @@ print_usage(const char* name) printf("\t\tRemoves the specified keyring.\n\n"); printf("\t%s status []\n", name); - printf("\t\tShows the access status of the specified keyring, or the" + printf("\t\tShows the lock state of the specified keyring, or the" " default keyring if none is supplied.\n\n"); - printf("\t%s revoke []\n", name); - printf("\t\tRevoke access to the specified keyring, or to the default" - " keyring if none is supplied.\n\n"); + printf("\t%s lock []\n", name); + printf("\t\tLock the specified keyring, or the default keyring if none is" + " supplied.\n\n"); printf("\t%s master add \n", name); printf("\t\tAdd the access key for the specified keyring to the default" @@ -333,11 +333,11 @@ main(int argc, char* argv[]) return print_usage(argv[0]); return show_status(argc == 3 ? argv[2] : ""); - } else if (strcmp(argv[1], "revoke") == 0) { + } else if (strcmp(argv[1], "lock") == 0) { if (argc != 2 && argc != 3) return print_usage(argv[0]); - return revoke_access(argc == 3 ? argv[2] : ""); + return lock_keyring(argc == 3 ? argv[2] : ""); } else if (strcmp(argv[1], "master") == 0) { if (argc != 4) return print_usage(argv[0]); diff --git a/src/kits/app/KeyStore.cpp b/src/kits/app/KeyStore.cpp index 64cca00cf8..f0f7de71c7 100644 --- a/src/kits/app/KeyStore.cpp +++ b/src/kits/app/KeyStore.cpp @@ -291,40 +291,40 @@ BKeyStore::GetNextMasterKeyring(uint32& cookie, BString& keyring) } -// #pragma mark - Access +// #pragma mark - Locking bool -BKeyStore::IsKeyringAccessible(const char* keyring) +BKeyStore::IsKeyringUnlocked(const char* keyring) { - BMessage message(KEY_STORE_IS_KEYRING_ACCESSIBLE); + BMessage message(KEY_STORE_IS_KEYRING_UNLOCKED); message.AddString("keyring", keyring); BMessage reply; if (_SendKeyMessage(message, &reply) != B_OK) return false; - bool accessible; - if (reply.FindBool("accessible", &accessible) != B_OK) + bool unlocked; + if (reply.FindBool("unlocked", &unlocked) != B_OK) return false; - return accessible; + return unlocked; } status_t -BKeyStore::RevokeAccess(const char* keyring) +BKeyStore::LockKeyring(const char* keyring) { - BMessage message(KEY_STORE_REVOKE_ACCESS); + BMessage message(KEY_STORE_LOCK_KEYRING); message.AddString("keyring", keyring); return _SendKeyMessage(message, NULL); } status_t -BKeyStore::RevokeMasterAccess() +BKeyStore::LockMasterKeyring() { - return RevokeAccess(NULL); + return LockKeyring(NULL); } diff --git a/src/servers/keystore/KeyStoreServer.cpp b/src/servers/keystore/KeyStoreServer.cpp index 4d6c93b3c4..fee00271c8 100644 --- a/src/servers/keystore/KeyStoreServer.cpp +++ b/src/servers/keystore/KeyStoreServer.cpp @@ -41,8 +41,8 @@ static const uint32 kFlagRemoveMasterKey = 0x0100; static const uint32 kFlagAddKeyringsToMaster = 0x0200; static const uint32 kFlagRemoveKeyringsFromMaster = 0x0400; static const uint32 kFlagEnumerateMasterKeyrings = 0x0800; -static const uint32 kFlagQueryAccessibility = 0x1000; -static const uint32 kFlagRevokeAccess = 0x2000; +static const uint32 kFlagQueryLockState = 0x1000; +static const uint32 kFlagLockKeyring = 0x2000; static const uint32 kFlagEnumerateApplications = 0x4000; static const uint32 kFlagRemoveApplications = 0x8000; @@ -50,9 +50,8 @@ static const uint32 kDefaultAppFlags = kFlagGetKey | kFlagEnumerateKeys | kFlagAddKey | kFlagRemoveKey | kFlagAddKeyring | kFlagRemoveKeyring | kFlagEnumerateKeyrings | kFlagSetMasterKey | kFlagRemoveMasterKey | kFlagAddKeyringsToMaster | kFlagRemoveKeyringsFromMaster - | kFlagEnumerateMasterKeyrings | kFlagQueryAccessibility - | kFlagQueryAccessibility | kFlagRevokeAccess | kFlagEnumerateApplications - | kFlagRemoveApplications; + | kFlagEnumerateMasterKeyrings | kFlagQueryLockState | kFlagLockKeyring + | kFlagEnumerateApplications | kFlagRemoveApplications; KeyStoreServer::KeyStoreServer() @@ -117,8 +116,8 @@ KeyStoreServer::MessageReceived(BMessage* message) case KEY_STORE_GET_NEXT_KEY: case KEY_STORE_ADD_KEY: case KEY_STORE_REMOVE_KEY: - case KEY_STORE_IS_KEYRING_ACCESSIBLE: - case KEY_STORE_REVOKE_ACCESS: + case KEY_STORE_IS_KEYRING_UNLOCKED: + case KEY_STORE_LOCK_KEYRING: case KEY_STORE_ADD_KEYRING_TO_MASTER: case KEY_STORE_REMOVE_KEYRING_FROM_MASTER: case KEY_STORE_GET_NEXT_APPLICATION: @@ -146,10 +145,10 @@ KeyStoreServer::MessageReceived(BMessage* message) case KEY_STORE_REMOVE_APPLICATION: { // These need keyring access to do anything. - while (!keyring->IsAccessible()) { - status_t accessResult = _AccessKeyring(*keyring); - if (accessResult != B_OK) { - result = accessResult; + while (!keyring->IsUnlocked()) { + status_t unlockResult = _UnlockKeyring(*keyring); + if (unlockResult != B_OK) { + result = unlockResult; message->what = 0; break; } @@ -320,16 +319,16 @@ KeyStoreServer::MessageReceived(BMessage* message) break; } - case KEY_STORE_IS_KEYRING_ACCESSIBLE: + case KEY_STORE_IS_KEYRING_UNLOCKED: { - reply.AddBool("accessible", keyring->IsAccessible()); + reply.AddBool("unlocked", keyring->IsUnlocked()); result = B_OK; break; } - case KEY_STORE_REVOKE_ACCESS: + case KEY_STORE_LOCK_KEYRING: { - keyring->RevokeAccess(); + keyring->Lock(); result = B_OK; break; } @@ -338,10 +337,10 @@ KeyStoreServer::MessageReceived(BMessage* message) case KEY_STORE_REMOVE_KEYRING_FROM_MASTER: { // We also need access to the default keyring. - while (!fDefaultKeyring->IsAccessible()) { - status_t accessResult = _AccessKeyring(*fDefaultKeyring); - if (accessResult != B_OK) { - result = accessResult; + while (!fDefaultKeyring->IsUnlocked()) { + status_t unlockResult = _UnlockKeyring(*fDefaultKeyring); + if (unlockResult != B_OK) { + result = unlockResult; message->what = 0; break; } @@ -528,10 +527,10 @@ KeyStoreServer::_AccessFlagsFor(uint32 command) const return kFlagRemoveKeyringsFromMaster; case KEY_STORE_GET_NEXT_MASTER_KEYRING: return kFlagEnumerateMasterKeyrings; - case KEY_STORE_IS_KEYRING_ACCESSIBLE: - return kFlagQueryAccessibility; - case KEY_STORE_REVOKE_ACCESS: - return kFlagRevokeAccess; + case KEY_STORE_IS_KEYRING_UNLOCKED: + return kFlagQueryLockState; + case KEY_STORE_LOCK_KEYRING: + return kFlagLockKeyring; case KEY_STORE_GET_NEXT_APPLICATION: return kFlagEnumerateApplications; case KEY_STORE_REMOVE_APPLICATION: @@ -673,16 +672,16 @@ KeyStoreServer::_RemoveKeyring(const BString& name) status_t -KeyStoreServer::_AccessKeyring(Keyring& keyring) +KeyStoreServer::_UnlockKeyring(Keyring& keyring) { // If we are accessing a keyring that has been added to master access we // get the key from the default keyring and unlock with that. BMessage keyMessage; - if (&keyring != fDefaultKeyring && fDefaultKeyring->IsAccessible()) { + if (&keyring != fDefaultKeyring && fDefaultKeyring->IsUnlocked()) { if (fDefaultKeyring->FindKey(kKeyringKeysIdentifier, keyring.Name(), false, &keyMessage) == B_OK) { - // We found a key for this keyring, try to access with it. - if (keyring.Access(keyMessage) == B_OK) + // We found a key for this keyring, try to unlock with it. + if (keyring.Unlock(keyMessage) == B_OK) return B_OK; } } @@ -692,7 +691,7 @@ KeyStoreServer::_AccessKeyring(Keyring& keyring) if (result != B_OK) return result; - return keyring.Access(keyMessage); + return keyring.Unlock(keyMessage); } diff --git a/src/servers/keystore/KeyStoreServer.h b/src/servers/keystore/KeyStoreServer.h index 0490a7da6a..01e73a80cd 100644 --- a/src/servers/keystore/KeyStoreServer.h +++ b/src/servers/keystore/KeyStoreServer.h @@ -49,7 +49,7 @@ private: const BMessage& keyMessage); status_t _RemoveKeyring(const BString& name); - status_t _AccessKeyring(Keyring& keyring); + status_t _UnlockKeyring(Keyring& keyring); status_t _RequestKey(const BString& keyringName, BMessage& keyMessage); diff --git a/src/servers/keystore/Keyring.cpp b/src/servers/keystore/Keyring.cpp index 4f705785ce..eff7c0051a 100644 --- a/src/servers/keystore/Keyring.cpp +++ b/src/servers/keystore/Keyring.cpp @@ -10,11 +10,11 @@ Keyring::Keyring(const char* name, const BMessage* keyMessage) : fName(name), - fAccessible(false), + fUnlocked(false), fModified(false) { if (keyMessage != NULL) - Access(*keyMessage); + Unlock(*keyMessage); } @@ -59,7 +59,7 @@ Keyring::WriteToMessage(BMessage& message) status_t -Keyring::Access(const BMessage& keyMessage) +Keyring::Unlock(const BMessage& keyMessage) { fKeyMessage = keyMessage; @@ -69,15 +69,15 @@ Keyring::Access(const BMessage& keyMessage) return result; } - fAccessible = true; + fUnlocked = true; return B_OK; } void -Keyring::RevokeAccess() +Keyring::Lock() { - if (!fAccessible) + if (!fUnlocked) return; _EncryptToFlatBuffer(); @@ -85,14 +85,14 @@ Keyring::RevokeAccess() fKeyMessage.MakeEmpty(); fData.MakeEmpty(); fApplications.MakeEmpty(); - fAccessible = false; + fUnlocked = false; } bool -Keyring::IsAccessible() const +Keyring::IsUnlocked() const { - return fAccessible; + return fUnlocked; } @@ -131,7 +131,7 @@ status_t Keyring::FindApplication(const char* signature, const char* path, BMessage& appMessage) { - if (!fAccessible) + if (!fUnlocked) return B_NOT_ALLOWED; int32 count; @@ -159,7 +159,7 @@ Keyring::FindApplication(const char* signature, const char* path, status_t Keyring::AddApplication(const char* signature, const BMessage& appMessage) { - if (!fAccessible) + if (!fUnlocked) return B_NOT_ALLOWED; status_t result = fApplications.AddMessage(signature, &appMessage); @@ -174,7 +174,7 @@ Keyring::AddApplication(const char* signature, const BMessage& appMessage) status_t Keyring::RemoveApplication(const char* signature, const char* path) { - if (!fAccessible) + if (!fUnlocked) return B_NOT_ALLOWED; if (path == NULL) { @@ -216,7 +216,7 @@ status_t Keyring::FindKey(const BString& identifier, const BString& secondaryIdentifier, bool secondaryIdentifierOptional, BMessage* _foundKeyMessage) const { - if (!fAccessible) + if (!fUnlocked) return B_NOT_ALLOWED; int32 count; @@ -262,7 +262,7 @@ status_t Keyring::FindKey(BKeyType type, BKeyPurpose purpose, uint32 index, BMessage& _foundKeyMessage) const { - if (!fAccessible) + if (!fUnlocked) return B_NOT_ALLOWED; for (int32 keyIndex = 0;; keyIndex++) { @@ -327,7 +327,7 @@ status_t Keyring::AddKey(const BString& identifier, const BString& secondaryIdentifier, const BMessage& keyMessage) { - if (!fAccessible) + if (!fUnlocked) return B_NOT_ALLOWED; // Check for collisions. @@ -348,7 +348,7 @@ status_t Keyring::RemoveKey(const BString& identifier, const BMessage& keyMessage) { - if (!fAccessible) + if (!fUnlocked) return B_NOT_ALLOWED; int32 count; @@ -397,7 +397,7 @@ Keyring::_EncryptToFlatBuffer() if (!fModified) return B_OK; - if (!fAccessible) + if (!fUnlocked) return B_NOT_ALLOWED; BMessage container; diff --git a/src/servers/keystore/Keyring.h b/src/servers/keystore/Keyring.h index b5381f29f5..afbca03b14 100644 --- a/src/servers/keystore/Keyring.h +++ b/src/servers/keystore/Keyring.h @@ -20,9 +20,9 @@ public: status_t ReadFromMessage(const BMessage& message); status_t WriteToMessage(BMessage& message); - status_t Access(const BMessage& keyMessage); - void RevokeAccess(); - bool IsAccessible() const; + status_t Unlock(const BMessage& keyMessage); + void Lock(); + bool IsUnlocked() const; const BMessage& KeyMessage() const; status_t GetNextApplication(uint32& cookie, @@ -62,7 +62,7 @@ private: BMessage fData; BMessage fApplications; BMessage fKeyMessage; - bool fAccessible; + bool fUnlocked; bool fModified; }; From a5a5f4ca70b67a24c1a0666b8bde040748e0c3ae Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sun, 24 Jun 2012 14:48:45 +0200 Subject: [PATCH 077/104] Rename "default" to "master" keyring as that's what it is. Also add a well defined name ("Master") for the master keyring so it is easier to understand what this keyring does instead of displaying an empty string. --- src/bin/keystore/keystore.cpp | 18 +++++------ src/servers/keystore/KeyStoreServer.cpp | 41 +++++++++++++------------ src/servers/keystore/KeyStoreServer.h | 2 +- 3 files changed, 31 insertions(+), 30 deletions(-) diff --git a/src/bin/keystore/keystore.cpp b/src/bin/keystore/keystore.cpp index 5445f5dbb3..9699cf4c28 100644 --- a/src/bin/keystore/keystore.cpp +++ b/src/bin/keystore/keystore.cpp @@ -196,20 +196,20 @@ print_usage(const char* name) { printf("usage:\n"); printf("\t%s list passwords []\n", name); - printf("\t\tLists all accessible passwords from the specified keyring or" - " from the default keyring if none is supplied.\n"); + printf("\t\tLists all passwords of the specified keyring or from the" + " master keyring if none is supplied.\n"); printf("\t%s list keyrings\n", name); - printf("\t\tLists all accessible keyrings.\n\n"); + printf("\t\tLists all keyrings.\n\n"); printf("\t%s add password [] " "\n", name); - printf("\t\tAdds the specified password to the default keyring.\n"); + printf("\t\tAdds the specified password to the master keyring.\n"); printf("\t%s add password to []" " \n", name); printf("\t\tAdds the specified password to the specified keyring.\n\n"); printf("\t%s remove password []\n", name); - printf("\t\tRemoves the specified password from the default keyring.\n"); + printf("\t\tRemoves the specified password from the master keyring.\n"); printf("\t%s remove password from " " []\n", name); printf("\t\tRemoves the specified password from the specified keyring.\n\n"); @@ -223,19 +223,19 @@ print_usage(const char* name) printf("\t%s status []\n", name); printf("\t\tShows the lock state of the specified keyring, or the" - " default keyring if none is supplied.\n\n"); + " master keyring if none is supplied.\n\n"); printf("\t%s lock []\n", name); - printf("\t\tLock the specified keyring, or the default keyring if none is" + printf("\t\tLock the specified keyring, or the master keyring if none is" " supplied.\n\n"); printf("\t%s master add \n", name); - printf("\t\tAdd the access key for the specified keyring to the default" + printf("\t\tAdd the access key for the specified keyring to the master" " keyring.\n"); printf("\t%s master remove \n", name); printf("\t\tRemove the access key for the specified keyring from the" - " default keyring.\n"); + " master keyring.\n\n"); return 1; } diff --git a/src/servers/keystore/KeyStoreServer.cpp b/src/servers/keystore/KeyStoreServer.cpp index fee00271c8..27b1076f6b 100644 --- a/src/servers/keystore/KeyStoreServer.cpp +++ b/src/servers/keystore/KeyStoreServer.cpp @@ -27,6 +27,7 @@ using namespace BPrivate; +static const char* kMasterKeyringName = "Master"; static const char* kKeyringKeysIdentifier = "Keyrings"; static const uint32 kFlagGetKey = 0x0001; @@ -57,7 +58,7 @@ static const uint32 kDefaultAppFlags = kFlagGetKey | kFlagEnumerateKeys KeyStoreServer::KeyStoreServer() : BApplication(kKeyStoreServerSignature), - fDefaultKeyring(NULL), + fMasterKeyring(NULL), fKeyrings(20, true) { BPath path; @@ -82,8 +83,8 @@ KeyStoreServer::KeyStoreServer() _ReadKeyStoreDatabase(); - if (fDefaultKeyring == NULL) - fDefaultKeyring = new(std::nothrow) Keyring(""); + if (fMasterKeyring == NULL) + fMasterKeyring = new(std::nothrow) Keyring(kMasterKeyringName); } @@ -303,7 +304,7 @@ KeyStoreServer::MessageReceived(BMessage* message) } if (cookie == 0) - keyring = fDefaultKeyring; + keyring = fMasterKeyring; else keyring = fKeyrings.ItemAt(cookie - 1); @@ -336,9 +337,9 @@ KeyStoreServer::MessageReceived(BMessage* message) case KEY_STORE_ADD_KEYRING_TO_MASTER: case KEY_STORE_REMOVE_KEYRING_FROM_MASTER: { - // We also need access to the default keyring. - while (!fDefaultKeyring->IsUnlocked()) { - status_t unlockResult = _UnlockKeyring(*fDefaultKeyring); + // We also need access to the master keyring. + while (!fMasterKeyring->IsUnlocked()) { + status_t unlockResult = _UnlockKeyring(*fMasterKeyring); if (unlockResult != B_OK) { result = unlockResult; message->what = 0; @@ -358,12 +359,12 @@ KeyStoreServer::MessageReceived(BMessage* message) switch (message->what) { case KEY_STORE_ADD_KEYRING_TO_MASTER: - result = fDefaultKeyring->AddKey(kKeyringKeysIdentifier, + result = fMasterKeyring->AddKey(kKeyringKeysIdentifier, secondaryIdentifier, keyMessage); break; case KEY_STORE_REMOVE_KEYRING_FROM_MASTER: - result = fDefaultKeyring->RemoveKey(kKeyringKeysIdentifier, + result = fMasterKeyring->RemoveKey(kKeyringKeysIdentifier, keyMessage); break; } @@ -466,8 +467,8 @@ KeyStoreServer::_ReadKeyStoreDatabase() continue; } - if (strlen(keyringName) == 0) - fDefaultKeyring = keyring; + if (strcmp(keyringName, kMasterKeyringName) == 0) + fMasterKeyring = keyring; else fKeyrings.BinaryInsert(keyring, &Keyring::Compare); } @@ -480,8 +481,8 @@ status_t KeyStoreServer::_WriteKeyStoreDatabase() { BMessage keyrings; - if (fDefaultKeyring != NULL) - fDefaultKeyring->WriteToMessage(keyrings); + if (fMasterKeyring != NULL) + fMasterKeyring->WriteToMessage(keyrings); for (int32 i = 0; i < fKeyrings.CountItems(); i++) { Keyring* keyring = fKeyrings.ItemAt(i); @@ -629,8 +630,8 @@ KeyStoreServer::_RequestAppAccess(const BString& keyringName, Keyring* KeyStoreServer::_FindKeyring(const BString& name) { - if (name.IsEmpty()) - return fDefaultKeyring; + if (name.IsEmpty() || name == kMasterKeyringName) + return fMasterKeyring; return fKeyrings.BinarySearchByKey(name, &Keyring::Compare); } @@ -662,8 +663,8 @@ KeyStoreServer::_RemoveKeyring(const BString& name) if (keyring == NULL) return B_ENTRY_NOT_FOUND; - if (keyring == fDefaultKeyring) { - // The default keyring can't be removed. + if (keyring == fMasterKeyring) { + // The master keyring can't be removed. return B_NOT_ALLOWED; } @@ -675,10 +676,10 @@ status_t KeyStoreServer::_UnlockKeyring(Keyring& keyring) { // If we are accessing a keyring that has been added to master access we - // get the key from the default keyring and unlock with that. + // get the key from the master keyring and unlock with that. BMessage keyMessage; - if (&keyring != fDefaultKeyring && fDefaultKeyring->IsUnlocked()) { - if (fDefaultKeyring->FindKey(kKeyringKeysIdentifier, keyring.Name(), + if (&keyring != fMasterKeyring && fMasterKeyring->IsUnlocked()) { + if (fMasterKeyring->FindKey(kKeyringKeysIdentifier, keyring.Name(), false, &keyMessage) == B_OK) { // We found a key for this keyring, try to unlock with it. if (keyring.Unlock(keyMessage) == B_OK) diff --git a/src/servers/keystore/KeyStoreServer.h b/src/servers/keystore/KeyStoreServer.h index 01e73a80cd..30e607870b 100644 --- a/src/servers/keystore/KeyStoreServer.h +++ b/src/servers/keystore/KeyStoreServer.h @@ -54,7 +54,7 @@ private: status_t _RequestKey(const BString& keyringName, BMessage& keyMessage); - Keyring* fDefaultKeyring; + Keyring* fMasterKeyring; KeyringList fKeyrings; BFile fKeyStoreFile; }; From f8ccc323268f9ad9f2925d06ac5bf281395ca26a Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sun, 24 Jun 2012 14:53:07 +0200 Subject: [PATCH 078/104] Remove the API part of the concept of apps per key. The application access concept is on the keyring level only for now. Generally it probably would get pretty complicated and therefore harder to use when application access needs to be granted on a per key basis. --- headers/os/app/KeyStore.h | 12 +++++------- src/kits/app/KeyStore.cpp | 26 +++++++------------------- 2 files changed, 12 insertions(+), 26 deletions(-) diff --git a/headers/os/app/KeyStore.h b/headers/os/app/KeyStore.h index aae65f111f..0d30390d4b 100644 --- a/headers/os/app/KeyStore.h +++ b/headers/os/app/KeyStore.h @@ -79,15 +79,13 @@ public: // Applications - status_t GetNextApplication(const BKey& key, - uint32& cookie, BString& signature) const; - status_t GetNextApplication(const char* keyring, - const BKey& key, uint32& cookie, + status_t GetNextApplication(uint32& cookie, BString& signature) const; - status_t RemoveApplication(const BKey& key, - const char* signature); + status_t GetNextApplication(const char* keyring, + uint32& cookie, BString& signature) const; + status_t RemoveApplication(const char* signature); status_t RemoveApplication(const char* keyring, - const BKey& key, const char* signature); + const char* signature); // Service functions diff --git a/src/kits/app/KeyStore.cpp b/src/kits/app/KeyStore.cpp index f0f7de71c7..9b616bb305 100644 --- a/src/kits/app/KeyStore.cpp +++ b/src/kits/app/KeyStore.cpp @@ -333,24 +333,18 @@ BKeyStore::LockMasterKeyring() status_t -BKeyStore::GetNextApplication(const BKey& key, uint32& cookie, - BString& signature) const +BKeyStore::GetNextApplication(uint32& cookie, BString& signature) const { - return GetNextApplication(NULL, key, cookie, signature); + return GetNextApplication(NULL, cookie, signature); } status_t -BKeyStore::GetNextApplication(const char* keyring, const BKey& key, - uint32& cookie, BString& signature) const +BKeyStore::GetNextApplication(const char* keyring, uint32& cookie, + BString& signature) const { - BMessage keyMessage; - if (key.Flatten(keyMessage) != B_OK) - return B_BAD_VALUE; - BMessage message(KEY_STORE_GET_NEXT_APPLICATION); message.AddString("keyring", keyring); - message.AddMessage("key", &keyMessage); message.AddUInt32("cookie", cookie); BMessage reply; @@ -367,23 +361,17 @@ BKeyStore::GetNextApplication(const char* keyring, const BKey& key, status_t -BKeyStore::RemoveApplication(const BKey& key, const char* signature) +BKeyStore::RemoveApplication(const char* signature) { - return RemoveApplication(NULL, key, signature); + return RemoveApplication(NULL, signature); } status_t -BKeyStore::RemoveApplication(const char* keyring, const BKey& key, - const char* signature) +BKeyStore::RemoveApplication(const char* keyring, const char* signature) { - BMessage keyMessage; - if (key.Flatten(keyMessage) != B_OK) - return B_BAD_VALUE; - BMessage message(KEY_STORE_REMOVE_APPLICATION); message.AddString("keyring", keyring); - message.AddMessage("key", &keyMessage); message.AddString("signature", signature); return _SendKeyMessage(message, NULL); From 03a84249b537ecfe55fee6a35c0d0557235ce405 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sun, 24 Jun 2012 14:56:35 +0200 Subject: [PATCH 079/104] Add app enumeration and removal to the keystore cli tool. --- src/bin/keystore/keystore.cpp | 68 +++++++++++++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 3 deletions(-) diff --git a/src/bin/keystore/keystore.cpp b/src/bin/keystore/keystore.cpp index 9699cf4c28..865f433a98 100644 --- a/src/bin/keystore/keystore.cpp +++ b/src/bin/keystore/keystore.cpp @@ -191,6 +191,46 @@ remove_keyring_from_master(const char* keyring) } +int +list_applications(const char* keyring) +{ + BKeyStore keyStore; + uint32 cookie = 0; + + while (true) { + BString signature; + status_t result = keyStore.GetNextApplication(keyring, + cookie, signature); + if (result == B_ENTRY_NOT_FOUND) + break; + + if (result != B_OK) { + printf("failed to get next application: %s\n", strerror(result)); + return 2; + } + + printf("application: \"%s\"\n", signature.String()); + } + + return 0; +} + + +int +remove_application(const char* keyring, const char* signature) +{ + BKeyStore keyStore; + + status_t result = keyStore.RemoveApplication(keyring, signature); + if (result != B_OK) { + printf("failed to remove application: %s\n", strerror(result)); + return 3; + } + + return 0; +} + + int print_usage(const char* name) { @@ -199,7 +239,10 @@ print_usage(const char* name) printf("\t\tLists all passwords of the specified keyring or from the" " master keyring if none is supplied.\n"); printf("\t%s list keyrings\n", name); - printf("\t\tLists all keyrings.\n\n"); + printf("\t\tLists all keyrings.\n"); + printf("\t%s list applications []\n", name); + printf("\t\tLists the applications that have been granted permanent access" + " to a keyring once it is unlocked.\n\n"); printf("\t%s add password [] " "\n", name); @@ -216,8 +259,7 @@ print_usage(const char* name) printf("\t%s add keyring \n", name); printf("\t\tAdds a new keyring with the specified name, protected by the" - " supplied password.\n\n"); - + " supplied password.\n"); printf("\t%s remove keyring \n", name); printf("\t\tRemoves the specified keyring.\n\n"); @@ -237,6 +279,13 @@ print_usage(const char* name) printf("\t\tRemove the access key for the specified keyring from the" " master keyring.\n\n"); + printf("\t%s remove application \n", name); + printf("\t\tRemove permanent access for the application with the given" + " signature from the master keyring.\n"); + printf("\t%s remove application from \n", name); + printf("\t\tRemove permanent access for the application with the given" + " signature from the specified keyring.\n"); + return 1; } @@ -257,6 +306,8 @@ main(int argc, char* argv[]) return list_passwords(argc > 3 ? argv[3] : NULL); if (strcmp(argv[2], "keyrings") == 0) return list_keyrings(); + if (strcmp(argv[2], "applications") == 0) + return list_applications(argc > 3 ? argv[3] : NULL); } else if (strcmp(argv[1], "add") == 0) { if (argc < 3) return print_usage(argv[0]); @@ -327,6 +378,17 @@ main(int argc, char* argv[]) } else if (strcmp(argv[2], "keyring") == 0) { if (argc == 4) return remove_keyring(argv[3]); + } else if (strcmp(argv[2], "application") == 0) { + const char* keyring = NULL; + const char* signature = NULL; + if (argc == 6 && strcmp(argv[3], "from") == 0) { + keyring = argv[4]; + signature = argv[5]; + } else if (argc == 4) + signature = argv[3]; + + if (signature != NULL) + return remove_application(keyring, signature); } } else if (strcmp(argv[1], "status") == 0) { if (argc != 2 && argc != 3) From 82b425a59f7318911d012f281ba8e9a4f70e8a82 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sun, 24 Jun 2012 14:57:51 +0200 Subject: [PATCH 080/104] Reword the label from "Always Allow" to "Allow Always". --- src/servers/keystore/AppAccessRequestWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/servers/keystore/AppAccessRequestWindow.cpp b/src/servers/keystore/AppAccessRequestWindow.cpp index 8c7a8df61d..b7ce8b625e 100644 --- a/src/servers/keystore/AppAccessRequestWindow.cpp +++ b/src/servers/keystore/AppAccessRequestWindow.cpp @@ -80,7 +80,7 @@ public: new BMessage(kMessageOnce)); buttons->GroupLayout()->AddView(fOnceButton); - fAlwaysButton = new(std::nothrow) BButton("Always Allow", + fAlwaysButton = new(std::nothrow) BButton("Allow Always", new BMessage(kMessageAlways)); buttons->GroupLayout()->AddView(fAlwaysButton); From 7b437e50eb14a7fb7cfdfa3bc212ad894904fd66 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sun, 24 Jun 2012 15:02:50 +0200 Subject: [PATCH 081/104] Reflect "access" -> "unlock" change in key request dialog. --- src/servers/keystore/KeyRequestWindow.cpp | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/servers/keystore/KeyRequestWindow.cpp b/src/servers/keystore/KeyRequestWindow.cpp index f8c7ecf1c5..81035aa595 100644 --- a/src/servers/keystore/KeyRequestWindow.cpp +++ b/src/servers/keystore/KeyRequestWindow.cpp @@ -25,7 +25,7 @@ static const uint32 kMessageCancel = 'btcl'; -static const uint32 kMessageOk = 'btok'; +static const uint32 kMessageUnlock = 'btul'; class KeyRequestView : public BView { @@ -88,8 +88,9 @@ public: buttons->GroupLayout()->AddItem(BSpaceLayoutItem::CreateGlue()); - fOkButton = new(std::nothrow) BButton("OK", new BMessage(kMessageOk)); - buttons->GroupLayout()->AddView(fOkButton); + fUnlockButton = new(std::nothrow) BButton("Unlock", + new BMessage(kMessageUnlock)); + buttons->GroupLayout()->AddView(fUnlockButton); rootLayout->AddView(controls); rootLayout->AddView(buttons); @@ -99,8 +100,8 @@ public: AttachedToWindow() { fCancelButton->SetTarget(Window()); - fOkButton->SetTarget(Window()); - fOkButton->MakeDefault(true); + fUnlockButton->SetTarget(Window()); + fUnlockButton->MakeDefault(true); } void @@ -121,20 +122,20 @@ private: BTextControl* fPassword; BCheckBox* fPersist; BButton* fCancelButton; - BButton* fOkButton; + BButton* fUnlockButton; }; KeyRequestWindow::KeyRequestWindow() : - BWindow(BRect(50, 50, 269, 302), "Access Keyring", + BWindow(BRect(50, 50, 269, 302), "Unlock Keyring", B_TITLED_WINDOW, B_NOT_RESIZABLE | B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE | B_AUTO_UPDATE_SIZE_LIMITS), fRequestView(NULL), fDoneSem(-1), fResult(B_ERROR) { - fDoneSem = create_sem(0, "keyring access dialog"); + fDoneSem = create_sem(0, "keyring unlock dialog"); if (fDoneSem < 0) return; @@ -178,8 +179,8 @@ KeyRequestWindow::MessageReceived(BMessage* message) { switch (message->what) { case kMessageCancel: - case kMessageOk: - fResult = message->what == kMessageOk ? B_OK : B_CANCELED; + case kMessageUnlock: + fResult = message->what == kMessageUnlock ? B_OK : B_CANCELED; release_sem(fDoneSem); return; } From f1f719c433de2853888a2ee0c95114505a2f68d8 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sun, 24 Jun 2012 15:05:27 +0200 Subject: [PATCH 082/104] Make the keyring label and name StringViews. --- src/servers/keystore/KeyRequestWindow.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/servers/keystore/KeyRequestWindow.cpp b/src/servers/keystore/KeyRequestWindow.cpp index 81035aa595..4ebaf2b14e 100644 --- a/src/servers/keystore/KeyRequestWindow.cpp +++ b/src/servers/keystore/KeyRequestWindow.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -54,13 +55,19 @@ public: rootLayout->SetSpacing(inset); layout->SetSpacing(inset, inset); - fKeyringName = new(std::nothrow) BTextControl("Keyring:", "", NULL); - if (fKeyringName == NULL) + BStringView* label = new(std::nothrow) BStringView("keyringLabel", + "Keyring:"); + if (label == NULL) return; int32 row = 0; - layout->AddItem(fKeyringName->CreateLabelLayoutItem(), 0, row); - layout->AddItem(fKeyringName->CreateTextViewLayoutItem(), 1, row++); + 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("Password:", "", NULL); if (fPassword == NULL) @@ -118,7 +125,7 @@ public: } private: - BTextControl* fKeyringName; + BStringView* fKeyringName; BTextControl* fPassword; BCheckBox* fPersist; BButton* fCancelButton; From 7306e9e4d5af80508cd66f5d5f07d5faea2698fb Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sun, 24 Jun 2012 15:05:58 +0200 Subject: [PATCH 083/104] Add an explanatory message to the key request dialog. --- src/servers/keystore/KeyRequestWindow.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/servers/keystore/KeyRequestWindow.cpp b/src/servers/keystore/KeyRequestWindow.cpp index 4ebaf2b14e..d2f5c7e07b 100644 --- a/src/servers/keystore/KeyRequestWindow.cpp +++ b/src/servers/keystore/KeyRequestWindow.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -99,6 +100,21 @@ public: new BMessage(kMessageUnlock)); buttons->GroupLayout()->AddView(fUnlockButton); + BTextView* message = new(std::nothrow) BTextView("message"); + message->SetText("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->SetViewColor(ui_color(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); } From 0e4f2804b599700c5837e79e1a555f644f74c3a9 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sun, 24 Jun 2012 15:06:26 +0200 Subject: [PATCH 084/104] Remove the leftover checkbox in the key request dialog. --- src/servers/keystore/KeyRequestWindow.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/servers/keystore/KeyRequestWindow.cpp b/src/servers/keystore/KeyRequestWindow.cpp index d2f5c7e07b..4d3d7a9c2c 100644 --- a/src/servers/keystore/KeyRequestWindow.cpp +++ b/src/servers/keystore/KeyRequestWindow.cpp @@ -82,10 +82,6 @@ public: layout->AddItem(fPassword->CreateLabelLayoutItem(), 0, row); layout->AddItem(layoutItem, 1, row++); - fPersist = new(std::nothrow) BCheckBox("Not yet"); - layout->AddItem(BSpaceLayoutItem::CreateGlue(), 0, row); - layout->AddView(fPersist, 1, row++); - BGroupView* buttons = new(std::nothrow) BGroupView(B_HORIZONTAL); if (buttons == NULL) return; @@ -143,7 +139,6 @@ public: private: BStringView* fKeyringName; BTextControl* fPassword; - BCheckBox* fPersist; BButton* fCancelButton; BButton* fUnlockButton; }; From a2f279870c158dd81005c29ade41dc976e2892f2 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sun, 24 Jun 2012 15:07:06 +0200 Subject: [PATCH 085/104] Add strings that explain an access operation. May be used in the app access request dialog later on to show what privilege is actually requested. --- src/servers/keystore/KeyStoreServer.cpp | 42 +++++++++++++++++++++++++ src/servers/keystore/KeyStoreServer.h | 1 + 2 files changed, 43 insertions(+) diff --git a/src/servers/keystore/KeyStoreServer.cpp b/src/servers/keystore/KeyStoreServer.cpp index 27b1076f6b..1892cc8511 100644 --- a/src/servers/keystore/KeyStoreServer.cpp +++ b/src/servers/keystore/KeyStoreServer.cpp @@ -542,6 +542,48 @@ KeyStoreServer::_AccessFlagsFor(uint32 command) const } +const char* +KeyStoreServer::_AccessStringFor(uint32 accessFlag) const +{ + switch (accessFlag) { + case kFlagGetKey: + return "Get keys from the keyring."; + case kFlagEnumerateKeys: + return "Enumerate and get keys from the keyring."; + case kFlagAddKey: + return "Add keys to the keyring."; + case kFlagRemoveKey: + return "Remove keys from the keyring."; + case kFlagAddKeyring: + return "Add new keyrings."; + case kFlagRemoveKeyring: + return "Remove keyrings."; + case kFlagEnumerateKeyrings: + return "Enumerate the available keyrings."; + case kFlagSetMasterKey: + return "Set the master key."; + case kFlagRemoveMasterKey: + return "Remove the master key."; + case kFlagAddKeyringsToMaster: + return "Add the keyring key to the master keyring."; + case kFlagRemoveKeyringsFromMaster: + return "Remove the keyring key from the master keyring."; + case kFlagEnumerateMasterKeyrings: + return "Enumerate keyrings added to the master keyring."; + case kFlagQueryLockState: + return "Query the lock state of the keyring."; + case kFlagLockKeyring: + return "Lock the keyring."; + case kFlagEnumerateApplications: + return "Enumerate the applications of the keyring."; + case kFlagRemoveApplications: + return "Remove applications from the keyring."; + } + + return NULL; +} + + status_t KeyStoreServer::_ResolveCallingApp(const BMessage& message, app_info& callingAppInfo) const diff --git a/src/servers/keystore/KeyStoreServer.h b/src/servers/keystore/KeyStoreServer.h index 30e607870b..8af20ad7bf 100644 --- a/src/servers/keystore/KeyStoreServer.h +++ b/src/servers/keystore/KeyStoreServer.h @@ -30,6 +30,7 @@ private: status_t _WriteKeyStoreDatabase(); uint32 _AccessFlagsFor(uint32 command) const; + const char* _AccessStringFor(uint32 accessFlag) const; status_t _ResolveCallingApp(const BMessage& message, app_info& callingAppInfo) const; From ee834720429a09b6727b310c46a464064c159a82 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sun, 24 Jun 2012 15:08:43 +0200 Subject: [PATCH 086/104] Accumulate the app access flags instead of replacing them. Before, each permanently granted access flag would overwrite the previously granted flag, causing the dialog to come up whenever the operation was changed. --- src/servers/keystore/KeyStoreServer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/servers/keystore/KeyStoreServer.cpp b/src/servers/keystore/KeyStoreServer.cpp index 1892cc8511..2717012279 100644 --- a/src/servers/keystore/KeyStoreServer.cpp +++ b/src/servers/keystore/KeyStoreServer.cpp @@ -643,7 +643,7 @@ KeyStoreServer::_ValidateAppAccess(Keyring& keyring, const app_info& appInfo, appMessage.MakeEmpty(); appMessage.AddString("path", path.Path()); - appMessage.AddUInt32("flags", accessFlags); + appMessage.AddUInt32("flags", appFlags | accessFlags); appMessage.AddString("checksum", checksum); keyring.RemoveApplication(appInfo.signature, path.Path()); From cbdd5aff176eb863edcf21b0784391b1d51f093a Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sun, 24 Jun 2012 15:32:31 +0200 Subject: [PATCH 087/104] Restyle the app access request dialog to make it less horrible. --- .../keystore/AppAccessRequestWindow.cpp | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/servers/keystore/AppAccessRequestWindow.cpp b/src/servers/keystore/AppAccessRequestWindow.cpp index b7ce8b625e..d4fb25f7fa 100644 --- a/src/servers/keystore/AppAccessRequestWindow.cpp +++ b/src/servers/keystore/AppAccessRequestWindow.cpp @@ -52,8 +52,11 @@ public: return; BString details; - details << "The application\n" << signature << " (" << path << ")\n" - << "requests access to keyring\n" << keyringName << "\n"; + details << "The application:\n\n" + << signature << " (" << path << ")\n\n" + << "requests access to keyring:\n\n" + << keyringName << "\n\n"; + if (appIsNew) details << "This application hasn't been granted access before."; else if (appWasUpdated) { @@ -61,10 +64,20 @@ public: << " granted access."; } else { details << "This application doesn't yet have the required" - " priviledges."; + " privileges."; } message->SetText(details); + message->SetViewColor(ui_color(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); + + message->SetExplicitMinSize(BSize(message->StringWidth( + "01234567890123456789012345678901234567890123456789") + inset, + B_SIZE_UNSET)); BGroupView* buttons = new(std::nothrow) BGroupView(B_HORIZONTAL); if (buttons == NULL) From a59169de6f5fd92ba06d5d3836a4223b22cb8b6e Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sun, 24 Jun 2012 16:06:41 +0200 Subject: [PATCH 088/104] Add the access string to the app access request dialog. This way the user can see what operation the application tries to do. --- .../keystore/AppAccessRequestWindow.cpp | 24 +++++++++++++------ src/servers/keystore/AppAccessRequestWindow.h | 3 ++- src/servers/keystore/KeyStoreServer.cpp | 9 +++---- src/servers/keystore/KeyStoreServer.h | 3 ++- 4 files changed, 26 insertions(+), 13 deletions(-) diff --git a/src/servers/keystore/AppAccessRequestWindow.cpp b/src/servers/keystore/AppAccessRequestWindow.cpp index d4fb25f7fa..bb63438373 100644 --- a/src/servers/keystore/AppAccessRequestWindow.cpp +++ b/src/servers/keystore/AppAccessRequestWindow.cpp @@ -31,7 +31,8 @@ static const uint32 kMessageAlways = 'btaa'; class AppAccessRequestView : public BView { public: AppAccessRequestView(const char* keyringName, const char* signature, - const char* path, bool appIsNew, bool appWasUpdated) + const char* path, const char* accessString, bool appIsNew, + bool appWasUpdated) : BView("AppAccessRequestView", B_WILL_DRAW) { @@ -52,10 +53,18 @@ public: return; BString details; - details << "The application:\n\n" - << signature << " (" << path << ")\n\n" - << "requests access to keyring:\n\n" - << keyringName << "\n\n"; + details << "The application:\n" + << signature << " (" << path << ")\n\n"; + + if (keyringName != NULL) { + details << "requests access to keyring:\n" + << keyringName << "\n\n"; + } + + if (accessString != NULL) { + details << "to perform the following action:\n" + << accessString << "\n\n"; + } if (appIsNew) details << "This application hasn't been granted access before."; @@ -120,7 +129,8 @@ private: AppAccessRequestWindow::AppAccessRequestWindow(const char* keyringName, - const char* signature, const char* path, bool appIsNew, bool appWasUpdated) + const char* signature, const char* path, const char* accessString, + bool appIsNew, bool appWasUpdated) : BWindow(BRect(50, 50, 269, 302), "Application Keyring Access", B_TITLED_WINDOW, B_NOT_RESIZABLE | B_ASYNCHRONOUS_CONTROLS @@ -140,7 +150,7 @@ AppAccessRequestWindow::AppAccessRequestWindow(const char* keyringName, SetLayout(layout); fRequestView = new(std::nothrow) AppAccessRequestView(keyringName, - signature, path, appIsNew, appWasUpdated); + signature, path, accessString, appIsNew, appWasUpdated); if (fRequestView == NULL) return; diff --git a/src/servers/keystore/AppAccessRequestWindow.h b/src/servers/keystore/AppAccessRequestWindow.h index 2dfbd875e8..e8fbee8a5b 100644 --- a/src/servers/keystore/AppAccessRequestWindow.h +++ b/src/servers/keystore/AppAccessRequestWindow.h @@ -18,7 +18,8 @@ public: AppAccessRequestWindow( const char* keyringName, const char* signature, - const char* path, bool appIsNew, + const char* path, + const char* accessString, bool appIsNew, bool appWasUpdated); virtual ~AppAccessRequestWindow(); diff --git a/src/servers/keystore/KeyStoreServer.cpp b/src/servers/keystore/KeyStoreServer.cpp index 2717012279..19fe75435e 100644 --- a/src/servers/keystore/KeyStoreServer.cpp +++ b/src/servers/keystore/KeyStoreServer.cpp @@ -635,9 +635,10 @@ KeyStoreServer::_ValidateAppAccess(Keyring& keyring, const app_info& appInfo, if ((accessFlags & appFlags) == accessFlags) return B_OK; + const char* accessString = _AccessStringFor(accessFlags); bool allowAlways = false; result = _RequestAppAccess(keyring.Name(), appInfo.signature, path.Path(), - appIsNew, appWasUpdated, accessFlags, allowAlways); + accessString, appIsNew, appWasUpdated, accessFlags, allowAlways); if (result != B_OK || !allowAlways) return result; @@ -656,12 +657,12 @@ KeyStoreServer::_ValidateAppAccess(Keyring& keyring, const app_info& appInfo, status_t KeyStoreServer::_RequestAppAccess(const BString& keyringName, - const char* signature, const char* path, bool appIsNew, bool appWasUpdated, - uint32 accessFlags, bool& allowAlways) + const char* signature, const char* path, const char* accessString, + bool appIsNew, bool appWasUpdated, uint32 accessFlags, bool& allowAlways) { AppAccessRequestWindow* requestWindow = new(std::nothrow) AppAccessRequestWindow(keyringName, signature, path, - appIsNew, appWasUpdated); + accessString, appIsNew, appWasUpdated); if (requestWindow == NULL) return B_NO_MEMORY; diff --git a/src/servers/keystore/KeyStoreServer.h b/src/servers/keystore/KeyStoreServer.h index 8af20ad7bf..aa25f82ca8 100644 --- a/src/servers/keystore/KeyStoreServer.h +++ b/src/servers/keystore/KeyStoreServer.h @@ -40,7 +40,8 @@ private: status_t _RequestAppAccess( const BString& keyringName, const char* signature, - const char* path, bool appIsNew, + const char* path, + const char* accessString, bool appIsNew, bool appWasUpdated, uint32 accessFlags, bool& allowAlways); From 112af586522700955f276f583e2741c1840bec1d Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sun, 24 Jun 2012 16:10:00 +0200 Subject: [PATCH 089/104] Focus the password field in the key request dialog. --- src/servers/keystore/KeyRequestWindow.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/servers/keystore/KeyRequestWindow.cpp b/src/servers/keystore/KeyRequestWindow.cpp index 4d3d7a9c2c..61c7111f1f 100644 --- a/src/servers/keystore/KeyRequestWindow.cpp +++ b/src/servers/keystore/KeyRequestWindow.cpp @@ -121,6 +121,7 @@ public: fCancelButton->SetTarget(Window()); fUnlockButton->SetTarget(Window()); fUnlockButton->MakeDefault(true); + fPassword->MakeFocus(); } void From 8775bd129db78d06eb4876d3af0cff7893d612eb Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sun, 24 Jun 2012 20:45:22 +0200 Subject: [PATCH 090/104] Remove old TODO as we don't support multiple instances for now. As there aren't any more generic meta data containers inside BKey, there's no real way to distinguish different instances with the same identifiers. This may be added later, for example the same index system as used in BMessage could apply. --- headers/os/app/KeyStore.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/headers/os/app/KeyStore.h b/headers/os/app/KeyStore.h index 0d30390d4b..38486aadad 100644 --- a/headers/os/app/KeyStore.h +++ b/headers/os/app/KeyStore.h @@ -14,8 +14,6 @@ public: BKeyStore(); virtual ~BKeyStore(); -// TODO: -> GetNextPassword() - there can always be more than one key -// with the same identifier/secondaryIdentifier (ie. different username) status_t GetKey(BKeyType type, const char* identifier, BKey& key); status_t GetKey(BKeyType type, const char* identifier, From d4d6d1239322eeb4c100489eb76ed63afde449d6 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Mon, 25 Jun 2012 20:12:59 +0200 Subject: [PATCH 091/104] Don't require a key when creating a new keyring. There will be key setting/removal functions so the step of adding the keyring and setting a key on it can be done individually. --- headers/os/app/KeyStore.h | 3 +-- src/bin/keystore/keystore.cpp | 14 ++++++-------- src/kits/app/KeyStore.cpp | 8 +------- src/servers/keystore/KeyStoreServer.cpp | 9 ++++----- src/servers/keystore/KeyStoreServer.h | 3 +-- src/servers/keystore/Keyring.cpp | 4 +--- src/servers/keystore/Keyring.h | 3 +-- 7 files changed, 15 insertions(+), 29 deletions(-) diff --git a/headers/os/app/KeyStore.h b/headers/os/app/KeyStore.h index 38486aadad..f89819c809 100644 --- a/headers/os/app/KeyStore.h +++ b/headers/os/app/KeyStore.h @@ -51,8 +51,7 @@ public: // Keyrings - status_t AddKeyring(const char* keyring, - const BKey& key); + status_t AddKeyring(const char* keyring); status_t RemoveKeyring(const char* keyring); status_t GetNextKeyring(uint32& cookie, diff --git a/src/bin/keystore/keystore.cpp b/src/bin/keystore/keystore.cpp index 865f433a98..6189c545f6 100644 --- a/src/bin/keystore/keystore.cpp +++ b/src/bin/keystore/keystore.cpp @@ -57,12 +57,11 @@ remove_password(const char* keyring, const char* identifier, int -add_keyring(const char* keyring, const char* passwordString) +add_keyring(const char* keyring) { BKeyStore keyStore; - BPasswordKey password(passwordString, B_KEY_PURPOSE_KEYRING, NULL); - status_t result = keyStore.AddKeyring(keyring, password); + status_t result = keyStore.AddKeyring(keyring); if (result != B_OK) { printf("failed to add keyring: %s\n", strerror(result)); return 2; @@ -257,9 +256,8 @@ print_usage(const char* name) " []\n", name); printf("\t\tRemoves the specified password from the specified keyring.\n\n"); - printf("\t%s add keyring \n", name); - printf("\t\tAdds a new keyring with the specified name, protected by the" - " supplied password.\n"); + printf("\t%s add keyring \n", name); + printf("\t\tAdds a new keyring with the specified name.\n"); printf("\t%s remove keyring \n", name); printf("\t\tRemoves the specified keyring.\n\n"); @@ -344,10 +342,10 @@ main(int argc, char* argv[]) password); } } else if (strcmp(argv[2], "keyring") == 0) { - if (argc < 5) + if (argc < 4) return print_usage(argv[0]); - return add_keyring(argv[3], argv[4]); + return add_keyring(argv[3]); } } else if (strcmp(argv[1], "remove") == 0) { if (argc < 3) diff --git a/src/kits/app/KeyStore.cpp b/src/kits/app/KeyStore.cpp index 9b616bb305..8540729b4b 100644 --- a/src/kits/app/KeyStore.cpp +++ b/src/kits/app/KeyStore.cpp @@ -187,16 +187,10 @@ BKeyStore::GetNextKey(const char* keyring, BKeyType type, BKeyPurpose purpose, status_t -BKeyStore::AddKeyring(const char* keyring, const BKey& key) +BKeyStore::AddKeyring(const char* keyring) { - BMessage keyMessage; - if (key.Flatten(keyMessage) != B_OK) - return B_BAD_VALUE; - BMessage message(KEY_STORE_ADD_KEYRING); message.AddString("keyring", keyring); - message.AddMessage("key", &keyMessage); - return _SendKeyMessage(message, NULL); } diff --git a/src/servers/keystore/KeyStoreServer.cpp b/src/servers/keystore/KeyStoreServer.cpp index 19fe75435e..b0c782e561 100644 --- a/src/servers/keystore/KeyStoreServer.cpp +++ b/src/servers/keystore/KeyStoreServer.cpp @@ -269,13 +269,12 @@ KeyStoreServer::MessageReceived(BMessage* message) { BMessage keyMessage; BString keyring; - if (message->FindString("keyring", &keyring) != B_OK - || message->FindMessage("key", &keyMessage) != B_OK) { + if (message->FindString("keyring", &keyring) != B_OK) { result = B_BAD_VALUE; break; } - result = _AddKeyring(keyring, keyMessage); + result = _AddKeyring(keyring); if (result == B_OK) _WriteKeyStoreDatabase(); @@ -681,12 +680,12 @@ KeyStoreServer::_FindKeyring(const BString& name) status_t -KeyStoreServer::_AddKeyring(const BString& name, const BMessage& keyMessage) +KeyStoreServer::_AddKeyring(const BString& name) { if (_FindKeyring(name) != NULL) return B_NAME_IN_USE; - Keyring* keyring = new(std::nothrow) Keyring(name, &keyMessage); + Keyring* keyring = new(std::nothrow) Keyring(name); if (keyring == NULL) return B_NO_MEMORY; diff --git a/src/servers/keystore/KeyStoreServer.h b/src/servers/keystore/KeyStoreServer.h index aa25f82ca8..4ab7a460fb 100644 --- a/src/servers/keystore/KeyStoreServer.h +++ b/src/servers/keystore/KeyStoreServer.h @@ -47,8 +47,7 @@ private: Keyring* _FindKeyring(const BString& name); - status_t _AddKeyring(const BString& name, - const BMessage& keyMessage); + status_t _AddKeyring(const BString& name); status_t _RemoveKeyring(const BString& name); status_t _UnlockKeyring(Keyring& keyring); diff --git a/src/servers/keystore/Keyring.cpp b/src/servers/keystore/Keyring.cpp index eff7c0051a..b472fffa4f 100644 --- a/src/servers/keystore/Keyring.cpp +++ b/src/servers/keystore/Keyring.cpp @@ -7,14 +7,12 @@ #include "Keyring.h" -Keyring::Keyring(const char* name, const BMessage* keyMessage) +Keyring::Keyring(const char* name) : fName(name), fUnlocked(false), fModified(false) { - if (keyMessage != NULL) - Unlock(*keyMessage); } diff --git a/src/servers/keystore/Keyring.h b/src/servers/keystore/Keyring.h index afbca03b14..978e312a4f 100644 --- a/src/servers/keystore/Keyring.h +++ b/src/servers/keystore/Keyring.h @@ -12,8 +12,7 @@ class Keyring { public: - Keyring(const char* name, - const BMessage* keyMessage = NULL); + Keyring(const char* name); ~Keyring(); const char* Name() const { return fName; } From bec02d0c2f483a804eb0b833d099b85b3660cdb0 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Mon, 25 Jun 2012 20:19:30 +0200 Subject: [PATCH 092/104] Store each keyring in a message under a common keyrings field. * Each keyring is now stored in a proper message which allows it to contain additional meta data along side the flat data. * Adding all keyring messages under a common field also allows to add meta data to the keystore, as the keyrings don't use up random field names anymore. * Treat the master keyring as any other keyring and just add it to the list. This allows to write/read the keystore database without special casing the master keyring. --- src/servers/keystore/KeyStoreServer.cpp | 49 +++++++++++++------------ src/servers/keystore/Keyring.cpp | 20 +++++++++- src/servers/keystore/Keyring.h | 1 + 3 files changed, 45 insertions(+), 25 deletions(-) diff --git a/src/servers/keystore/KeyStoreServer.cpp b/src/servers/keystore/KeyStoreServer.cpp index b0c782e561..c46761108a 100644 --- a/src/servers/keystore/KeyStoreServer.cpp +++ b/src/servers/keystore/KeyStoreServer.cpp @@ -30,6 +30,8 @@ using namespace BPrivate; static const char* kMasterKeyringName = "Master"; static const char* kKeyringKeysIdentifier = "Keyrings"; +static const uint32 kKeyStoreFormatVersion = 1; + static const uint32 kFlagGetKey = 0x0001; static const uint32 kFlagEnumerateKeys = 0x0002; static const uint32 kFlagAddKey = 0x0004; @@ -83,8 +85,10 @@ KeyStoreServer::KeyStoreServer() _ReadKeyStoreDatabase(); - if (fMasterKeyring == NULL) + if (fMasterKeyring == NULL) { fMasterKeyring = new(std::nothrow) Keyring(kMasterKeyringName); + fKeyrings.BinaryInsert(fMasterKeyring, &Keyring::Compare); + } } @@ -302,11 +306,7 @@ KeyStoreServer::MessageReceived(BMessage* message) break; } - if (cookie == 0) - keyring = fMasterKeyring; - else - keyring = fKeyrings.ItemAt(cookie - 1); - + keyring = fKeyrings.ItemAt(cookie); if (keyring == NULL) { result = B_ENTRY_NOT_FOUND; break; @@ -442,34 +442,35 @@ KeyStoreServer::MessageReceived(BMessage* message) status_t KeyStoreServer::_ReadKeyStoreDatabase() { - BMessage keyrings; - status_t result = keyrings.Unflatten(&fKeyStoreFile); + BMessage keystore; + status_t result = keystore.Unflatten(&fKeyStoreFile); if (result != B_OK) { printf("failed to read keystore database\n"); _WriteKeyStoreDatabase(); + // Reinitializes the database. return result; } int32 index = 0; - char* keyringName = NULL; - while (keyrings.GetInfo(B_RAW_TYPE, index++, &keyringName, NULL) == B_OK) { - Keyring* keyring = new(std::nothrow) Keyring(keyringName); + BMessage keyringData; + while (keystore.FindMessage("keyrings", index++, &keyringData) == B_OK) { + Keyring* keyring = new(std::nothrow) Keyring(); if (keyring == NULL) { - printf("no memory for allocating keyring \"%s\"\n", keyringName); - continue; + printf("no memory for allocating keyring\n"); + break; } - status_t result = keyring->ReadFromMessage(keyrings); + status_t result = keyring->ReadFromMessage(keyringData); if (result != B_OK) { - printf("failed to read keyring \"%s\" from data\n", keyringName); + printf("failed to read keyring from data\n"); delete keyring; continue; } - if (strcmp(keyringName, kMasterKeyringName) == 0) + if (strcmp(keyring->Name(), kMasterKeyringName) == 0) fMasterKeyring = keyring; - else - fKeyrings.BinaryInsert(keyring, &Keyring::Compare); + + fKeyrings.BinaryInsert(keyring, &Keyring::Compare); } return B_OK; @@ -479,23 +480,25 @@ KeyStoreServer::_ReadKeyStoreDatabase() status_t KeyStoreServer::_WriteKeyStoreDatabase() { - BMessage keyrings; - if (fMasterKeyring != NULL) - fMasterKeyring->WriteToMessage(keyrings); + BMessage keystore; + keystore.AddUInt32("format", kKeyStoreFormatVersion); for (int32 i = 0; i < fKeyrings.CountItems(); i++) { Keyring* keyring = fKeyrings.ItemAt(i); if (keyring == NULL) continue; - status_t result = keyring->WriteToMessage(keyrings); + BMessage keyringData; + status_t result = keyring->WriteToMessage(keyringData); if (result != B_OK) return result; + + keystore.AddMessage("keyrings", &keyringData); } fKeyStoreFile.SetSize(0); fKeyStoreFile.Seek(0, SEEK_SET); - return keyrings.Flatten(&fKeyStoreFile); + return keystore.Flatten(&fKeyStoreFile); } diff --git a/src/servers/keystore/Keyring.cpp b/src/servers/keystore/Keyring.cpp index b472fffa4f..28bcaaf1b3 100644 --- a/src/servers/keystore/Keyring.cpp +++ b/src/servers/keystore/Keyring.cpp @@ -7,6 +7,14 @@ #include "Keyring.h" +Keyring::Keyring() + : + fUnlocked(false), + fModified(false) +{ +} + + Keyring::Keyring(const char* name) : fName(name), @@ -24,9 +32,13 @@ Keyring::~Keyring() status_t Keyring::ReadFromMessage(const BMessage& message) { + status_t result = message.FindString("name", &fName); + if (result != B_OK) + return result; + ssize_t size; const void* data; - status_t result = message.FindData(fName, B_RAW_TYPE, &data, &size); + result = message.FindData("data", B_RAW_TYPE, &data, &size); if (result != B_OK) return result; @@ -51,8 +63,12 @@ Keyring::WriteToMessage(BMessage& message) if (result != B_OK) return result; - return message.AddData(fName, B_RAW_TYPE, fFlatBuffer.Buffer(), + result = message.AddData("data", B_RAW_TYPE, fFlatBuffer.Buffer(), fFlatBuffer.BufferLength()); + if (result != B_OK) + return result; + + return message.AddString("name", fName); } diff --git a/src/servers/keystore/Keyring.h b/src/servers/keystore/Keyring.h index 978e312a4f..d0ba76f875 100644 --- a/src/servers/keystore/Keyring.h +++ b/src/servers/keystore/Keyring.h @@ -12,6 +12,7 @@ class Keyring { public: + Keyring(); Keyring(const char* name); ~Keyring(); From a82011ff964f4e27f38d0d8ebbc1e04fdf9db22e Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Mon, 25 Jun 2012 20:27:35 +0200 Subject: [PATCH 093/104] Introduce keyring unlock key concept. * Rename fKeyMessage to fUnlockKey and the KeyMessage() getter to UnlockKey(). * Keep track of whether the keyring has an unlock key set. * Store and restore that info separately. * En- and decryption will depend on unlock key presence later. * Add functions to set and remove an unlock key and query for it. --- src/servers/keystore/KeyStoreServer.cpp | 9 ++-- src/servers/keystore/Keyring.cpp | 72 +++++++++++++++++++++---- src/servers/keystore/Keyring.h | 12 +++-- 3 files changed, 78 insertions(+), 15 deletions(-) diff --git a/src/servers/keystore/KeyStoreServer.cpp b/src/servers/keystore/KeyStoreServer.cpp index c46761108a..05b367d0ce 100644 --- a/src/servers/keystore/KeyStoreServer.cpp +++ b/src/servers/keystore/KeyStoreServer.cpp @@ -350,7 +350,7 @@ KeyStoreServer::MessageReceived(BMessage* message) break; BString secondaryIdentifier = keyring->Name(); - BMessage keyMessage = keyring->KeyMessage(); + BMessage keyMessage = keyring->UnlockKey(); keyMessage.RemoveName("identifier"); keyMessage.AddString("identifier", kKeyringKeysIdentifier); keyMessage.RemoveName("secondaryIdentifier"); @@ -720,6 +720,9 @@ KeyStoreServer::_RemoveKeyring(const BString& name) status_t KeyStoreServer::_UnlockKeyring(Keyring& keyring) { + if (!keyring.HasUnlockKey()) + return keyring.Unlock(NULL); + // If we are accessing a keyring that has been added to master access we // get the key from the master keyring and unlock with that. BMessage keyMessage; @@ -727,7 +730,7 @@ KeyStoreServer::_UnlockKeyring(Keyring& keyring) if (fMasterKeyring->FindKey(kKeyringKeysIdentifier, keyring.Name(), false, &keyMessage) == B_OK) { // We found a key for this keyring, try to unlock with it. - if (keyring.Unlock(keyMessage) == B_OK) + if (keyring.Unlock(&keyMessage) == B_OK) return B_OK; } } @@ -737,7 +740,7 @@ KeyStoreServer::_UnlockKeyring(Keyring& keyring) if (result != B_OK) return result; - return keyring.Unlock(keyMessage); + return keyring.Unlock(&keyMessage); } diff --git a/src/servers/keystore/Keyring.cpp b/src/servers/keystore/Keyring.cpp index 28bcaaf1b3..5575ceabe7 100644 --- a/src/servers/keystore/Keyring.cpp +++ b/src/servers/keystore/Keyring.cpp @@ -9,6 +9,7 @@ Keyring::Keyring() : + fHasUnlockKey(false), fUnlocked(false), fModified(false) { @@ -18,6 +19,7 @@ Keyring::Keyring() Keyring::Keyring(const char* name) : fName(name), + fHasUnlockKey(false), fUnlocked(false), fModified(false) { @@ -36,6 +38,10 @@ Keyring::ReadFromMessage(const BMessage& message) if (result != B_OK) return result; + result = message.FindBool("hasUnlockKey", &fHasUnlockKey); + if (result != B_OK) + return result; + ssize_t size; const void* data; result = message.FindData("data", B_RAW_TYPE, &data, &size); @@ -68,18 +74,29 @@ Keyring::WriteToMessage(BMessage& message) if (result != B_OK) return result; + result = message.AddBool("hasUnlockKey", fHasUnlockKey); + if (result != B_OK) + return result; + return message.AddString("name", fName); } status_t -Keyring::Unlock(const BMessage& keyMessage) +Keyring::Unlock(const BMessage* keyMessage) { - fKeyMessage = keyMessage; + if (fUnlocked) + return B_OK; + + if (fHasUnlockKey == (keyMessage == NULL)) + return B_BAD_VALUE; + + if (keyMessage != NULL) + fUnlockKey = *keyMessage; status_t result = _DecryptFromFlatBuffer(); if (result != B_OK) { - fKeyMessage.MakeEmpty(); + fUnlockKey.MakeEmpty(); return result; } @@ -96,7 +113,7 @@ Keyring::Lock() _EncryptToFlatBuffer(); - fKeyMessage.MakeEmpty(); + fUnlockKey.MakeEmpty(); fData.MakeEmpty(); fApplications.MakeEmpty(); fUnlocked = false; @@ -110,10 +127,43 @@ Keyring::IsUnlocked() const } -const BMessage& -Keyring::KeyMessage() const +bool +Keyring::HasUnlockKey() const { - return fKeyMessage; + return fHasUnlockKey; +} + + +const BMessage& +Keyring::UnlockKey() const +{ + return fUnlockKey; +} + + +status_t +Keyring::SetUnlockKey(const BMessage& keyMessage) +{ + if (!fUnlocked) + return B_NOT_ALLOWED; + + fHasUnlockKey = true; + fUnlockKey = keyMessage; + fModified = true; + return B_OK; +} + + +status_t +Keyring::RemoveUnlockKey() +{ + if (!fUnlocked) + return B_NOT_ALLOWED; + + fUnlockKey.MakeEmpty(); + fHasUnlockKey = false; + fModified = true; + return B_OK; } @@ -430,7 +480,9 @@ Keyring::_EncryptToFlatBuffer() if (result != B_OK) return result; - // TODO: Actually encrypt the flat buffer... + if (fHasUnlockKey) { + // TODO: Actually encrypt the flat buffer... + } fModified = false; return B_OK; @@ -443,7 +495,9 @@ Keyring::_DecryptFromFlatBuffer() if (fFlatBuffer.BufferLength() == 0) return B_OK; - // TODO: Actually decrypt the flat buffer... + if (fHasUnlockKey) { + // TODO: Actually decrypt the flat buffer... + } BMessage container; fFlatBuffer.Seek(0, SEEK_SET); diff --git a/src/servers/keystore/Keyring.h b/src/servers/keystore/Keyring.h index d0ba76f875..de8d931ccd 100644 --- a/src/servers/keystore/Keyring.h +++ b/src/servers/keystore/Keyring.h @@ -20,10 +20,15 @@ public: status_t ReadFromMessage(const BMessage& message); status_t WriteToMessage(BMessage& message); - status_t Unlock(const BMessage& keyMessage); + status_t Unlock(const BMessage* keyMessage); void Lock(); bool IsUnlocked() const; - const BMessage& KeyMessage() const; + + bool HasUnlockKey() const; + const BMessage& UnlockKey() const; + + status_t SetUnlockKey(const BMessage& keyMessage); + status_t RemoveUnlockKey(); status_t GetNextApplication(uint32& cookie, BString& signature, BString& path); @@ -61,7 +66,8 @@ private: BMallocIO fFlatBuffer; BMessage fData; BMessage fApplications; - BMessage fKeyMessage; + BMessage fUnlockKey; + bool fHasUnlockKey; bool fUnlocked; bool fModified; }; From 4a0460a9bc02ca100b7b7de2f7b04e77ee75593f Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Mon, 25 Jun 2012 20:31:27 +0200 Subject: [PATCH 094/104] Add generic unlock key setting and removal. * Replace {Set|Remove}MasterKey() by generic {Set|Remove}UnlockKey() that works on a keyring. * Implement {Set|Remove}MasterUnlockKey() on top of that. * Rename the commands and constants accrodingly. * Implement setting and removing keyring unlock keys. --- headers/os/app/KeyStore.h | 10 +++-- headers/private/app/KeyStoreDefs.h | 4 +- src/kits/app/KeyStore.cpp | 30 +++++++++++---- src/servers/keystore/KeyStoreServer.cpp | 51 +++++++++++++++++++------ 4 files changed, 72 insertions(+), 23 deletions(-) diff --git a/headers/os/app/KeyStore.h b/headers/os/app/KeyStore.h index f89819c809..7c5a86d638 100644 --- a/headers/os/app/KeyStore.h +++ b/headers/os/app/KeyStore.h @@ -57,10 +57,14 @@ public: status_t GetNextKeyring(uint32& cookie, BString& keyring); - // Master key + status_t SetUnlockKey(const char* keyring, + const BKey& key); + status_t RemoveUnlockKey(const char* keyring); - status_t SetMasterKey(const BKey& key); - status_t RemoveMasterKey(); + // Master keyring + + status_t SetMasterUnlockKey(const BKey& key); + status_t RemoveMasterUnlockKey(); status_t AddKeyringToMaster(const char* keyring); status_t RemoveKeyringFromMaster(const char* keyring); diff --git a/headers/private/app/KeyStoreDefs.h b/headers/private/app/KeyStoreDefs.h index 257a35275d..0c1218c031 100644 --- a/headers/private/app/KeyStoreDefs.h +++ b/headers/private/app/KeyStoreDefs.h @@ -30,8 +30,8 @@ enum { KEY_STORE_ADD_KEYRING = 'KaKR', KEY_STORE_REMOVE_KEYRING = 'KrKR', KEY_STORE_GET_NEXT_KEYRING = 'KnKR', - KEY_STORE_SET_MASTER_KEY = 'KsMK', - KEY_STORE_REMOVE_MASTER_KEY = 'KrMK', + KEY_STORE_SET_UNLOCK_KEY = 'KsuK', + KEY_STORE_REMOVE_UNLOCK_KEY = 'KruK', KEY_STORE_ADD_KEYRING_TO_MASTER = 'KarM', KEY_STORE_REMOVE_KEYRING_FROM_MASTER = 'KrrM', KEY_STORE_GET_NEXT_MASTER_KEYRING = 'KnrM', diff --git a/src/kits/app/KeyStore.cpp b/src/kits/app/KeyStore.cpp index 8540729b4b..c72b87a7a5 100644 --- a/src/kits/app/KeyStore.cpp +++ b/src/kits/app/KeyStore.cpp @@ -223,17 +223,15 @@ BKeyStore::GetNextKeyring(uint32& cookie, BString& keyring) } -// #pragma mark - Master key - - status_t -BKeyStore::SetMasterKey(const BKey& key) +BKeyStore::SetUnlockKey(const char* keyring, const BKey& key) { BMessage keyMessage; if (key.Flatten(keyMessage) != B_OK) return B_BAD_VALUE; - BMessage message(KEY_STORE_SET_MASTER_KEY); + BMessage message(KEY_STORE_SET_UNLOCK_KEY); + message.AddString("keyring", keyring); message.AddMessage("key", &keyMessage); return _SendKeyMessage(message, NULL); @@ -241,13 +239,31 @@ BKeyStore::SetMasterKey(const BKey& key) status_t -BKeyStore::RemoveMasterKey() +BKeyStore::RemoveUnlockKey(const char* keyring) { - BMessage message(KEY_STORE_REMOVE_MASTER_KEY); + BMessage message(KEY_STORE_REMOVE_UNLOCK_KEY); + message.AddString("keyring", keyring); return _SendKeyMessage(message, NULL); } +// #pragma mark - Master key + + +status_t +BKeyStore::SetMasterUnlockKey(const BKey& key) +{ + return SetUnlockKey(NULL, key); +} + + +status_t +BKeyStore::RemoveMasterUnlockKey() +{ + return RemoveUnlockKey(NULL); +} + + status_t BKeyStore::AddKeyringToMaster(const char* keyring) { diff --git a/src/servers/keystore/KeyStoreServer.cpp b/src/servers/keystore/KeyStoreServer.cpp index 05b367d0ce..f825fb4088 100644 --- a/src/servers/keystore/KeyStoreServer.cpp +++ b/src/servers/keystore/KeyStoreServer.cpp @@ -39,8 +39,8 @@ static const uint32 kFlagRemoveKey = 0x0008; static const uint32 kFlagAddKeyring = 0x0010; static const uint32 kFlagRemoveKeyring = 0x0020; static const uint32 kFlagEnumerateKeyrings = 0x0040; -static const uint32 kFlagSetMasterKey = 0x0080; -static const uint32 kFlagRemoveMasterKey = 0x0100; +static const uint32 kFlagSetUnlockKey = 0x0080; +static const uint32 kFlagRemoveUnlockKey = 0x0100; static const uint32 kFlagAddKeyringsToMaster = 0x0200; static const uint32 kFlagRemoveKeyringsFromMaster = 0x0400; static const uint32 kFlagEnumerateMasterKeyrings = 0x0800; @@ -51,7 +51,7 @@ static const uint32 kFlagRemoveApplications = 0x8000; static const uint32 kDefaultAppFlags = kFlagGetKey | kFlagEnumerateKeys | kFlagAddKey | kFlagRemoveKey | kFlagAddKeyring | kFlagRemoveKeyring - | kFlagEnumerateKeyrings | kFlagSetMasterKey | kFlagRemoveMasterKey + | kFlagEnumerateKeyrings | kFlagSetUnlockKey | kFlagRemoveUnlockKey | kFlagAddKeyringsToMaster | kFlagRemoveKeyringsFromMaster | kFlagEnumerateMasterKeyrings | kFlagQueryLockState | kFlagLockKeyring | kFlagEnumerateApplications | kFlagRemoveApplications; @@ -123,6 +123,8 @@ KeyStoreServer::MessageReceived(BMessage* message) case KEY_STORE_REMOVE_KEY: case KEY_STORE_IS_KEYRING_UNLOCKED: case KEY_STORE_LOCK_KEYRING: + case KEY_STORE_SET_UNLOCK_KEY: + case KEY_STORE_REMOVE_UNLOCK_KEY: case KEY_STORE_ADD_KEYRING_TO_MASTER: case KEY_STORE_REMOVE_KEYRING_FROM_MASTER: case KEY_STORE_GET_NEXT_APPLICATION: @@ -145,6 +147,8 @@ KeyStoreServer::MessageReceived(BMessage* message) case KEY_STORE_GET_NEXT_KEY: case KEY_STORE_ADD_KEY: case KEY_STORE_REMOVE_KEY: + case KEY_STORE_SET_UNLOCK_KEY: + case KEY_STORE_REMOVE_UNLOCK_KEY: case KEY_STORE_ADD_KEYRING_TO_MASTER: case KEY_STORE_GET_NEXT_APPLICATION: case KEY_STORE_REMOVE_APPLICATION: @@ -333,6 +337,31 @@ KeyStoreServer::MessageReceived(BMessage* message) break; } + case KEY_STORE_SET_UNLOCK_KEY: + { + BMessage keyMessage; + if (message->FindMessage("key", &keyMessage) != B_OK) { + result = B_BAD_VALUE; + break; + } + + result = keyring->SetUnlockKey(keyMessage); + if (result == B_OK) + _WriteKeyStoreDatabase(); + + // TODO: Update the key in the master if this keyring was added. + break; + } + + case KEY_STORE_REMOVE_UNLOCK_KEY: + { + result = keyring->RemoveUnlockKey(); + if (result == B_OK) + _WriteKeyStoreDatabase(); + + break; + } + case KEY_STORE_ADD_KEYRING_TO_MASTER: case KEY_STORE_REMOVE_KEYRING_FROM_MASTER: { @@ -520,10 +549,10 @@ KeyStoreServer::_AccessFlagsFor(uint32 command) const return kFlagRemoveKeyring; case KEY_STORE_GET_NEXT_KEYRING: return kFlagEnumerateKeyrings; - case KEY_STORE_SET_MASTER_KEY: - return kFlagSetMasterKey; - case KEY_STORE_REMOVE_MASTER_KEY: - return kFlagRemoveMasterKey; + case KEY_STORE_SET_UNLOCK_KEY: + return kFlagSetUnlockKey; + case KEY_STORE_REMOVE_UNLOCK_KEY: + return kFlagRemoveUnlockKey; case KEY_STORE_ADD_KEYRING_TO_MASTER: return kFlagAddKeyringsToMaster; case KEY_STORE_REMOVE_KEYRING_FROM_MASTER: @@ -562,10 +591,10 @@ KeyStoreServer::_AccessStringFor(uint32 accessFlag) const return "Remove keyrings."; case kFlagEnumerateKeyrings: return "Enumerate the available keyrings."; - case kFlagSetMasterKey: - return "Set the master key."; - case kFlagRemoveMasterKey: - return "Remove the master key."; + case kFlagSetUnlockKey: + return "Set the unlock key of the keyring."; + case kFlagRemoveUnlockKey: + return "Remove the unlock key of the keyring."; case kFlagAddKeyringsToMaster: return "Add the keyring key to the master keyring."; case kFlagRemoveKeyringsFromMaster: From ae542b141d7ca7752430d984142646afc1310a67 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Mon, 25 Jun 2012 20:36:34 +0200 Subject: [PATCH 095/104] Add setting/removal of keyring unlock keys to the cli app. --- src/bin/keystore/keystore.cpp | 49 ++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/src/bin/keystore/keystore.cpp b/src/bin/keystore/keystore.cpp index 6189c545f6..682db34f14 100644 --- a/src/bin/keystore/keystore.cpp +++ b/src/bin/keystore/keystore.cpp @@ -230,6 +230,37 @@ remove_application(const char* keyring, const char* signature) } +int +set_unlock_key(const char* keyring, const char* passwordString) +{ + BKeyStore keyStore; + BPasswordKey password(passwordString, B_KEY_PURPOSE_KEYRING, NULL); + + status_t result = keyStore.SetUnlockKey(keyring, password); + if (result != B_OK) { + printf("failed to set unlock key: %s\n", strerror(result)); + return 3; + } + + return 0; +} + + +int +remove_unlock_key(const char* keyring) +{ + BKeyStore keyStore; + + status_t result = keyStore.RemoveUnlockKey(keyring); + if (result != B_OK) { + printf("failed to remove unlock key: %s\n", strerror(result)); + return 3; + } + + return 0; +} + + int print_usage(const char* name) { @@ -282,8 +313,13 @@ print_usage(const char* name) " signature from the master keyring.\n"); printf("\t%s remove application from \n", name); printf("\t\tRemove permanent access for the application with the given" - " signature from the specified keyring.\n"); + " signature from the specified keyring.\n\n"); + printf("\t%s key set \n", name); + printf("\t\tSet the unlock key of the specified keyring to the given" + " password.\n"); + printf("\t%s key remove \n", name); + printf("\t\tRemove the unlock key of the specified keyring.\n"); return 1; } @@ -406,6 +442,17 @@ main(int argc, char* argv[]) return add_keyring_to_master(argv[3]); if (strcmp(argv[2], "remove") == 0) return remove_keyring_from_master(argv[3]); + } else if (strcmp(argv[1], "key") == 0) { + if (argc < 4) + return print_usage(argv[0]); + + if (strcmp(argv[2], "set") == 0) { + if (argc == 5) + return set_unlock_key(argv[3], argv[4]); + } else if (strcmp(argv[2], "remove") == 0) { + if (argc == 4) + return remove_unlock_key(argv[3]); + } } return print_usage(argv[0]); From d3b8b801a8cef1fad01cb2f1a3b28c552712bb00 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Mon, 25 Jun 2012 20:37:39 +0200 Subject: [PATCH 096/104] Fix missing write of the keystore database on app removal. --- src/servers/keystore/KeyStoreServer.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/servers/keystore/KeyStoreServer.cpp b/src/servers/keystore/KeyStoreServer.cpp index f825fb4088..1c7ca387a6 100644 --- a/src/servers/keystore/KeyStoreServer.cpp +++ b/src/servers/keystore/KeyStoreServer.cpp @@ -438,6 +438,9 @@ KeyStoreServer::MessageReceived(BMessage* message) path = NULL; result = keyring->RemoveApplication(signature, path); + if (result == B_OK) + _WriteKeyStoreDatabase(); + break; } From c5469c39398f17b4e96ff71702788e0cfc72c0ec Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Mon, 25 Jun 2012 20:44:59 +0200 Subject: [PATCH 097/104] Add missing check for unlocked state. --- src/servers/keystore/Keyring.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/servers/keystore/Keyring.cpp b/src/servers/keystore/Keyring.cpp index 5575ceabe7..8392716909 100644 --- a/src/servers/keystore/Keyring.cpp +++ b/src/servers/keystore/Keyring.cpp @@ -171,6 +171,9 @@ status_t Keyring::GetNextApplication(uint32& cookie, BString& signature, BString& path) { + if (!fUnlocked) + return B_NOT_ALLOWED; + char* nameFound = NULL; status_t result = fApplications.GetInfo(B_MESSAGE_TYPE, cookie++, &nameFound, NULL); From 6cf270f88e7c79ef2fc4c31b76eb79f9085bb9ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dancs=C3=B3=20R=C3=B3bert?= Date: Sun, 10 Feb 2013 19:42:36 +0100 Subject: [PATCH 098/104] Added "Always on top" menu to the ActivityMonitor. Signed-off-by: Matt Madia --- src/apps/activitymonitor/ActivityWindow.cpp | 11 +++++++++++ src/apps/activitymonitor/ActivityWindow.h | 2 ++ 2 files changed, 13 insertions(+) diff --git a/src/apps/activitymonitor/ActivityWindow.cpp b/src/apps/activitymonitor/ActivityWindow.cpp index 188289163e..ea1bd21f9a 100644 --- a/src/apps/activitymonitor/ActivityWindow.cpp +++ b/src/apps/activitymonitor/ActivityWindow.cpp @@ -31,6 +31,7 @@ static const uint32 kMsgAddView = 'advw'; static const uint32 kMsgShowSettings = 'shst'; +static const uint32 kMsgAlwaysOnTop = 'alot'; ActivityWindow::ActivityWindow() @@ -131,6 +132,9 @@ ActivityWindow::ActivityWindow() menu = new BMenu(B_TRANSLATE("Settings")); menu->AddItem(new BMenuItem(B_TRANSLATE("Settings" B_UTF8_ELLIPSIS), new BMessage(kMsgShowSettings))); + menu->AddSeparatorItem(); + fAlwaysOnTop = new BMenuItem(B_TRANSLATE("Always on top"), new BMessage(kMsgAlwaysOnTop)); + menu->AddItem(fAlwaysOnTop); menu->SetTargetForItems(this); menuBar->AddItem(menu); } @@ -200,6 +204,13 @@ ActivityWindow::MessageReceived(BMessage* message) } break; } + + case kMsgAlwaysOnTop: + { + SetFeel(this->IsFloating() ? B_NORMAL_WINDOW_FEEL : B_FLOATING_ALL_WINDOW_FEEL); + fAlwaysOnTop->SetMarked(!fAlwaysOnTop->IsMarked()); + break; + } case kMsgTimeIntervalUpdated: BroadcastToActivityViews(message); diff --git a/src/apps/activitymonitor/ActivityWindow.h b/src/apps/activitymonitor/ActivityWindow.h index aa218aff50..e7a97d2c2c 100644 --- a/src/apps/activitymonitor/ActivityWindow.h +++ b/src/apps/activitymonitor/ActivityWindow.h @@ -31,6 +31,8 @@ public: bigtime_t RefreshInterval() const; private: + BMenuItem* fAlwaysOnTop; + status_t _OpenSettings(BFile& file, uint32 mode); status_t _LoadSettings(BMessage& settings); status_t _SaveSettings(); From b58ffb0b4af5504e251c09b30885823cd384fcd4 Mon Sep 17 00:00:00 2001 From: Matt Madia Date: Wed, 6 Mar 2013 17:25:32 -0500 Subject: [PATCH 099/104] Automatic whitespace cleanup. No functional change. --- src/apps/activitymonitor/ActivityWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/activitymonitor/ActivityWindow.cpp b/src/apps/activitymonitor/ActivityWindow.cpp index ea1bd21f9a..f74a907e86 100644 --- a/src/apps/activitymonitor/ActivityWindow.cpp +++ b/src/apps/activitymonitor/ActivityWindow.cpp @@ -204,7 +204,7 @@ ActivityWindow::MessageReceived(BMessage* message) } break; } - + case kMsgAlwaysOnTop: { SetFeel(this->IsFloating() ? B_NORMAL_WINDOW_FEEL : B_FLOATING_ALL_WINDOW_FEEL); From f4b00418348b564b3daf32e0c7f937c2a47a5ea3 Mon Sep 17 00:00:00 2001 From: Ryan Leavengood Date: Thu, 7 Mar 2013 08:39:27 -0500 Subject: [PATCH 100/104] Save always on top setting and fix style issues. --- src/apps/activitymonitor/ActivityWindow.cpp | 23 ++++++++++++++++++--- src/apps/activitymonitor/ActivityWindow.h | 9 ++++---- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/apps/activitymonitor/ActivityWindow.cpp b/src/apps/activitymonitor/ActivityWindow.cpp index f74a907e86..c103c16a51 100644 --- a/src/apps/activitymonitor/ActivityWindow.cpp +++ b/src/apps/activitymonitor/ActivityWindow.cpp @@ -29,9 +29,10 @@ #undef B_TRANSLATION_CONTEXT #define B_TRANSLATION_CONTEXT "ActivityWindow" + static const uint32 kMsgAddView = 'advw'; -static const uint32 kMsgShowSettings = 'shst'; static const uint32 kMsgAlwaysOnTop = 'alot'; +static const uint32 kMsgShowSettings = 'shst'; ActivityWindow::ActivityWindow() @@ -132,9 +133,14 @@ ActivityWindow::ActivityWindow() menu = new BMenu(B_TRANSLATE("Settings")); menu->AddItem(new BMenuItem(B_TRANSLATE("Settings" B_UTF8_ELLIPSIS), new BMessage(kMsgShowSettings))); + menu->AddSeparatorItem(); fAlwaysOnTop = new BMenuItem(B_TRANSLATE("Always on top"), new BMessage(kMsgAlwaysOnTop)); + bool alwaysOnTop = false; + if (settings.FindBool("always on top", &alwaysOnTop) == B_OK) + _SetAlwaysOnTop(alwaysOnTop); menu->AddItem(fAlwaysOnTop); + menu->SetTargetForItems(this); menuBar->AddItem(menu); } @@ -207,8 +213,7 @@ ActivityWindow::MessageReceived(BMessage* message) case kMsgAlwaysOnTop: { - SetFeel(this->IsFloating() ? B_NORMAL_WINDOW_FEEL : B_FLOATING_ALL_WINDOW_FEEL); - fAlwaysOnTop->SetMarked(!fAlwaysOnTop->IsMarked()); + _SetAlwaysOnTop(!fAlwaysOnTop->IsMarked()); break; } @@ -311,6 +316,10 @@ ActivityWindow::_SaveSettings() if (status != B_OK) return status; + status = settings.AddBool("always on top", fAlwaysOnTop->IsMarked()); + if (status != B_OK) + return status; + #ifdef __HAIKU__ BView* top = fLayout->View(); #else @@ -379,3 +388,11 @@ ActivityWindow::_MessageDropped(BMessage* message) } } + +void +ActivityWindow::_SetAlwaysOnTop(bool alwaysOnTop) +{ + SetFeel(alwaysOnTop ? B_FLOATING_ALL_WINDOW_FEEL : B_NORMAL_WINDOW_FEEL); + fAlwaysOnTop->SetMarked(alwaysOnTop); +} + diff --git a/src/apps/activitymonitor/ActivityWindow.h b/src/apps/activitymonitor/ActivityWindow.h index e7a97d2c2c..0232cd80b5 100644 --- a/src/apps/activitymonitor/ActivityWindow.h +++ b/src/apps/activitymonitor/ActivityWindow.h @@ -31,19 +31,20 @@ public: bigtime_t RefreshInterval() const; private: - BMenuItem* fAlwaysOnTop; - status_t _OpenSettings(BFile& file, uint32 mode); status_t _LoadSettings(BMessage& settings); status_t _SaveSettings(); void _AddDefaultView(); void _MessageDropped(BMessage *message); + void _SetAlwaysOnTop(bool alwaysOnTop); + BMenuItem* fAlwaysOnTop; #ifdef __HAIKU__ - BGroupLayout* fLayout; + BGroupLayout* fLayout; #endif - BMessenger fSettingsWindow; + BMessenger fSettingsWindow; + }; static const uint32 kMsgRemoveView = 'rmvw'; From 57ad8744837fa88a3bbc87e63a72bfdbfa99596e Mon Sep 17 00:00:00 2001 From: Ryan Leavengood Date: Thu, 7 Mar 2013 08:55:39 -0500 Subject: [PATCH 101/104] Use GetBool and SetBool convenience methods for always on top. --- src/apps/activitymonitor/ActivityWindow.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/apps/activitymonitor/ActivityWindow.cpp b/src/apps/activitymonitor/ActivityWindow.cpp index c103c16a51..f635ec63ae 100644 --- a/src/apps/activitymonitor/ActivityWindow.cpp +++ b/src/apps/activitymonitor/ActivityWindow.cpp @@ -136,9 +136,7 @@ ActivityWindow::ActivityWindow() menu->AddSeparatorItem(); fAlwaysOnTop = new BMenuItem(B_TRANSLATE("Always on top"), new BMessage(kMsgAlwaysOnTop)); - bool alwaysOnTop = false; - if (settings.FindBool("always on top", &alwaysOnTop) == B_OK) - _SetAlwaysOnTop(alwaysOnTop); + _SetAlwaysOnTop(settings.GetBool("always on top", false)); menu->AddItem(fAlwaysOnTop); menu->SetTargetForItems(this); @@ -316,7 +314,7 @@ ActivityWindow::_SaveSettings() if (status != B_OK) return status; - status = settings.AddBool("always on top", fAlwaysOnTop->IsMarked()); + status = settings.SetBool("always on top", fAlwaysOnTop->IsMarked()); if (status != B_OK) return status; From eb594c5cd5a3a6b8b89be13f22f0e2731273bcae Mon Sep 17 00:00:00 2001 From: Ryan Leavengood Date: Thu, 7 Mar 2013 09:20:17 -0500 Subject: [PATCH 102/104] Don't constantly recreate the tool tip, just update the text. Fixes #9502, more or less. --- src/preferences/time/TimeZoneListView.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/preferences/time/TimeZoneListView.cpp b/src/preferences/time/TimeZoneListView.cpp index 87a8519c85..aa75195203 100644 --- a/src/preferences/time/TimeZoneListView.cpp +++ b/src/preferences/time/TimeZoneListView.cpp @@ -63,10 +63,12 @@ TimeZoneListView::GetToolTipAt(BPoint point, BToolTip** _tip) << " (" << dateInTimeZone << ')'; if (fToolTip != NULL) - fToolTip->ReleaseReference(); - fToolTip = new (std::nothrow) BTextToolTip(toolTip.String()); - if (fToolTip == NULL) - return false; + fToolTip->SetText(toolTip.String()); + else { + fToolTip = new (std::nothrow) BTextToolTip(toolTip.String()); + if (fToolTip == NULL) + return false; + } *_tip = fToolTip; From a595db17d6d26d923045f93a9a6277bda66444b8 Mon Sep 17 00:00:00 2001 From: Ryan Leavengood Date: Thu, 7 Mar 2013 09:30:04 -0500 Subject: [PATCH 103/104] Further simplify the Time tooltips by using SetToolTip. --- src/preferences/time/TimeZoneListView.cpp | 15 +++------------ src/preferences/time/TimeZoneListView.h | 6 ------ 2 files changed, 3 insertions(+), 18 deletions(-) diff --git a/src/preferences/time/TimeZoneListView.cpp b/src/preferences/time/TimeZoneListView.cpp index aa75195203..84598c6993 100644 --- a/src/preferences/time/TimeZoneListView.cpp +++ b/src/preferences/time/TimeZoneListView.cpp @@ -26,16 +26,13 @@ TimeZoneListView::TimeZoneListView(void) : - BOutlineListView("cityList", B_SINGLE_SELECTION_LIST), - fToolTip(NULL) + BOutlineListView("cityList", B_SINGLE_SELECTION_LIST) { } TimeZoneListView::~TimeZoneListView() { - if (fToolTip != NULL) - fToolTip->ReleaseReference(); } @@ -62,15 +59,9 @@ TimeZoneListView::GetToolTipAt(BPoint point, BToolTip** _tip) << B_TRANSLATE("\nNow: ") << nowInTimeZone << " (" << dateInTimeZone << ')'; - if (fToolTip != NULL) - fToolTip->SetText(toolTip.String()); - else { - fToolTip = new (std::nothrow) BTextToolTip(toolTip.String()); - if (fToolTip == NULL) - return false; - } + SetToolTip(toolTip.String()); - *_tip = fToolTip; + *_tip = ToolTip(); return true; } diff --git a/src/preferences/time/TimeZoneListView.h b/src/preferences/time/TimeZoneListView.h index 0b9fd48d0a..7814e844aa 100644 --- a/src/preferences/time/TimeZoneListView.h +++ b/src/preferences/time/TimeZoneListView.h @@ -12,9 +12,6 @@ #include -class BTextToolTip; - - class TimeZoneListView : public BOutlineListView { public: TimeZoneListView(void); @@ -22,9 +19,6 @@ public: protected: virtual bool GetToolTipAt(BPoint point, BToolTip** _tip); - -private: - BTextToolTip* fToolTip; }; From f6afd3e9f7b5580118731286dbc21a333d298458 Mon Sep 17 00:00:00 2001 From: Ryan Leavengood Date: Thu, 7 Mar 2013 22:04:02 -0500 Subject: [PATCH 104/104] Improve alignment and layout of the notifications. Implements diver's mockup from #8566. --- src/servers/notification/AppGroupView.cpp | 38 +++++++++++++------ src/servers/notification/AppGroupView.h | 1 + src/servers/notification/NotificationView.cpp | 5 ++- .../notification/NotificationWindow.cpp | 4 +- 4 files changed, 34 insertions(+), 14 deletions(-) diff --git a/src/servers/notification/AppGroupView.cpp b/src/servers/notification/AppGroupView.cpp index 450476f80a..0927d16426 100644 --- a/src/servers/notification/AppGroupView.cpp +++ b/src/servers/notification/AppGroupView.cpp @@ -23,7 +23,7 @@ #include "NotificationView.h" -static const int kHeaderSize = 20; +static const int kHeaderSize = 23; AppGroupView::AppGroupView(NotificationWindow* win, const char* label) @@ -61,13 +61,15 @@ AppGroupView::Draw(BRect updateRect) // Draw the buttons fCollapseRect.top = (kHeaderSize - kExpandSize) / 2; - fCollapseRect.left = kEdgePadding * 2; + fCollapseRect.left = kEdgePadding * 3; fCollapseRect.right = fCollapseRect.left + 1.5 * kExpandSize; fCollapseRect.bottom = fCollapseRect.top + kExpandSize; fCloseRect = bounds; - fCloseRect.top = (kHeaderSize - kExpandSize) / 2; - fCloseRect.right -= kEdgePadding * 2; + fCloseRect.top = (kHeaderSize - kCloseSize) / 2; + // Take off the 1 to line this up with the close button on the + // notification view + fCloseRect.right -= kEdgePadding * 3 - 1; fCloseRect.left = fCloseRect.right - kCloseSize; fCloseRect.bottom = fCloseRect.top + kCloseSize; @@ -88,9 +90,13 @@ AppGroupView::Draw(BRect updateRect) label << " (" << fInfo.size() << ")"; SetFont(be_bold_font); + font_height fontHeight; + GetFontHeight(&fontHeight); + float y = (bounds.top + bounds.bottom - ceilf(fontHeight.ascent) + - ceilf(fontHeight.descent)) / 2.0 + ceilf(fontHeight.ascent); - DrawString(label.String(), BPoint(fCollapseRect.right + 2 * kEdgePadding, - fCloseRect.bottom)); + DrawString(label.String(), + BPoint(fCollapseRect.right + 4 * kEdgePadding, y)); } @@ -98,11 +104,7 @@ void AppGroupView::_DrawCloseButton(const BRect& updateRect) { PushState(); - BRect closeRect = Bounds(); - - closeRect.InsetBy(7, 7); - closeRect.left = closeRect.right - kCloseSize; - closeRect.bottom = closeRect.top + kCloseSize; + BRect closeRect = fCloseRect; rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); float tint = B_DARKEN_2_TINT; @@ -225,6 +227,13 @@ AppGroupView::AddInfo(NotificationView* view) } } + // Invalidate all children to show or hide the close buttons in the + // notification view + int32 children = fInfo.size(); + for (int32 i = 0; i < children; i++) { + fInfo[i]->Invalidate(); + } + if (!found) { fInfo.push_back(view); } @@ -249,3 +258,10 @@ AppGroupView::HasChildren() { return !fInfo.empty(); } + + +int32 +AppGroupView::ChildrenCount() +{ + return fInfo.size(); +} diff --git a/src/servers/notification/AppGroupView.h b/src/servers/notification/AppGroupView.h index 10f9e60cc2..c3cbeac18e 100644 --- a/src/servers/notification/AppGroupView.h +++ b/src/servers/notification/AppGroupView.h @@ -29,6 +29,7 @@ public: void Draw(BRect updateRect); bool HasChildren(); + int32 ChildrenCount(); void AddInfo(NotificationView* view); diff --git a/src/servers/notification/NotificationView.cpp b/src/servers/notification/NotificationView.cpp index f5a2994fe2..b88e5de99f 100644 --- a/src/servers/notification/NotificationView.cpp +++ b/src/servers/notification/NotificationView.cpp @@ -29,6 +29,7 @@ #include #include +#include "AppGroupView.h" #include "NotificationWindow.h" @@ -273,7 +274,9 @@ NotificationView::Draw(BRect updateRect) rgb_color detailCol = ui_color(B_CONTROL_BORDER_COLOR); detailCol = tint_color(detailCol, B_LIGHTEN_2_TINT); - _DrawCloseButton(updateRect); + AppGroupView* groupView = dynamic_cast(Parent()); + if (groupView != NULL && groupView->ChildrenCount() > 1) + _DrawCloseButton(updateRect); SetHighColor(tint_color(ViewColor(), B_DARKEN_1_TINT)); BPoint left(Bounds().left, Bounds().top); diff --git a/src/servers/notification/NotificationWindow.cpp b/src/servers/notification/NotificationWindow.cpp index 068048bee3..73053e2058 100644 --- a/src/servers/notification/NotificationWindow.cpp +++ b/src/servers/notification/NotificationWindow.cpp @@ -376,11 +376,11 @@ NotificationWindow::SetPosition() break; case B_DESKBAR_RIGHT_TOP: x = frame.left - width - rightOffset; - y = frame.top - topOffset; + y = frame.top - topOffset + 1; break; case B_DESKBAR_LEFT_TOP: x = frame.right + leftOffset; - y = frame.top - topOffset; + y = frame.top - topOffset + 1; break; case B_DESKBAR_RIGHT_BOTTOM: y = frame.bottom - height + bottomOffset;