Ticket #2185: src_preferences_screensaver_ScreenSaverApp.cpp.2.diff

File src_preferences_screensaver_ScreenSaverApp.cpp.2.diff, 9.4 KB (added by kaoutsis, 11 years ago)
  • src/preferences/screensaver/ScreenSaverApp.cpp

     
    1010
    1111#include "ScreenSaverWindow.h"
    1212
     13#include <Alert.h>
    1314#include <Application.h>
    1415#include <Entry.h>
     16#include <File.h>
     17#include <FindDirectory.h>
     18#include <kernel/fs_attr.h>
     19#include <kernel/image.h>
     20#include <Node.h>
     21#include <NodeMonitor.h>
    1522#include <Path.h>
     23#include <ScreenSaver.h>
    1624
    1725#include <stdio.h>
    1826#include <stdlib.h>
    1927#include <unistd.h>
    2028
    2129
     30static status_t
     31CopyData(BFile& srcFile, BFile& dstFile)
     32{   
     33    char buffer[4096];
     34
     35    while (true) {
     36        ssize_t bytesRead = srcFile.Read(buffer, sizeof(buffer));
     37        if (bytesRead > 0) {
     38            ssize_t bytesWritten = dstFile.Write(buffer, bytesRead);
     39            if (bytesWritten < 0)
     40                return bytesWritten;
     41        } else if (bytesRead < 0)
     42            return bytesRead;
     43        else
     44            break;
     45    }
     46
     47    return B_OK;
     48}
     49
     50
     51static status_t
     52CopyAttributes(BNode& srcNode, BNode& dstNode)
     53{
     54    srcNode.RewindAttrs();
     55    char name[B_ATTR_NAME_LENGTH];
     56    while (srcNode.GetNextAttrName(name) == B_OK) {
     57        attr_info info;
     58        if (srcNode.GetAttrInfo(name, &info) == B_OK) {
     59            char buffer[info.size];
     60
     61            ssize_t bytesRead = srcNode.ReadAttr(name, info.type, 0, buffer, info.size);
     62            if (bytesRead > 0) {
     63                ssize_t bytesWritten = dstNode.WriteAttr(name, info.type, 0,
     64                    buffer, info.size);
     65                if (bytesWritten < 0)
     66                    return bytesWritten;
     67            } else
     68                return bytesRead;
     69        }
     70    }
     71
     72    return B_OK;       
     73}
     74
     75
     76static status_t
     77CopyScreenSaver(BFile& srcFile, BFile& dstFile)
     78{
     79    status_t status = CopyData(srcFile, dstFile);
     80    if (status < B_OK)
     81        return status;
     82       
     83    return CopyAttributes(srcFile, dstFile);
     84}
     85
     86
    2287class ScreenSaverApp : public BApplication {
    2388    public:
    2489        ScreenSaverApp();
    2590        virtual void RefsReceived(BMessage *message);
     91        virtual void MessageReceived(BMessage *message);
    2692
    2793    private:
    2894        BWindow *fScreenSaverWindow;
     
    34100{
    35101    fScreenSaverWindow = new ScreenSaverWindow();
    36102    fScreenSaverWindow->Show();
     103   
     104    // monitor the user's addons directory
     105    BPath userAddonsScrDirPath;
     106    status_t status = find_directory(B_USER_ADDONS_DIRECTORY,
     107        &userAddonsScrDirPath);
     108    if (status == B_OK)
     109        status = userAddonsScrDirPath.Append("Screen Savers");
     110
     111    if (status < B_OK) {
     112        BString errorMessage;
     113        errorMessage << "At " << __PRETTY_FUNCTION__ << "\n";
     114        errorMessage << "find_directory() failed. \nReason: ";
     115        errorMessage << strerror(status);
     116        (new BAlert("AlertError", errorMessage.String(), "OK", NULL, NULL,
     117            B_WIDTH_AS_USUAL, B_STOP_ALERT))->Go();
     118        return;
     119    }
     120
     121    BEntry userAddonsScrDirEntry(userAddonsScrDirPath.Path());
     122    node_ref nodeRef;
     123    userAddonsScrDirEntry.GetNodeRef(&nodeRef);
     124    status = watch_node(&nodeRef, B_WATCH_DIRECTORY, this);
     125    if (status != B_OK)
     126        fprintf(stderr, "Could not start watching: %s\n", strerror(status));
    37127}
    38128
    39129
     130void
     131ScreenSaverApp::MessageReceived(BMessage* message)
     132{
     133    switch (message->what) {
     134        case B_NODE_MONITOR:
     135            fScreenSaverWindow->PostMessage(kMsgUpdateList);
     136            break;
     137
     138        default:
     139            BApplication::MessageReceived(message);
     140            break;
     141    }
     142}
     143
     144
    40145void
    41146ScreenSaverApp::RefsReceived(BMessage *message)
    42147{
    43     entry_ref ref;
    44     if (message->FindRef("refs", &ref) != B_OK)
    45         return;
    46148
    47149    // Install the screen saver by copying it to the add-ons directory
    48150    // TODO: the translator have a similar mechanism - this could be cleaned
    49151    //  up and have one nicely working solution
    50     // TODO: should test if the dropped ref is really a screen saver!
    51     // TODO: you can receive more than one ref at a time...
    52152
    53     BEntry entry;
    54     entry.SetTo(&ref, true);
    55     if (entry.InitCheck() != B_OK)
    56         return;
     153    int32 index = 0;
     154    entry_ref ref;
    57155
    58     BPath path;
    59     entry.GetPath(&path);
     156    while (message->FindRef("refs", index++, &ref) == B_OK) {
     157        BEntry srcEntry;
     158        srcEntry.SetTo(&ref, true);
    60159
    61     // TODO: find_directory() anyone??
    62     char temp[2*B_PATH_NAME_LENGTH];
    63     sprintf(temp,"cp %s '/boot/home/config/add-ons/Screen Savers/'\n", path.Path());
    64     system(temp);
    65     fScreenSaverWindow->PostMessage(kMsgUpdateList);
     160        if (srcEntry.InitCheck() != B_OK)
     161            return;
     162
     163        BPath srcPath;
     164        srcEntry.GetPath(&srcPath);
     165
     166        if (srcEntry.IsDirectory()) {
     167            BString errorMessage;
     168            errorMessage << srcPath.Leaf() << " is a directory!\n";
     169            errorMessage << "You can not install a directory!";
     170            (new BAlert("AlertError", errorMessage.String(), "OK", NULL, NULL,
     171                B_WIDTH_AS_USUAL, B_INFO_ALERT))->Go();
     172            return;
     173        }
     174
     175        BFile srcFile(srcPath.Path(), O_RDONLY);
     176        if (srcFile.InitCheck() != B_OK)
     177            return;
     178
     179        // Check if the file in question is really a screensaver
     180
     181        // First check for black-listed files:
     182        // binary files that may crash the ScreenSaver pref.
     183        // without being really screensavers, and the
     184        // user may try to throw in the ScreenSaver pref. window
     185
     186        BString blackListed1("libroot.so");
     187        BString blackListed2("runtime_loader");
     188
     189        BString candidateScr(srcPath.Leaf());
     190
     191        if (candidateScr == blackListed1
     192            || candidateScr == blackListed2) {
     193            BString errorMessage;
     194            errorMessage << "File " << srcPath.Leaf() << "\n";
     195            errorMessage << "is not a screensaver file!";
     196            (new BAlert("AlertError", errorMessage.String(), "OK", NULL, NULL,
     197                B_WIDTH_AS_USUAL, B_INFO_ALERT))->Go();
     198            continue;
     199        }   
     200
     201
     202        // Check all the other files
     203
     204        image_id candidateScreenSaverId = load_add_on(srcPath.Path());
     205        if (candidateScreenSaverId < B_OK) {
     206            BString errorMessage;
     207            errorMessage << "File " << srcPath.Leaf() << "\n";
     208            errorMessage << "is not a screensaver file!";
     209            (new BAlert("AlertError", errorMessage.String(), "OK", NULL, NULL,
     210                B_WIDTH_AS_USUAL, B_INFO_ALERT))->Go();
     211
     212            unload_add_on(candidateScreenSaverId);
     213            continue;
     214        }
     215
     216        BScreenSaver* (*instantiate)(BMessage* msg, image_id image);
     217        status_t getImageSymbolStatus = get_image_symbol(candidateScreenSaverId,
     218            "instantiate_screen_saver", B_SYMBOL_TYPE_TEXT, (void**)&instantiate);
     219        unload_add_on(candidateScreenSaverId);
     220
     221        if (getImageSymbolStatus < B_OK) {
     222            BString errorMessage;
     223            errorMessage << "File " << srcPath.Leaf() << "\n";
     224            errorMessage << "is not a screensaver file!";
     225            (new BAlert("AlertError", errorMessage.String(), "OK", NULL, NULL,
     226                B_WIDTH_AS_USUAL, B_INFO_ALERT))->Go();
     227            continue;
     228        }
     229
     230        BPath userNewScreenSaver;
     231        status_t status = find_directory(B_USER_ADDONS_DIRECTORY,
     232            &userNewScreenSaver);
     233        if (status < B_OK) {
     234            BString errorMessage;
     235            errorMessage << "At " << __PRETTY_FUNCTION__ << "\n";
     236            errorMessage << "find_directory() failed. \nReason: ";
     237            errorMessage << strerror(status);
     238            (new BAlert("AlertError", errorMessage.String(), "OK", NULL, NULL,
     239                B_WIDTH_AS_USUAL, B_STOP_ALERT))->Go();
     240            return;
     241        }
     242
     243        userNewScreenSaver.Append("Screen Savers");
     244        userNewScreenSaver.Append(srcPath.Leaf());
     245
     246        BFile destFile(userNewScreenSaver.Path(), O_RDWR | O_CREAT);
     247        if (destFile.InitCheck() != B_OK)
     248            return;
     249
     250        status = CopyScreenSaver(srcFile, destFile);
     251        if (status < B_OK) {
     252            BString errorMessage;
     253            errorMessage << "At " << __PRETTY_FUNCTION__ << "\n";
     254            errorMessage << "Copying the screensaver file failed. \nReason: ";
     255            errorMessage << strerror(status);
     256            (new BAlert("AlertError", errorMessage.String(), "OK", NULL, NULL,
     257                B_WIDTH_AS_USUAL, B_STOP_ALERT))->Go();
     258            return;
     259        }
     260
     261        fScreenSaverWindow->PostMessage(kMsgUpdateList);   
     262    }
    66263}
    67264
    68265
  • src/preferences/screensaver/ScreenSaverWindow.cpp

     
    417417            BPath path = basePath;
    418418            path.Append(name);
    419419
     420            // Before adding the item in the list,
     421            // check if the file in question is really a screensaver.
     422
     423            // First check for black-listed files:
     424            // binary files that may crash the ScreenSaver pref.
     425            // without being really screensavers, and the
     426            // user may try to throw in the ScreenSaver pref. window
     427
     428            BString blackListed1("libroot.so");
     429            BString blackListed2("runtime_loader");
     430
     431            BString candidateScr(path.Leaf());
     432
     433            if (candidateScr == blackListed1
     434                || candidateScr == blackListed2)
     435            continue;
     436
     437            // Check all the other files
     438
     439            image_id candidateScreenSaverId = load_add_on(path.Path());
     440            if (candidateScreenSaverId < B_OK) {
     441                unload_add_on(candidateScreenSaverId);
     442                continue;
     443            }
     444
     445            BScreenSaver* (*instantiate)(BMessage* msg, image_id image);
     446            status_t getImageSymbolStatus = get_image_symbol(candidateScreenSaverId,
     447                "instantiate_screen_saver", B_SYMBOL_TYPE_TEXT, (void**)&instantiate);
     448            unload_add_on(candidateScreenSaverId);
     449
     450            if (getImageSymbolStatus < B_OK)
     451                continue;
     452
    420453            ScreenSaverItem* item = new ScreenSaverItem(name, path.Path());
    421454            fListView->AddItem(item);
    422455           
     
    834867void
    835868ScreenSaverWindow::MessageReceived(BMessage *msg)
    836869{
     870    uint32 type;
     871    int32 count;
     872
     873    // one or more screensavers have been dropped
     874    // into the window; inform the application
     875    // in order to take care the installation
     876    switch (msg->what) {
     877        case B_SIMPLE_DATA:
     878            msg->GetInfo("refs", &type, &count);
     879            if (count > 0 && type == B_REF_TYPE) {
     880                msg->what = B_REFS_RECEIVED;
     881                be_app->PostMessage(msg);
     882            }
     883            break;
     884    }
     885
     886
    837887    // "Fade" tab, slider updates
    838888
    839889    switch (msg->what) {