Ticket #2185: src_preferences_screensaver_ScreenSaverApp.cpp.diff

File src_preferences_screensaver_ScreenSaverApp.cpp.diff, 7.4 KB (added by kaoutsis, 16 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 <Node.h>
    1520#include <Path.h>
    1621
    1722#include <stdio.h>
     
    1924#include <unistd.h>
    2025
    2126
     27static status_t
     28CopyData(BFile& srcFile, BFile& dstFile)
     29{   
     30    char buffer[4096];
     31
     32    while (true) {
     33        ssize_t bytesRead = srcFile.Read(buffer, sizeof(buffer));
     34        if (bytesRead > 0) {
     35            ssize_t bytesWritten = dstFile.Write(buffer, bytesRead);
     36            if (bytesWritten < 0)
     37                return bytesWritten;
     38        } else if (bytesRead < 0)
     39            return bytesRead;
     40        else
     41            break;
     42    }
     43
     44    return B_OK;
     45}
     46
     47
     48static status_t
     49CopyAttributes(BNode& srcNode, BNode& dstNode)
     50{
     51    srcNode.RewindAttrs();
     52    char name[B_ATTR_NAME_LENGTH];
     53    while (srcNode.GetNextAttrName(name) == B_OK) {
     54        attr_info info;
     55        if (srcNode.GetAttrInfo(name, &info) == B_OK) {
     56            char buffer[info.size];
     57
     58            ssize_t bytesRead = srcNode.ReadAttr(name, info.type, 0, buffer, info.size);
     59            if (bytesRead > 0) {
     60                ssize_t bytesWritten = dstNode.WriteAttr(name, info.type, 0,
     61                    buffer, info.size);
     62                if (bytesWritten < 0)
     63                    return bytesWritten;
     64            } else
     65                return bytesRead;
     66        }
     67    }
     68
     69    return B_OK;       
     70}
     71
     72
     73static status_t
     74CopyScreenSaver(BFile& srcFile, BFile& dstFile)
     75{
     76    status_t status = CopyData(srcFile, dstFile);
     77    if (status < B_OK)
     78        return status;
     79       
     80    return CopyAttributes(srcFile, dstFile);
     81}
     82
     83
    2284class ScreenSaverApp : public BApplication {
    2385    public:
    2486        ScreenSaverApp();
     
    40102void
    41103ScreenSaverApp::RefsReceived(BMessage *message)
    42104{
    43     entry_ref ref;
    44     if (message->FindRef("refs", &ref) != B_OK)
    45         return;
    46105
    47106    // Install the screen saver by copying it to the add-ons directory
    48107    // TODO: the translator have a similar mechanism - this could be cleaned
    49108    //  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...
    52109
    53     BEntry entry;
    54     entry.SetTo(&ref, true);
    55     if (entry.InitCheck() != B_OK)
    56         return;
     110    int32 index = 0;
     111    entry_ref ref;
    57112
    58     BPath path;
    59     entry.GetPath(&path);
     113    while (message->FindRef("refs", index++, &ref) == B_OK) {
     114        BEntry srcEntry;
     115        srcEntry.SetTo(&ref, true);
    60116
    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);
     117        if (srcEntry.InitCheck() != B_OK)
     118            return;
     119
     120        BPath srcPath;
     121        srcEntry.GetPath(&srcPath);
     122
     123        if (srcEntry.IsDirectory()) {
     124            BString errorMessage;
     125            errorMessage << srcPath.Leaf() << " is a directory!\n";
     126            errorMessage << "You can not install a directory!";
     127            (new BAlert("AlertError", errorMessage.String(), "OK", NULL, NULL,
     128                B_WIDTH_AS_USUAL, B_INFO_ALERT))->Go();
     129            return;
     130        }
     131
     132        BFile srcFile(srcPath.Path(), O_RDONLY);
     133        if (srcFile.InitCheck() != B_OK)
     134            return;
     135
     136        // Check if the file in question is really a screensaver
     137        // (with some acrobatics!)
     138
     139        // First check for black-listed files:
     140        // binary files that contains the string 'StartSaver'
     141        // libscreensaver.so, ScreenSaver, screen_blanker
     142        // without being really screensavers, and the
     143        // user may try to throw in the ScreenSaver pref. window
     144
     145        BString blackListed1("libscreensaver.so");
     146        BString blackListed2("ScreenSaver");
     147        BString blackListed3("screen_blanker");
     148
     149        BString candidateScr(srcPath.Leaf());
     150
     151        if (candidateScr == blackListed1
     152            || candidateScr == blackListed2
     153            || candidateScr == blackListed3) {
     154            BString errorMessage;
     155            errorMessage << "File " << srcPath.Leaf() << "\n";
     156            errorMessage << "is not a screensaver file!";
     157            (new BAlert("AlertError", errorMessage.String(), "OK", NULL, NULL,
     158                B_WIDTH_AS_USUAL, B_INFO_ALERT))->Go();
     159            return;
     160        }   
     161
     162        // Check all the other files
     163
     164        off_t location = 0;
     165        bool isFileScreenSaver = false;
     166        uint32 kBytesToRead = 4096;
     167        uint32 kNumOfTries = 20;
     168        char buffer[kNumOfTries * kBytesToRead];
     169        ssize_t bytesRead;
     170
     171        while (kNumOfTries) {
     172            bytesRead = srcFile.ReadAt(location, buffer + location, kBytesToRead);
     173            if (bytesRead < B_OK) {
     174                BString errorMessage;
     175                errorMessage << "At " << __PRETTY_FUNCTION__ << "\n";
     176                errorMessage << "failed to examine file " << srcPath.Leaf() << "\n";
     177                errorMessage << "Reason: " << strerror(bytesRead);
     178                (new BAlert("AlertError", errorMessage.String(), "OK", NULL, NULL,
     179                    B_WIDTH_AS_USUAL, B_STOP_ALERT))->Go();
     180                return;
     181            }
     182
     183            for (uint32 index = 0; index < kBytesToRead; index++) {
     184                if (buffer[location + index] == '\0')
     185                    buffer[location + index] = 'a';
     186            }
     187
     188            const char stringToFind[] = "StartSaver";
     189            if (char* foundAddress = strstr(buffer, stringToFind)) {
     190                isFileScreenSaver = true;
     191                memset(foundAddress, 'a', strlen(stringToFind));
     192                break;
     193            }
     194
     195            location += kBytesToRead;
     196            kNumOfTries--;
     197        }
     198
     199        if (!isFileScreenSaver) {
     200            BString errorMessage;
     201            errorMessage << "File " << srcPath.Leaf() << "\n";
     202            errorMessage << "is not a screensaver file!";
     203            (new BAlert("AlertError", errorMessage.String(), "OK", NULL, NULL,
     204                B_WIDTH_AS_USUAL, B_INFO_ALERT))->Go();
     205            return;
     206        }
     207
     208        BPath userNewScreenSaver;
     209        status_t status = find_directory(B_USER_ADDONS_DIRECTORY,
     210            &userNewScreenSaver);
     211        if (status < B_OK) {
     212            BString errorMessage;
     213            errorMessage << "At " << __PRETTY_FUNCTION__ << "\n";
     214            errorMessage << "find_directory() failed. \nReason: ";
     215            errorMessage << strerror(status);
     216            (new BAlert("AlertError", errorMessage.String(), "OK", NULL, NULL,
     217                B_WIDTH_AS_USUAL, B_STOP_ALERT))->Go();
     218            return;
     219        }
     220
     221        userNewScreenSaver.Append("Screen Savers");
     222        userNewScreenSaver.Append(srcPath.Leaf());
     223
     224        BFile destFile(userNewScreenSaver.Path(), O_RDWR | O_CREAT);
     225        if (destFile.InitCheck() != B_OK)
     226            return;
     227
     228        status = CopyScreenSaver(srcFile, destFile);
     229        if (status < B_OK) {
     230            BString errorMessage;
     231            errorMessage << "At " << __PRETTY_FUNCTION__ << "\n";
     232            errorMessage << "Copying the screensaver file failed. \nReason: ";
     233            errorMessage << strerror(status);
     234            (new BAlert("AlertError", errorMessage.String(), "OK", NULL, NULL,
     235                B_WIDTH_AS_USUAL, B_STOP_ALERT))->Go();
     236            return;
     237        }
     238
     239        fScreenSaverWindow->PostMessage(kMsgUpdateList);   
     240    }
    66241}
    67242
    68243
  • src/preferences/screensaver/ScreenSaverWindow.cpp

     
    834834void
    835835ScreenSaverWindow::MessageReceived(BMessage *msg)
    836836{
     837    uint32 type;
     838    int32 count;
     839
     840    // one or more screensavers have been dropped
     841    // into the window; inform the application
     842    // in order to take care the installation
     843    switch (msg->what) {
     844        case B_SIMPLE_DATA:
     845            msg->GetInfo("refs", &type, &count);
     846            if (count > 0 && type == B_REF_TYPE) {
     847                msg->what = B_REFS_RECEIVED;
     848                be_app->PostMessage(msg);
     849            }
     850            break;
     851    }
     852
     853
    837854    // "Fade" tab, slider updates
    838855
    839856    switch (msg->what) {