Work in progress of mail rework.

* Not everything compiles; all protocols, and inbound filters do, though.
* Renamed a few classes to give a better idea what they are for; prefixed
  public classes with the 'B' prefix.
* Moved ProtocolConfigView's classes into the BPrivate namespace.
* Moved BMailFilter into its own file.
* Added BMailFilter::DescriptiveName(). This is now used by the RuleFilter
  in order to give a description of what it's doing (ie. no more dozens of
  "Rule filter" entries in the preferences).
* Removed no longer used MailAddon.h.
* Renamed Addon to AddOn where found, since that is more consistent with the
  rest of the API.
* Merged the former MailProtocol with the former MailProtocolThread; the
  differentiation between those two was pretty messy.
* All configuration views touched so far are now using the layout kit.
* The RuleFilter is currently broken functionality wise; I have not yet decided
  how to solve the stuff it uses (TriggerFileMove() does not exist anymore,
  for example).
* BMailAddOnSettings (formerly known as AddonSettings) now directly subclass
  BMessage; there are no Settings() and EditSettings() method anymore. The
  class uses a copy of itself to determine whether or not it has been changed.
* Lots of cleanup.
This commit is contained in:
Axel Dörfler
2015-01-06 15:21:36 +01:00
parent 0f11280e6d
commit 715bf3d17a
32 changed files with 1756 additions and 2508 deletions
@@ -1,74 +0,0 @@
/* Filter - the base class for all mail filters
**
** Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved.
*/
#ifndef ZOIDBERG_MAIL_ADDON_H
#define ZOIDBERG_MAIL_ADDON_H
#include "MailProtocol.h"
#include "MailSettings.h"
class BView;
//
// The addon interface: export instantiate_mailfilter()
// and instantiate_mailconfig() to create a Filter addon
//
extern "C" _EXPORT InboundProtocol* instantiate_inbound_protocol(
BMailAccountSettings* settings);
extern "C" _EXPORT OutboundProtocol* instantiate_outbound_protocol(
BMailAccountSettings* settings);
extern "C" _EXPORT BView* instantiate_config_panel(MailAddonSettings&,
BMailAccountSettings&);
// return a view that configures the MailProtocol
// returned by the functions below. BView::Archive(foo,true)
// produces this addon's settings, which are passed to the in-
// stantiate_* functions and stored persistently. This function
// should gracefully handle empty and NULL settings.
extern "C" _EXPORT BView* instantiate_filter_config_panel(AddonSettings&);
extern "C" _EXPORT MailFilter* instantiate_mailfilter(MailProtocol& protocol,
AddonSettings* settings);
extern "C" _EXPORT BString descriptive_name();
// the config panel will show this name in the chains filter
// list if this function returns B_OK.
// The buffer is as big as B_FILE_NAME_LENGTH.
// standard Filters:
//
// * Parser - does ParseRFC2822(io_message,io_headers)
// * Folder - stores the message in the specified folder,
// optionally under io_folder, returns MD_HANDLED
// * HeaderFilter(regex,Yes_fiters,No_filters) -
// Applies Nes_filters to messages that have a header
// matching regex; applies No_filters otherwise.
// * CompatabilityFilter - Invokes the standard mail_dae-
// mon filter ~/config/settings/add-ons/MailDaemon/Filter
// on the message's Entry.
// * Producer - Reads outbound messages from disk and inserts
// them into the queue.
// * SMTPSender - Sends the message, via the specified
// SMTP server, to the people in header field
// "MAIL:recipients", changes the the Entry's
// "MAIL:flags" field to no longer pending, changes the
// "MAIL:status" header field to "Sent", and adds a header
// field "MAIL:when" with the time it was sent.
// * Dumper - returns MD_DISCARD
//
//
// Standard chain types:
//
// Incoming Mail: Protocol - Parser - Notifier - Folder
// Outgoing Mail: Producer - SMTPSender
//
// "chains" are lists of addons that appear in, or can be
// added to, the "Accounts" list in the config panel, a tree-
// view ordered by the chain type and the chain's AccountName().
// Their config views should be shown, one after the other,
// in the config panel.
#endif /* ZOIDBERG_MAIL_ADDON_H */
@@ -0,0 +1,50 @@
/*
* Copyright 2011-2012, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef MAIL_FILTER_H
#define MAIL_FILTER_H
#include "MailProtocol.h"
#include "MailSettings.h"
class BMailProtocol;
class BView;
class BMailFilter {
public:
BMailFilter(BMailProtocol& protocol,
BMailAddOnSettings* settings);
virtual ~BMailFilter();
virtual BString DescriptiveName() const = 0;
// Message hooks if filter is installed to an inbound protocol
virtual void HeaderFetched(const entry_ref& ref,
BFile* file);
virtual void BodyFetched(const entry_ref& ref, BFile* file);
virtual void MailboxSynchronized(status_t status);
// Message hooks if filter is installed to an outbound protocol
virtual void MessageReadyToSend(const entry_ref& ref,
BFile* file);
virtual void MessageSent(const entry_ref& ref,
BFile* file);
protected:
BMailProtocol& fMailProtocol;
BMailAddOnSettings* fSettings;
};
// Your filter needs to export these hooks in order to be picked up
extern "C" BView* instantiate_filter_config_panel(BMailAddOnSettings& settings);
extern "C" BMailFilter* instantiate_filter(BMailProtocol& protocol,
BMailAddOnSettings* settings);
extern "C" BString filter_name();
#endif // MAIL_FILTER_H
+69 -141
View File
@@ -21,6 +21,9 @@
#include <MailSettings.h> #include <MailSettings.h>
class BMailFilter;
class BMailNotifier { class BMailNotifier {
public: public:
virtual ~BMailNotifier() {} virtual ~BMailNotifier() {}
@@ -38,71 +41,47 @@ public:
}; };
class MailProtocol; class BMailProtocol : BLooper {
class MailFilter {
public: public:
MailFilter(MailProtocol& protocol, BMailProtocol(
AddonSettings* settings); const BMailAccountSettings& settings);
virtual ~MailFilter(); virtual ~BMailProtocol();
//! Message hooks if filter is installed to an inbound protocol const BMailAccountSettings& AccountSettings() const;
virtual void HeaderFetched(const entry_ref& ref,
BFile* file);
virtual void BodyFetched(const entry_ref& ref, BFile* file);
virtual void MailboxSynced(status_t status);
//! Message hooks if filter is installed to an outbound protocol
virtual void MessageReadyToSend(const entry_ref& ref,
BFile* file);
virtual void MessageSent(const entry_ref& ref,
BFile* file);
protected:
MailProtocol& fMailProtocol;
AddonSettings* fAddonSettings;
};
class MailProtocolThread;
class MailProtocol {
public:
MailProtocol(BMailAccountSettings* settings);
virtual ~MailProtocol();
virtual void SetStopNow() {}
BMailAccountSettings& AccountSettings();
void SetProtocolThread(
MailProtocolThread* protocolThread);
virtual void AddedToLooper() {}
MailProtocolThread* Looper();
/*! Add handler to the handler list. The handler is installed /
removed to the according BLooper automatically. */
bool AddHandler(BHandler* handler);
//! Does not delete handler
bool RemoveHandler(BHandler* handler);
void SetMailNotifier(BMailNotifier* mailNotifier); void SetMailNotifier(BMailNotifier* mailNotifier);
BMailNotifier* MailNotifier() const;
virtual void ShowError(const char* error); //! We take ownership of the filters
virtual void ShowMessage(const char* message); bool AddFilter(BMailFilter* filter);
virtual void SetTotalItems(int32 items); int32 CountFilter() const;
virtual void SetTotalItemsSize(int32 size); BMailFilter* FilterAt(int32 index) const;
virtual void ReportProgress(int bytes, int messages, BMailFilter* RemoveFilter(int32 index);
bool RemoveFilter(BMailFilter* filter);
virtual void MessageReceived(BMessage* message);
// Mail storage operations
virtual status_t MoveMessage(const entry_ref& ref,
BDirectory& dir);
virtual status_t DeleteMessage(const entry_ref& ref);
virtual void FileRenamed(const entry_ref& from,
const entry_ref& to);
virtual void FileDeleted(const node_ref& node);
// Convenience methods that call the BMailNotifier
void ShowError(const char* error);
void ShowMessage(const char* message);
protected:
void SetTotalItems(uint32 items);
void SetTotalItemsSize(uint64 size);
void ReportProgress(uint32 messages, uint64 bytes,
const char* message = NULL); const char* message = NULL);
virtual void ResetProgress(const char* message = NULL); void ResetProgress(const char* message = NULL);
//! MailProtocol takes ownership of the filters
bool AddFilter(MailFilter* filter);
int32 CountFilter();
MailFilter* FilterAt(int32 index);
MailFilter* RemoveFilter(int32 index);
bool RemoveFilter(MailFilter* filter);
// Filter notifications
void NotifyNewMessagesToFetch(int32 nMessages); void NotifyNewMessagesToFetch(int32 nMessages);
void NotifyHeaderFetched(const entry_ref& ref, void NotifyHeaderFetched(const entry_ref& ref,
BFile* mail); BFile* mail);
@@ -113,35 +92,29 @@ public:
void NotifyMessageSent(const entry_ref& ref, void NotifyMessageSent(const entry_ref& ref,
BFile* mail); BFile* mail);
//! mail storage operations void LoadFilters(
virtual status_t MoveMessage(const entry_ref& ref, const BMailProtocolSettings& settings);
BDirectory& dir);
virtual status_t DeleteMessage(const entry_ref& ref);
virtual void FileRenamed(const entry_ref& from, private:
const entry_ref& to); BMailFilter* _LoadFilter(BMailAddOnSettings* filterSettings);
virtual void FileDeleted(const node_ref& node);
protected: protected:
void LoadFilters(MailAddonSettings& settings); const BMailAccountSettings fAccountSettings;
BMailAccountSettings fAccountSettings;
BMailNotifier* fMailNotifier; BMailNotifier* fMailNotifier;
private: private:
MailFilter* _LoadFilter(AddonSettings* filterSettings); BObjectList<BMailFilter> fFilterList;
std::map<entry_ref, image_id> fFilterImages;
MailProtocolThread* fProtocolThread;
BObjectList<BHandler> fHandlerList;
BObjectList<MailFilter> fFilterList;
std::map<entry_ref, image_id> fFilterImages;
}; };
class InboundProtocol : public MailProtocol { class BInboundMailProtocol : public BMailProtocol {
public: public:
InboundProtocol(BMailAccountSettings* settings); BInboundMailProtocol(
virtual ~InboundProtocol(); const BMailAccountSettings& settings);
virtual ~BInboundMailProtocol();
virtual void MessageReceived(BMessage* message);
virtual status_t SyncMessages() = 0; virtual status_t SyncMessages() = 0;
virtual status_t FetchBody(const entry_ref& ref) = 0; virtual status_t FetchBody(const entry_ref& ref) = 0;
@@ -149,78 +122,33 @@ public:
read_flags flag = B_READ); read_flags flag = B_READ);
virtual status_t DeleteMessage(const entry_ref& ref) = 0; virtual status_t DeleteMessage(const entry_ref& ref) = 0;
virtual status_t AppendMessage(const entry_ref& ref); virtual status_t AppendMessage(const entry_ref& ref);
protected:
void NotiyMailboxSynchronized(status_t status);
}; };
class OutboundProtocol : public MailProtocol { class BOutboundMailProtocol : public BMailProtocol {
public: public:
OutboundProtocol( BOutboundMailProtocol(
BMailAccountSettings* settings); const BMailAccountSettings& settings);
virtual ~OutboundProtocol(); virtual ~BOutboundMailProtocol();
virtual status_t SendMessages(const std::vector<entry_ref>& virtual void MessageReceived(BMessage* message);
mails, size_t totalBytes) = 0;
virtual status_t SendMessages(
const std::vector<entry_ref>& mails,
size_t totalBytes) = 0;
}; };
class MailProtocolThread : public BLooper { // Your protocol needs to export these hooks in order to be picked up
public: extern "C" _EXPORT BInboundMailProtocol* instantiate_inbound_protocol(
MailProtocolThread(MailProtocol* protocol); const BMailAccountSettings& settings);
virtual void MessageReceived(BMessage* message); extern "C" _EXPORT BOutboundMailProtocol* instantiate_outbound_protocol(
const BMailAccountSettings& settings);
MailProtocol* Protocol() { return fMailProtocol; } extern "C" _EXPORT BView* instantiate_protocol_config_panel(
BMailAccountSettings& settings);
void SetStopNow();
/*! These function post a message to the loop to trigger the action.
*/
void TriggerFileMove(const entry_ref& ref,
BDirectory& dir);
void TriggerFileDeletion(const entry_ref& ref);
void TriggerFileRenamed(const entry_ref& from,
const entry_ref& to);
void TriggerFileDeleted(const node_ref& node);
private:
MailProtocol* fMailProtocol;
};
class InboundProtocolThread : public MailProtocolThread {
public:
InboundProtocolThread(
InboundProtocol* protocol);
~InboundProtocolThread();
void MessageReceived(BMessage* message);
void SyncMessages();
void FetchBody(const entry_ref& ref,
BMessenger* listener = NULL);
void MarkMessageAsRead(const entry_ref& ref,
read_flags flag = B_READ);
void DeleteMessage(const entry_ref& ref);
void AppendMessage(const entry_ref& ref);
private:
void _NotiyMailboxSynced(status_t status);
InboundProtocol* fProtocol;
};
class OutboundProtocolThread : public MailProtocolThread {
public:
OutboundProtocolThread(
OutboundProtocol* protocol);
~OutboundProtocolThread();
void MessageReceived(BMessage* message);
void SendMessages(const std::vector<entry_ref>&
mails, size_t totalBytes);
private:
OutboundProtocol* fProtocol;
};
#endif // MAIL_PROTOCOL_H #endif // MAIL_PROTOCOL_H
@@ -1,9 +1,11 @@
/* ProtocolConfigView - the standard config view for all protocols /*
** * Copyright 2004-2012, Haiku Inc. All rights reserved.
** Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved. * Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved.
*/ *
#ifndef ZOIDBERG_PROTOCOL_CONFIG_VIEW_H * Distributed under the terms of the MIT License.
#define ZOIDBERG_PROTOCOL_CONFIG_VIEW_H */
#ifndef _PROTOCOL_CONFIG_VIEW_H
#define _PROTOCOL_CONFIG_VIEW_H
#include <CheckBox.h> #include <CheckBox.h>
@@ -11,19 +13,29 @@
#include <TextControl.h> #include <TextControl.h>
#include <View.h> #include <View.h>
#include "MailSettings.h" #include <MailSettings.h>
class BCheckBox;
class BGridLayout;
class BMenuField;
class BTextControl;
namespace BPrivate {
class BodyDownloadConfig : public BView { class BodyDownloadConfig : public BView {
public: public:
BodyDownloadConfig(); BodyDownloadConfig();
void SetTo(MailAddonSettings& settings); void SetTo(BMailProtocolSettings& settings);
void MessageReceived(BMessage *msg); void MessageReceived(BMessage* message);
void AttachedToWindow(); void AttachedToWindow();
void GetPreferredSize(float *width, float *height); void GetPreferredSize(float* width, float* height);
status_t Archive(BMessage *into, bool) const; status_t Archive(BMessage* into, bool deep = true) const;
private: private:
BTextControl* fSizeBox; BTextControl* fSizeBox;
BCheckBox* fPartialBox; BCheckBox* fPartialBox;
@@ -31,39 +43,64 @@ private:
}; };
typedef enum { enum mail_protocol_config_options {
B_MAIL_PROTOCOL_HAS_AUTH_METHODS = 1, B_MAIL_PROTOCOL_HAS_AUTH_METHODS = 1,
B_MAIL_PROTOCOL_HAS_FLAVORS = 2, B_MAIL_PROTOCOL_HAS_FLAVORS = 2,
B_MAIL_PROTOCOL_HAS_USERNAME = 4, B_MAIL_PROTOCOL_HAS_USERNAME = 4,
B_MAIL_PROTOCOL_HAS_PASSWORD = 8, B_MAIL_PROTOCOL_HAS_PASSWORD = 8,
B_MAIL_PROTOCOL_HAS_HOSTNAME = 16, B_MAIL_PROTOCOL_HAS_HOSTNAME = 16,
B_MAIL_PROTOCOL_CAN_LEAVE_MAIL_ON_SERVER = 32, B_MAIL_PROTOCOL_CAN_LEAVE_MAIL_ON_SERVER = 32,
B_MAIL_PROTOCOL_PARTIAL_DOWNLOAD = 64 B_MAIL_PROTOCOL_PARTIAL_DOWNLOAD = 64
} b_mail_protocol_config_options; };
class BMailProtocolConfigView : public BView { class MailProtocolConfigView : public BView {
public: public:
BMailProtocolConfigView(uint32 options_mask MailProtocolConfigView(uint32 optionsMask
= B_MAIL_PROTOCOL_HAS_FLAVORS = B_MAIL_PROTOCOL_HAS_FLAVORS
| B_MAIL_PROTOCOL_HAS_USERNAME | B_MAIL_PROTOCOL_HAS_USERNAME
| B_MAIL_PROTOCOL_HAS_PASSWORD | B_MAIL_PROTOCOL_HAS_PASSWORD
| B_MAIL_PROTOCOL_HAS_HOSTNAME); | B_MAIL_PROTOCOL_HAS_HOSTNAME);
virtual ~BMailProtocolConfigView(); virtual ~MailProtocolConfigView();
void SetTo(MailAddonSettings& archive); void SetTo(BMailProtocolSettings& settings);
void AddFlavor(const char *label); void AddFlavor(const char* label);
void AddAuthMethod(const char *label, void AddAuthMethod(const char* label,
bool needUserPassword = true); bool needUserPassword = true);
virtual status_t Archive(BMessage *into, bool deep = true) const; BGridLayout* Layout() const;
virtual void GetPreferredSize(float *width, float *height);
virtual status_t Archive(BMessage* into, bool deep = true) const;
virtual void AttachedToWindow(); virtual void AttachedToWindow();
virtual void MessageReceived(BMessage *msg); virtual void MessageReceived(BMessage* message);
private: private:
BTextControl* _AddTextControl(BGridLayout* layout,
const char* name, const char* label);
BMenuField* _AddMenuField(BGridLayout* layout,
const char* name, const char* label);
void _StoreIndexOfMarked(BMessage& message,
const char* name, BMenuField* field) const;
void _StoreCheckBox(BMessage& message,
const char* name,
BCheckBox* checkBox) const;
void _SetCredentialsEnabled(bool enabled);
private:
BTextControl* fHostControl;
BTextControl* fUserControl;
BTextControl* fPasswordControl;
BMenuField* fFlavorField;
BMenuField* fAuthenticationField;
BCheckBox* fLeaveOnServerCheckBox;
BCheckBox* fRemoveFromServerCheckBox;
BodyDownloadConfig* fBodyDownloadConfig; BodyDownloadConfig* fBodyDownloadConfig;
}; };
#endif /* ZOIDBERG_PROTOCOL_CONFIG_VIEW_H */
} // namespace BPrivate
#endif /* _PROTOCOL_CONFIG_VIEW_H */
+41 -37
View File
@@ -1,6 +1,8 @@
/* /*
* Copyright 2004-2012, Haiku Inc. All rights reserved.
* Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved. * Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved.
* Copyright 2011 Clemens Zeidler. * Copyright 2011 Clemens Zeidler.
*
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#ifndef MAIL_SETTINGS_H #ifndef MAIL_SETTINGS_H
@@ -77,49 +79,49 @@ private:
}; };
class AddonSettings { class BMailAddOnSettings : public BMessage {
public: public:
AddonSettings(); BMailAddOnSettings();
virtual ~BMailAddOnSettings();
bool Load(const BMessage& message); virtual status_t Load(const BMessage& message);
bool Save(BMessage& message); virtual status_t Save(BMessage& message);
void SetAddonRef(const entry_ref& ref); void SetAddOnRef(const entry_ref& ref);
const entry_ref& AddonRef() const; const entry_ref& AddOnRef() const;
const BMessage& Settings() const; virtual bool HasBeenModified() const;
BMessage& EditSettings();
bool HasBeenModified();
private: private:
BMessage fSettings; BMessage fOriginalSettings;
entry_ref fAddonRef; entry_ref fRef;
entry_ref fOriginalRef;
bool fModified;
}; };
class MailAddonSettings : public AddonSettings { class BMailProtocolSettings : public BMailAddOnSettings {
public: public:
bool Load(const BMessage& message); BMailProtocolSettings();
bool Save(BMessage& message); virtual ~BMailProtocolSettings();
int32 CountFilterSettings(); virtual status_t Load(const BMessage& message);
virtual status_t Save(BMessage& message);
int32 CountFilterSettings() const;
int32 AddFilterSettings(const entry_ref* ref = NULL); int32 AddFilterSettings(const entry_ref* ref = NULL);
bool RemoveFilterSettings(int32 index); void RemoveFilterSettings(int32 index);
bool MoveFilterSettings(int32 from, int32 to); bool MoveFilterSettings(int32 from, int32 to);
AddonSettings* FilterSettingsAt(int32 index); BMailAddOnSettings* FilterSettingsAt(int32 index) const;
bool HasBeenModified(); virtual bool HasBeenModified() const;
private: private:
std::vector<AddonSettings> fFiltersSettings; BObjectList<BMailAddOnSettings> fFiltersSettings;
}; };
class BMailAccountSettings { class BMailAccountSettings {
public: public:
BMailAccountSettings(); BMailAccountSettings();
BMailAccountSettings(BEntry account); BMailAccountSettings(BEntry account);
~BMailAccountSettings(); ~BMailAccountSettings();
@@ -127,24 +129,26 @@ class BMailAccountSettings {
status_t InitCheck() { return fStatus; } status_t InitCheck() { return fStatus; }
void SetAccountID(int32 id); void SetAccountID(int32 id);
int32 AccountID(); int32 AccountID() const;
void SetName(const char* name); void SetName(const char* name);
const char* Name() const; const char* Name() const;
void SetRealName(const char* realName); void SetRealName(const char* realName);
const char* RealName() const; const char* RealName() const;
void SetReturnAddress(const char* returnAddress); void SetReturnAddress(const char* returnAddress);
const char* ReturnAddress() const; const char* ReturnAddress() const;
bool SetInboundAddon(const char* name); bool SetInboundAddOn(const char* name);
bool SetOutboundAddon(const char* name); bool SetOutboundAddOn(const char* name);
const entry_ref& InboundPath() const; const entry_ref& InboundAddOnRef() const;
const entry_ref& OutboundPath() const; const entry_ref& OutboundAddOnRef() const;
MailAddonSettings& InboundSettings(); BMailProtocolSettings& InboundSettings();
MailAddonSettings& OutboundSettings(); const BMailProtocolSettings& InboundSettings() const;
BMailProtocolSettings& OutboundSettings();
const BMailProtocolSettings& OutboundSettings() const;
bool HasInbound(); bool HasInbound();
bool HasOutbound(); bool HasOutbound();
@@ -158,9 +162,9 @@ class BMailAccountSettings {
status_t Save(); status_t Save();
status_t Delete(); status_t Delete();
bool HasBeenModified(); bool HasBeenModified() const;
const BEntry& AccountFile(); const BEntry& AccountFile() const;
private: private:
status_t _CreateAccountFilePath(); status_t _CreateAccountFilePath();
@@ -175,8 +179,8 @@ private:
BString fRealName; BString fRealName;
BString fReturnAdress; BString fReturnAdress;
MailAddonSettings fInboundSettings; BMailProtocolSettings fInboundSettings;
MailAddonSettings fOutboundSettings; BMailProtocolSettings fOutboundSettings;
bool fInboundEnabled; bool fInboundEnabled;
bool fOutboundEnabled; bool fOutboundEnabled;
+48 -35
View File
@@ -1,9 +1,11 @@
#ifndef FILE_CONFIG_VIEW /*
#define FILE_CONFIG_VIEW * Copyright 2004-2012, Haiku, Inc. All rights reserved.
/* FileConfigView - a file configuration view for filters * Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved.
** *
** Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved. * Distributed under the terms of the MIT License.
*/ */
#ifndef _FILE_CONFIG_VIEW_H
#define _FILE_CONFIG_VIEW_H
#include <View.h> #include <View.h>
@@ -13,45 +15,56 @@
class BTextControl; class BTextControl;
class BButton; class BButton;
class BFileControl : public BView
{
public:
BFileControl(BRect rect,const char *name,const char *label,const char *pathOfFile = NULL,uint32 flavors = B_DIRECTORY_NODE);
~BFileControl();
virtual void AttachedToWindow(); namespace BPrivate {
virtual void MessageReceived(BMessage *msg);
void SetText(const char *pathOfFile);
const char *Text() const;
void SetEnabled(bool enabled); class FileControl : public BView {
public:
FileControl(const char* name, const char* label,
const char* pathOfFile = NULL,
uint32 flavors = B_DIRECTORY_NODE);
virtual ~FileControl();
virtual void GetPreferredSize(float *width, float *height); virtual void AttachedToWindow();
virtual void MessageReceived(BMessage* message);
private: void SetText(const char* pathOfFile);
BTextControl *fText; const char* Text() const;
BButton *fButton;
BFilePanel *fPanel; void SetEnabled(bool enabled);
uint32 _reserved[5]; private:
BTextControl* fText;
BButton* fButton;
BFilePanel* fPanel;
uint32 _reserved[5];
}; };
class BMailFileConfigView : public BFileControl
{
public:
BMailFileConfigView(const char *label,const char *name,bool useMeta = false,const char *defaultPath = NULL,uint32 flavors = B_DIRECTORY_NODE);
void SetTo(const BMessage *archive, BMessage *metadata); class MailFileConfigView : public FileControl {
virtual status_t Archive(BMessage *into, bool deep = true) const; public:
MailFileConfigView(const char* label,
const char* name, bool useMeta = false,
const char* defaultPath = NULL,
uint32 flavors = B_DIRECTORY_NODE);
private: void SetTo(const BMessage* archive,
BMessage *fMeta; BMessage* metadata);
bool fUseMeta; virtual status_t Archive(BMessage* into, bool deep = true) const;
const char *fName;
uint32 _reserved[5]; private:
BMessage* fMeta;
bool fUseMeta;
const char* fName;
uint32 _reserved[5];
}; };
#endif /* FILE_CONFIG_VIEW */
} // namespace BPrivate
#endif // _FILE_CONFIG_VIEW_H
@@ -1,199 +1,231 @@
/* RuleFilter's config view - performs action depending on matching a header value /*
** * Copyright 2004-2012, Haiku, Inc. All rights reserved.
** Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved. * Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved.
*/ *
* Distributed under the terms of the MIT License.
*/
#include <stdio.h> #include <stdio.h>
#include <Catalog.h> #include <Catalog.h>
#include <MenuField.h> #include <LayoutBuilder.h>
#include <PopUpMenu.h> #include <MailFilter.h>
#include <Message.h>
#include <TextControl.h>
#include <MenuItem.h>
#include <MailAddon.h>
#include <FileConfigView.h>
#include <MailSettings.h> #include <MailSettings.h>
#include <MenuField.h>
#include <MenuItem.h>
#include <Message.h>
#include <PopUpMenu.h>
#include <TextControl.h>
#include <FileConfigView.h>
#include "RuleFilter.h"
#undef B_TRANSLATION_CONTEXT #undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "ConfigView" #define B_TRANSLATION_CONTEXT "ConfigView"
const uint32 kMsgActionMoveTo = 'argm'; using namespace BPrivate;
const uint32 kMsgActionDelete = 'argd';
const uint32 kMsgActionSetTo = 'args';
const uint32 kMsgActionReplyWith = 'argr'; static const uint32 kMsgActionChanged = 'actC';
const uint32 kMsgActionSetRead = 'arge';
class RuleFilterConfig : public BView { class RuleFilterConfig : public BView {
public: public:
RuleFilterConfig(const BMessage *settings); RuleFilterConfig(const BMessage& settings);
virtual void MessageReceived(BMessage *msg); virtual void MessageReceived(BMessage* message);
virtual void AttachedToWindow(); virtual void AttachedToWindow();
virtual status_t Archive(BMessage *into, bool deep = true) const; virtual status_t Archive(BMessage* into, bool deep = true) const;
virtual void GetPreferredSize(float *width, float *height);
private: private:
BTextControl *attr, *regex; void _SetVisible(BView* view, bool visible);
BFileControl *arg;
BPopUpMenu *menu, *outbound; private:
BMenuField *outbound_field; BTextControl* fAttributeControl;
int staging; BTextControl* fRegexControl;
int32 chain; FileControl* fFileControl;
BTextControl* fFlagsControl;
BPopUpMenu* fActionMenu;
BPopUpMenu* fAccountMenu;
BMenuField* fAccountField;
int fAction;
int32 fAccountID;
}; };
RuleFilterConfig::RuleFilterConfig(const BMessage *settings) RuleFilterConfig::RuleFilterConfig(const BMessage& settings)
: :
BView(BRect(0,0,260,85),"rulefilter_config", B_FOLLOW_LEFT | B_FOLLOW_TOP, BView("rulefilter_config", 0),
0), menu(NULL) fActionMenu(NULL)
{ {
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
attr = new BTextControl(BRect(5,5,100,20),"attr", B_TRANSLATE("If"),
B_TRANSLATE("header (e.g. Subject)"),NULL);
attr->SetDivider(be_plain_font->StringWidth(B_TRANSLATE("If"))+ 4);
if (settings->HasString("attribute"))
attr->SetText(settings->FindString("attribute"));
AddChild(attr);
regex = new BTextControl(BRect(104,5,255,20),"attr", B_TRANSLATE("has"), if (settings.HasInt32("do_what"))
fAction = settings.FindInt32("do_what");
else
fAction = -1;
fAttributeControl = new BTextControl("attr", B_TRANSLATE("If"),
B_TRANSLATE("header (e.g. Subject)"), NULL);
if (settings.HasString("attribute"))
fAttributeControl->SetText(settings.FindString("attribute"));
fRegexControl = new BTextControl("regex", B_TRANSLATE("has"),
B_TRANSLATE("value (use REGEX: in from of regular expressions like " B_TRANSLATE("value (use REGEX: in from of regular expressions like "
"*spam*)"), NULL); "*spam*)"), NULL);
regex->SetDivider(be_plain_font->StringWidth(B_TRANSLATE("has")) + 4); if (settings.HasString("regex"))
if (settings->HasString("regex")) fRegexControl->SetText(settings.FindString("regex"));
regex->SetText(settings->FindString("regex"));
AddChild(regex);
arg = new BFileControl(BRect(5,55,255,80),"arg", NULL, fFileControl = new FileControl("arg", NULL,
B_TRANSLATE("this field is based on the action")); B_TRANSLATE("this field is based on the action"));
if (BControl *control = (BControl *)arg->FindView("select_file")) if (BControl* control = (BControl*)fFileControl->FindView("select_file"))
control->SetEnabled(false); control->SetEnabled(false);
if (settings->HasString("argument")) if (fAction == ACTION_MOVE_TO && settings.HasString("argument"))
arg->SetText(settings->FindString("argument")); fFileControl->SetText(settings.FindString("argument"));
outbound = new BPopUpMenu(B_TRANSLATE("<Choose account>")); fFlagsControl = new BTextControl("flags", NULL, NULL);
if (fAction == ACTION_SET_FLAGS_TO && settings.HasString("argument"))
fFlagsControl->SetText(settings.FindString("argument"));
if (settings->HasInt32("do_what")) // Populate account menu
staging = settings->FindInt32("do_what");
fAccountMenu = new BPopUpMenu(B_TRANSLATE("<Choose account>"));
if (fAction == ACTION_REPLY_WITH)
fAccountID = settings.FindInt32("argument");
else else
staging = -1; fAccountID = -1;
if (staging == 3)
chain = settings->FindInt32("argument");
else
chain = -1;
printf("Chain: %" B_PRId32 "\n",chain);
BMailAccounts accounts; BMailAccounts accounts;
for (int32 i = 0; i < accounts.CountAccounts(); i++) { for (int32 i = 0; i < accounts.CountAccounts(); i++) {
BMailAccountSettings* account = accounts.AccountAt(i); BMailAccountSettings* account = accounts.AccountAt(i);
if (!account->HasOutbound()) if (!account->HasOutbound())
continue; continue;
BMenuItem *item = new BMenuItem(account->Name(),
new BMessage(account->AccountID())); BMessage* message = new BMessage();
outbound->AddItem(item); message->AddInt32("account id", account->AccountID());
if (account->AccountID() == chain)
BMenuItem* item = new BMenuItem(account->Name(), message);
fAccountMenu->AddItem(item);
if (account->AccountID() == fAccountID)
item->SetMarked(true); item->SetMarked(true);
} }
}
fAccountField = new BMenuField("reply", "Foo", fAccountMenu);
void RuleFilterConfig::AttachedToWindow() { if (fAction >= 0) {
if (menu != NULL) BMenuItem* item = fActionMenu->ItemAt(fAction);
return; // We switched back from another tab if (item != NULL) {
item->SetMarked(true);
menu = new BPopUpMenu(B_TRANSLATE("<Choose action>")); MessageReceived(item->Message());
menu->AddItem(new BMenuItem(B_TRANSLATE("Move to"), }
new BMessage(kMsgActionMoveTo)));
menu->AddItem(new BMenuItem(B_TRANSLATE("Set flags to"),
new BMessage(kMsgActionSetTo)));
menu->AddItem(new BMenuItem(B_TRANSLATE("Delete message"),
new BMessage(kMsgActionDelete)));
menu->AddItem(new BMenuItem(B_TRANSLATE("Reply with"),
new BMessage(kMsgActionReplyWith)));
menu->AddItem(new BMenuItem(B_TRANSLATE("Set as read"),
new BMessage(kMsgActionSetRead)));
menu->SetTargetForItems(this);
BMenuField *field = new BMenuField(BRect(5,30,210,50),"do_what",
B_TRANSLATE("Then"), menu);
field->ResizeToPreferred();
field->SetDivider(be_plain_font->StringWidth(B_TRANSLATE("Then")) + 8);
AddChild(field);
outbound_field = new BMenuField(BRect(5,55,255,80),"reply","Foo",outbound);
outbound_field->ResizeToPreferred();
outbound_field->SetDivider(0);
if (staging >= 0) {
menu->ItemAt(staging)->SetMarked(true);
MessageReceived(menu->ItemAt(staging)->Message());
} else {
AddChild(arg);
} }
// Popuplate action menu
fActionMenu = new BPopUpMenu(B_TRANSLATE("<Choose action>"));
const struct {
rule_action action;
const char* label;
} kActions[] = {
{ACTION_MOVE_TO, B_TRANSLATE("Move to")},
{ACTION_SET_FLAGS_TO, B_TRANSLATE("Set flags to")},
{ACTION_DELETE_MESSAGE, B_TRANSLATE("Delete message")},
{ACTION_REPLY_WITH, B_TRANSLATE("Reply with")},
{ACTION_SET_AS_READ, B_TRANSLATE("Set as read")},
};
for (size_t i = 0; i < sizeof(kActions) / sizeof(kActions[0]); i++) {
BMessage* message = new BMessage(kMsgActionChanged);
message->AddInt32("action", (int32)kActions[i].action);
fActionMenu->AddItem(new BMenuItem(kActions[i].label, message));
}
BMenuField* actionField = new BMenuField("do_what", B_TRANSLATE("Then"),
fActionMenu);
// Build layout
BLayoutBuilder::Group<>(this, B_VERTICAL)
.AddGroup(B_HORIZONTAL)
.Add(fAttributeControl->CreateLabelLayoutItem())
.Add(fAttributeControl->CreateTextViewLayoutItem())
.Add(fRegexControl->CreateLabelLayoutItem())
.Add(fRegexControl->CreateTextViewLayoutItem())
.End()
.AddGroup(B_HORIZONTAL)
.Add(actionField->CreateLabelLayoutItem())
.Add(actionField->CreateMenuBarLayoutItem())
.End()
.Add(fFileControl)
.Add(fAccountField);
} }
status_t RuleFilterConfig::Archive(BMessage *into, bool deep) const {
void
RuleFilterConfig::AttachedToWindow()
{
fActionMenu->SetTargetForItems(this);
}
status_t
RuleFilterConfig::Archive(BMessage *into, bool deep) const
{
into->MakeEmpty(); into->MakeEmpty();
into->AddInt32("do_what",menu->IndexOf(menu->FindMarked())); into->AddInt32("do_what", fActionMenu->IndexOf(fActionMenu->FindMarked()));
into->AddString("attribute",attr->Text()); into->AddString("attribute", fAttributeControl->Text());
into->AddString("regex",regex->Text()); into->AddString("regex", fRegexControl->Text());
if (into->FindInt32("do_what") == 3) if (into->FindInt32("do_what") == ACTION_REPLY_WITH) {
into->AddInt32("argument", outbound->FindMarked()->Message()->what); BMenuItem* item = fAccountMenu->FindMarked();
else if (item != NULL) {
into->AddString("argument",arg->Text()); into->AddInt32("argument",
item->Message()->FindInt32("account id"));
}
} else
into->AddString("argument", fFileControl->Text());
return B_OK; return B_OK;
} }
void RuleFilterConfig::MessageReceived(BMessage *msg) {
switch (msg->what) void
{ RuleFilterConfig::MessageReceived(BMessage* message)
case kMsgActionMoveTo: {
case kMsgActionSetTo: switch (message->what) {
if (arg->FindView("file_path")) case kMsgActionChanged:
arg->SetEnabled(true); fAction = message->FindInt32("action");
if (BControl *control = (BControl *)arg->FindView("select_file"))
control->SetEnabled(msg->what == kMsgActionMoveTo); _SetVisible(fFileControl, fAction == ACTION_MOVE_TO);
if (arg->Parent() == NULL) { _SetVisible(fFlagsControl, fAction == ACTION_SET_FLAGS_TO);
outbound_field->RemoveSelf(); _SetVisible(fAccountField, fAction == ACTION_REPLY_WITH);
AddChild(arg);
}
break;
case kMsgActionDelete:
arg->SetEnabled(false);
if (arg->Parent() == NULL) {
outbound_field->RemoveSelf();
AddChild(arg);
}
break;
case kMsgActionReplyWith:
if (outbound->Parent() == NULL) {
arg->RemoveSelf();
AddChild(outbound_field);
}
break;
case kMsgActionSetRead:
arg->SetEnabled(false);
if (arg->Parent() == NULL) {
outbound_field->RemoveSelf();
AddChild(arg);
}
break; break;
default: default:
BView::MessageReceived(msg); BView::MessageReceived(message);
} }
} }
void RuleFilterConfig::GetPreferredSize(float *width, float *height) {
*width = 260;
*height = 55;
}
void
BView* instantiate_filter_config_panel(AddonSettings& settings) RuleFilterConfig::_SetVisible(BView* view, bool visible)
{ {
return new RuleFilterConfig(&settings.Settings()); while (visible && view->IsHidden(view))
view->Show();
while (!visible && !view->IsHidden(view))
view->Hide();
}
// #pragma mark -
BView*
instantiate_filter_config_panel(BMailAddOnSettings& settings)
{
return new RuleFilterConfig(settings);
} }
@@ -1,7 +1,12 @@
/* Match Header - performs action depending on matching a header value /*
** * Copyright 2004-2012, Haiku, Inc. All rights reserved.
** Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved. * Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved.
*/ *
* Distributed under the terms of the MIT License.
*/
//! Performs action depending on matching a header value.
#include "RuleFilter.h" #include "RuleFilter.h"
@@ -22,38 +27,46 @@
#define B_TRANSLATION_CONTEXT "RuleFilter" #define B_TRANSLATION_CONTEXT "RuleFilter"
RuleFilter::RuleFilter(MailProtocol& protocol, AddonSettings* addonSettings) RuleFilter::RuleFilter(BMailProtocol& protocol, BMailAddOnSettings* settings)
: :
MailFilter(protocol, addonSettings) BMailFilter(protocol, settings)
{ {
const BMessage* settings = &addonSettings->Settings();
// attribute is adapted to our "capitalize-each-word-in-the-header" policy // attribute is adapted to our "capitalize-each-word-in-the-header" policy
settings->FindString("attribute", &fAttribute); settings->FindString("attribute", &fAttribute);
fAttribute.CapitalizeEachWord(); fAttribute.CapitalizeEachWord();
BString regex; settings->FindString("regex", &fExpression);
settings->FindString("regex", &regex); int32 index = fExpression.FindFirst("REGEX:");
int32 index = regex.FindFirst("REGEX:");
if (index == B_ERROR || index > 0) if (index == B_ERROR || index > 0)
EscapeRegexTokens(regex); EscapeRegexTokens(fExpression);
else else
regex.RemoveFirst("REGEX:"); fExpression.RemoveFirst("REGEX:");
fMatcher.SetPattern(regex, false); fMatcher.SetPattern(fExpression, false);
settings->FindString("argument",&fArg); settings->FindString("argument", &fArg);
settings->FindInt32("do_what", (int32*)&fDoWhat); settings->FindInt32("do_what", (int32*)&fAction);
if (fDoWhat == Z_SET_REPLY) if (fAction == ACTION_REPLY_WITH)
settings->FindInt32("argument", &fReplyAccount); settings->FindInt32("argument", &fReplyAccount);
} }
BString
RuleFilter::DescriptiveName() const
{
BString name(B_TRANSLATE("Match \"%attribute\" against \"%regex\""));
name.ReplaceAll("%attribute", fAttribute);
name.ReplaceAll("%regex", fExpression);
return name;
}
void void
RuleFilter::HeaderFetched(const entry_ref& ref, BFile* file) RuleFilter::HeaderFetched(const entry_ref& ref, BFile* file)
{ {
// That field doesn't exist? NO match
if (fAttribute == "") if (fAttribute == "")
return; //----That field doesn't exist? NO match return;
attr_info info; attr_info info;
if (file->GetAttrInfo("Subject", &info) != B_OK if (file->GetAttrInfo("Subject", &info) != B_OK
@@ -68,72 +81,59 @@ RuleFilter::HeaderFetched(const entry_ref& ref, BFile* file)
BString data = buffer; BString data = buffer;
delete[] buffer; delete[] buffer;
if (!fMatcher.Match(data)) if (!fMatcher.Match(data)) {
return; //-----There wasn't an error. We're just not supposed to do anything // We're not supposed to do anything
return;
switch (fDoWhat) { }
case Z_MOVE_TO:
switch (fAction) {
case ACTION_MOVE_TO:
{ {
BDirectory dir(fArg); BDirectory dir(fArg);
fMailProtocol.Looper()->TriggerFileMove(ref, dir); // TODO: move is currently broken!
// fMailProtocol.Looper()->TriggerFileMove(ref, dir);
break; break;
} }
case Z_TRASH: case ACTION_DELETE_MESSAGE:
// TODO trash!? // TODO trash!?
fMailProtocol.Looper()->TriggerFileDeletion(ref); // fMailProtocol.Looper()->TriggerFileDeletion(ref);
break; break;
case Z_FLAG: case ACTION_SET_FLAGS_TO:
file->WriteAttrString("MAIL:filter_flags", &fArg); file->WriteAttrString("MAIL:filter_flags", &fArg);
break; break;
case Z_SET_REPLY: case ACTION_REPLY_WITH:
file->WriteAttr("MAIL:reply_with", B_INT32_TYPE, 0, &fReplyAccount, file->WriteAttr("MAIL:reply_with", B_INT32_TYPE, 0, &fReplyAccount,
4); sizeof(int32));
break; break;
case Z_SET_READ: case ACTION_SET_AS_READ:
{ {
InboundProtocol& protocol = (InboundProtocol&)fMailProtocol; BInboundMailProtocol& protocol
= (BInboundMailProtocol&)fMailProtocol;
protocol.MarkMessageAsRead(ref, B_READ); protocol.MarkMessageAsRead(ref, B_READ);
break; break;
} }
default: default:
fprintf(stderr,"Unknown do_what: 0x%04x!\n", fDoWhat); fprintf(stderr,"Unknown do_what: 0x%04x!\n", fAction);
} }
return; return;
} }
// #pragma mark -
BString BString
descriptive_name() filter_name()
{ {
/*const char *attribute = NULL;
settings->FindString("attribute",&attribute);
const char *regex = NULL;
settings->FindString("regex",&regex);
if (!attribute || strlen(attribute) > 15)
return B_ERROR;
sprintf(buffer, "Match \"%s\"", attribute);
if (!regex)
return B_OK;
char reg[20];
strncpy(reg, regex, 16);
if (strlen(regex) > 15)
strcpy(reg + 15, "...");
sprintf(buffer + strlen(buffer), " against \"%s\"", reg);
return B_OK;*/
return B_TRANSLATE("Rule filter"); return B_TRANSLATE("Rule filter");
} }
MailFilter* BMailFilter*
instantiate_mailfilter(MailProtocol& protocol, AddonSettings* settings) instantiate_filter(BMailProtocol& protocol, BMailAddOnSettings* settings)
{ {
return new RuleFilter(protocol, settings); return new RuleFilter(protocol, settings);
} }
@@ -1,40 +1,47 @@
#ifndef ZOIDBERG_RULE_FILTER_H /*
#define ZOIDBERG_RULE_FILTER_H * Copyright 2004-2012, Haiku, Inc. All rights reserved.
/* RuleFilter - performs action depending on matching a header value * Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved.
** *
** Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved. * Distributed under the terms of the MIT License.
*/ */
#ifndef RULE_FILTER_H
#define RULE_FILTER_H
#include <Message.h> #include <Message.h>
#include <List.h> #include <List.h>
#include <MailAddon.h> #include <MailFilter.h>
#include "StringMatcher.h" #include "StringMatcher.h"
typedef enum { enum rule_action {
Z_MOVE_TO, ACTION_MOVE_TO,
Z_FLAG, ACTION_SET_FLAGS_TO,
Z_TRASH, ACTION_DELETE_MESSAGE,
Z_SET_REPLY, ACTION_REPLY_WITH,
Z_SET_READ ACTION_SET_AS_READ
} z_mail_action_flags; };
class RuleFilter : public MailFilter { class RuleFilter : public BMailFilter {
public: public:
RuleFilter(MailProtocol& protocol, RuleFilter(BMailProtocol& protocol,
AddonSettings* settings); BMailAddOnSettings* settings);
void HeaderFetched(const entry_ref& ref,
virtual BString DescriptiveName() const;
virtual void HeaderFetched(const entry_ref& ref,
BFile* file); BFile* file);
private: private:
StringMatcher fMatcher;
BString fAttribute; BString fAttribute;
BString fExpression;
StringMatcher fMatcher;
BString fArg; BString fArg;
int32 fReplyAccount; int32 fReplyAccount;
z_mail_action_flags fDoWhat; rule_action fAction;
}; };
#endif /* ZOIDBERG_RULE_FILTER_H */
#endif // RULE_FILTER_H
@@ -1,20 +1,23 @@
/* ConfigView - the configuration view for the Notifier filter /*
** * Copyright 2004-2012, Haiku, Inc. All rights reserved.
** Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved. * Copyright 2001, Dr. Zoidberg Enterprises. All rights reserved.
*/ *
* Distributed under the terms of the MIT License.
*/
#include "ConfigView.h" #include "ConfigView.h"
#include <Catalog.h> #include <Catalog.h>
#include <CheckBox.h> #include <CheckBox.h>
#include <LayoutBuilder.h>
#include <PopUpMenu.h> #include <PopUpMenu.h>
#include <MenuItem.h> #include <MenuItem.h>
#include <MenuField.h> #include <MenuField.h>
#include <String.h> #include <String.h>
#include <Message.h> #include <Message.h>
#include <MailAddon.h> #include <MailFilter.h>
#include <MailSettings.h> #include <MailSettings.h>
@@ -26,18 +29,12 @@ const uint32 kMsgNotifyMethod = 'nomt';
ConfigView::ConfigView() ConfigView::ConfigView()
: BView(BRect(0,0,10,10),"notifier_config",B_FOLLOW_LEFT | B_FOLLOW_TOP,0) :
BView("notifier_config", 0)
{ {
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
// determine font height BPopUpMenu *menu = new BPopUpMenu(B_EMPTY_STRING, false, false);
font_height fontHeight;
GetFontHeight(&fontHeight);
float itemHeight = (int32)(fontHeight.ascent + fontHeight.descent
+ fontHeight.leading) + 6;
BRect frame(5,2,250,itemHeight + 2);
BPopUpMenu *menu = new BPopUpMenu(B_EMPTY_STRING,false,false);
const char *notifyMethods[] = { const char *notifyMethods[] = {
B_TRANSLATE("Beep"), B_TRANSLATE("Beep"),
@@ -47,29 +44,26 @@ ConfigView::ConfigView()
B_TRANSLATE("Central beep"), B_TRANSLATE("Central beep"),
B_TRANSLATE("Log window") B_TRANSLATE("Log window")
}; };
for (int32 i = 0,j = 1;i < 6;i++,j *= 2) { for (int32 i = 0, j = 1;i < 6; i++, j *= 2) {
menu->AddItem(new BMenuItem(notifyMethods[i], menu->AddItem(new BMenuItem(notifyMethods[i],
new BMessage(kMsgNotifyMethod))); new BMessage(kMsgNotifyMethod)));
} }
BMenuField *field = new BMenuField(frame,"notify", B_TRANSLATE("Method:"), BLayoutBuilder::Group<>(this).Add(
menu); new BMenuField("notify", B_TRANSLATE("Method:"), menu));
field->ResizeToPreferred(); }
field->SetDivider(field->StringWidth(B_TRANSLATE("Method:")) + 6);
AddChild(field);
ResizeToPreferred();
}
void ConfigView::AttachedToWindow() void
ConfigView::AttachedToWindow()
{ {
if (BMenuField *field = dynamic_cast<BMenuField *>(FindView("notify"))) if (BMenuField *field = dynamic_cast<BMenuField *>(FindView("notify")))
field->Menu()->SetTargetForItems(this); field->Menu()->SetTargetForItems(this);
} }
void ConfigView::SetTo(const BMessage *archive) void
ConfigView::SetTo(const BMessage *archive)
{ {
int32 method = archive->FindInt32("notification_method"); int32 method = archive->FindInt32("notification_method");
if (method < 0) if (method < 0)
@@ -79,8 +73,7 @@ void ConfigView::SetTo(const BMessage *archive)
if ((field = dynamic_cast<BMenuField *>(FindView("notify"))) == NULL) if ((field = dynamic_cast<BMenuField *>(FindView("notify"))) == NULL)
return; return;
for (int32 i = field->Menu()->CountItems();i-- > 0;) for (int32 i = field->Menu()->CountItems(); i-- > 0;) {
{
BMenuItem *item = field->Menu()->ItemAt(i); BMenuItem *item = field->Menu()->ItemAt(i);
item->SetMarked((method & (1L << i)) != 0); item->SetMarked((method & (1L << i)) != 0);
} }
@@ -88,15 +81,15 @@ void ConfigView::SetTo(const BMessage *archive)
} }
void ConfigView::UpdateNotifyText() void
ConfigView::UpdateNotifyText()
{ {
BMenuField *field; BMenuField *field;
if ((field = dynamic_cast<BMenuField *>(FindView("notify"))) == NULL) if ((field = dynamic_cast<BMenuField *>(FindView("notify"))) == NULL)
return; return;
BString label; BString label;
for (int32 i = field->Menu()->CountItems();i-- > 0;) for (int32 i = field->Menu()->CountItems(); i-- > 0;) {
{
BMenuItem *item = field->Menu()->ItemAt(i); BMenuItem *item = field->Menu()->ItemAt(i);
if (!item->IsMarked()) if (!item->IsMarked())
continue; continue;
@@ -111,16 +104,16 @@ void ConfigView::UpdateNotifyText()
} }
void ConfigView::MessageReceived(BMessage *msg) void
ConfigView::MessageReceived(BMessage *msg)
{ {
switch (msg->what) switch (msg->what) {
{
case kMsgNotifyMethod: case kMsgNotifyMethod:
{ {
BMenuItem *item; BMenuItem *item;
if (msg->FindPointer("source",(void **)&item) < B_OK) if (msg->FindPointer("source",(void **)&item) < B_OK)
break; break;
item->SetMarked(!item->IsMarked()); item->SetMarked(!item->IsMarked());
UpdateNotifyText(); UpdateNotifyText();
break; break;
@@ -131,46 +124,34 @@ void ConfigView::MessageReceived(BMessage *msg)
} }
status_t ConfigView::Archive(BMessage *into, bool) const status_t
ConfigView::Archive(BMessage *into, bool /*deep*/) const
{ {
int32 method = 0; int32 method = 0;
BMenuField *field; BMenuField *field;
if ((field = dynamic_cast<BMenuField *>(FindView("notify"))) != NULL) if ((field = dynamic_cast<BMenuField *>(FindView("notify"))) != NULL) {
{ for (int32 i = field->Menu()->CountItems(); i-- > 0;) {
for (int32 i = field->Menu()->CountItems();i-- > 0;)
{
BMenuItem *item = field->Menu()->ItemAt(i); BMenuItem *item = field->Menu()->ItemAt(i);
if (item->IsMarked()) if (item->IsMarked())
method |= 1L << i; method |= 1L << i;
} }
} }
if (into->ReplaceInt32("notification_method",method) != B_OK) if (into->ReplaceInt32("notification_method", method) != B_OK)
into->AddInt32("notification_method",method); into->AddInt32("notification_method", method);
return B_OK; return B_OK;
} }
void ConfigView::GetPreferredSize(float *width, float *height) // #pragma mark -
{
*width = 258;
*height = ChildAt(0)->Bounds().Height() + 8;
}
BView* BView*
instantiate_filter_config_panel(AddonSettings& settings) instantiate_filter_config_panel(BMailAddOnSettings& settings)
{ {
ConfigView *view = new ConfigView(); ConfigView *view = new ConfigView();
view->SetTo(&settings.Settings()); view->SetTo(&settings);
return view; return view;
} }
BString
descriptive_name()
{
return B_TRANSLATE("New mails notification");
}
@@ -1,35 +1,39 @@
#ifndef CONFIG_VIEW /*
#define CONFIG_VIEW * Copyright 2004-2012, Haiku, Inc. All rights reserved.
/* ConfigView - the configuration view for the Notifier filter * Copyright 2001, Dr. Zoidberg Enterprises. All rights reserved.
** *
** Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved. * Distributed under the terms of the MIT License.
*/ */
#ifndef CONFIG_VIEW_H
#define CONFIG_VIEW_H
#include <View.h> #include <View.h>
enum { enum {
do_beep = 1, NOTIFY_BEEP = 1,
alert = 2, NOTIFY_ALERT = 2,
blink_leds = 4, NOTIFY_BLINK_LEDS = 4,
big_doozy_alert = 8, NOTIFY_CENTRAL_ALERT = 8,
one_central_beep = 16, NOTIFY_CENTRAL_BEEP = 16,
log_window = 32 NOTIFY_NOTIFICATION = 32
}; };
class ConfigView : public BView
{
public:
ConfigView();
void SetTo(const BMessage *archive);
virtual status_t Archive(BMessage *into, bool deep = true) const;
virtual void AttachedToWindow(); class ConfigView : public BView {
virtual void MessageReceived(BMessage *msg); public:
virtual void GetPreferredSize(float *width, float *height); ConfigView();
void UpdateNotifyText(); void SetTo(const BMessage *archive);
virtual status_t Archive(BMessage *into, bool deep = true) const;
virtual void AttachedToWindow();
virtual void MessageReceived(BMessage *msg);
void UpdateNotifyText();
}; };
#endif /* CONFIG_VIEW */
#endif // CONFIG_VIEW_H
@@ -1,8 +1,13 @@
/* New Mail Notification - notifies incoming e-mail /*
* * Copyright 2004-2015, Haiku, Inc. All rights reserved.
* Copyright 2001, Dr. Zoidberg Enterprises. All rights reserved. * Copyright 2001, Dr. Zoidberg Enterprises. All rights reserved.
* Copyright 2011, Clemens Zeidler <[email protected]> * Copyright 2011, Clemens Zeidler <[email protected]>
*/ *
* Distributed under the terms of the MIT License.
*/
//! Notifies incoming e-mail
#include <Alert.h> #include <Alert.h>
@@ -14,7 +19,7 @@
#include <Path.h> #include <Path.h>
#include <String.h> #include <String.h>
#include <MailAddon.h> #include <MailFilter.h>
#include "ConfigView.h" #include "ConfigView.h"
@@ -23,33 +28,44 @@
#define B_TRANSLATION_CONTEXT "filter" #define B_TRANSLATION_CONTEXT "filter"
class NotifyFilter : public MailFilter class NotifyFilter : public BMailFilter {
{
public: public:
NotifyFilter(MailProtocol& protocol, NotifyFilter(BMailProtocol& protocol,
AddonSettings* settings); BMailAddOnSettings* settings);
virtual BString DescriptiveName() const;
void HeaderFetched(const entry_ref& ref, void HeaderFetched(const entry_ref& ref,
BFile* file); BFile* file);
void MailboxSynced(status_t status); void MailboxSynchronized(status_t status);
private: private:
int32 fStrategy; int32 fStrategy;
int32 fNNewMessages; int32 fNNewMessages;
}; };
NotifyFilter::NotifyFilter(MailProtocol& protocol, AddonSettings* settings) NotifyFilter::NotifyFilter(BMailProtocol& protocol,
BMailAddOnSettings* settings)
: :
MailFilter(protocol, settings), BMailFilter(protocol, settings),
fNNewMessages(0) fNNewMessages(0)
{ {
fStrategy = settings->Settings().FindInt32("notification_method"); fStrategy = settings->FindInt32("notification_method");
}
BString
NotifyFilter::DescriptiveName() const
{
return filter_name();
} }
void void
NotifyFilter::HeaderFetched(const entry_ref& ref, BFile* file) NotifyFilter::HeaderFetched(const entry_ref& ref, BFile* file)
{ {
// TODO: do not use MAIL:status here!
char statusString[256]; char statusString[256];
if (file->ReadAttr("MAIL:status", B_STRING_TYPE, 0, statusString, 256) < 0) if (file->ReadAttr("MAIL:status", B_STRING_TYPE, 0, statusString, 256) < 0)
return; return;
@@ -59,17 +75,17 @@ NotifyFilter::HeaderFetched(const entry_ref& ref, BFile* file)
void void
NotifyFilter::MailboxSynced(status_t status) NotifyFilter::MailboxSynchronized(status_t status)
{ {
if (fNNewMessages == 0) if (fNNewMessages == 0)
return; return;
if (fStrategy & do_beep) if ((fStrategy & NOTIFY_BEEP) != 0)
system_beep("New E-mail"); system_beep("New E-mail");
if (fStrategy & alert) { if ((fStrategy & NOTIFY_ALERT) != 0) {
static BMessageFormat format(B_TRANSLATE( BMessageFormat format(B_TRANSLATE(
"You have {0, plural, one{# new message} other{# new messages}} " "You have {0, plural, one{One new message} other{# new messages}} "
"for %account.")); "for %account."));
BString text; BString text;
@@ -83,13 +99,13 @@ NotifyFilter::MailboxSynced(status_t status)
alert->Go(NULL); alert->Go(NULL);
} }
if (fStrategy & blink_leds) if ((fStrategy & NOTIFY_BLINK_LEDS) != 0)
be_app->PostMessage('mblk'); be_app->PostMessage('mblk');
if (fStrategy & one_central_beep) if ((fStrategy & NOTIFY_CENTRAL_BEEP) != 0)
be_app->PostMessage('mcbp'); be_app->PostMessage('mcbp');
if (fStrategy & big_doozy_alert) { if ((fStrategy & NOTIFY_CENTRAL_ALERT) != 0) {
BMessage msg('numg'); BMessage msg('numg');
msg.AddInt32("num_messages", fNNewMessages); msg.AddInt32("num_messages", fNNewMessages);
msg.AddString("name", fMailProtocol.AccountSettings().Name()); msg.AddString("name", fMailProtocol.AccountSettings().Name());
@@ -97,9 +113,9 @@ NotifyFilter::MailboxSynced(status_t status)
be_app->PostMessage(&msg); be_app->PostMessage(&msg);
} }
if (fStrategy & log_window) { if ((fStrategy & NOTIFY_NOTIFICATION) != 0) {
static BMessageFormat format(B_TRANSLATE("{0, plural, " BMessageFormat format(B_TRANSLATE("{0, plural, "
"one{# new message} other{# new messages}}")); "one{One new message} other{# new messages}}"));
BString message; BString message;
format.Format(message, fNNewMessages); format.Format(message, fNNewMessages);
@@ -110,8 +126,18 @@ NotifyFilter::MailboxSynced(status_t status)
} }
MailFilter* // #pragma mark -
instantiate_mailfilter(MailProtocol& protocol, AddonSettings* settings)
BString
filter_name()
{
return B_TRANSLATE("New mails notification");
}
BMailFilter*
instantiate_filter(BMailProtocol& protocol, BMailAddOnSettings* settings)
{ {
return new NotifyFilter(protocol, settings); return new NotifyFilter(protocol, settings);
} }
@@ -4,113 +4,22 @@
* Copyright 2011, Clemens Zeidler <[email protected]> * Copyright 2011, Clemens Zeidler <[email protected]>
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
/******************************************************************************
* $Id: SpamFilter.cpp 29284 2009-02-22 13:45:40Z bga $ /*! Uses Bayesian statistics to evaluate the spaminess of a message.
* The evaluation is done by a separate server, this add-on just gets
* SpamFilter - Uses Bayesian statistics to evaluate the spaminess of a the text and uses scripting commands to get an evaluation from the server.
* message. The evaluation is done by a separate server, this add-on just gets If the server isn't running, it will be found and started up. Once the
* the text and uses scripting commands to get an evaluation from the server. evaluation has been received, it is added to the message as an attribute and
* If the server isn't running, it will be found and started up. Once the optionally as an addition to the subject. Some other add-on later in the
* evaluation has been received, it is added to the message as an attribute and pipeline will use the attribute to delete the message or move it to some
* optionally as an addition to the subject. Some other add-on later in the other folder.
* pipeline will use the attribute to delete the message or move it to some */
* other folder.
*
* Public Domain 2002, by Alexander G. M. Smith, no warranty. #include "SpamFilter.h"
*
* $Log: SpamFilter.cpp,v $ (SVN doesn't support log messages so manually done) #include <stdlib.h>
* r11769 | bonefish | 2005-03-17 03:30:54 -0500 (Thu, 17 Mar 2005) | 1 line #include <stdio.h>
* Move trunk into respective module.
*
* r9934 | nwhitehorn | 2004-11-11 21:55:05 -0500 (Thu, 11 Nov 2004) | 2 lines
* Added AGMS's excellent spam detection software. Still some weirdness with
* the configuration interface from E-mail prefs.
*
* r9669 | brunoga | 2004-10-30 18:23:26 -0400 (Sat, 30 Oct 2004) | 2 lines
* AGMS Spam Filter.
*
* Revision 1.19 2004/09/20 15:57:30 nwhitehorn
* Mostly updated the tree to Be/Haiku style identifier naming conventions. I have a few more things to work out, mostly in mail_util.h, and then I'm proceeding to jamify the build system. Then we go into Haiku CVS.
*
* Revision 1.18 2003/09/20 12:39:27 agmsmith
* Memory leak delete needs [] bug.
*
* Revision 1.17 2003/07/08 21:12:47 agmsmith
* Changed other spam filter defaults to values I find useful.
*
* Revision 1.16 2003/07/08 20:56:40 agmsmith
* Turn on auto-training for the spam filter by default.
*
* Revision 1.15 2003/07/06 13:30:33 agmsmith
* Make sure that the spam filter doesn't auto-train the message twice
* when it gets a partially downloaded e-mail (will just train on the
* partial one, ignore the complete message when it gets downloaded).
*
* Revision 1.14 2003/05/27 17:12:59 nwhitehorn
* Massive refactoring of the Protocol/ChainRunner/Filter system. You can probably
* examine its scope by examining the number of files changed. Regardless, this is
* preparation for lots of new features, and REAL WORKING IMAP. Yes, you heard me.
* Enjoy, and prepare for bugs (although I've fixed all the ones I've found, I susp
* ect there are some memory leaks in ChainRunner).
*
* Revision 1.13 2003/02/08 21:54:17 agmsmith
* Updated the AGMSBayesianSpamServer documentation to match the current
* version. Also removed the Beep options from the spam filter, now they
* are turned on or off in the system sound preferences.
*
* Revision 1.12 2002/12/18 02:27:45 agmsmith
* Added uncertain classification as suggested by BiPolar.
*
* Revision 1.11 2002/12/16 16:03:20 agmsmith
* Changed spam cutoff to 0.95 to work with default Chi-Squared scoring.
*
* Revision 1.10 2002/12/13 22:04:42 agmsmith
* Changed default to turn on the Spam marker in the subject.
*
* Revision 1.9 2002/12/13 20:27:44 agmsmith
* Added auto-training mode to the filter. It evaluates a message for
* spaminess then recursively adds it to the database. This can lead
* to weird results unless the user corrects the bad classifications.
*
* Revision 1.8 2002/11/28 20:20:57 agmsmith
* Now checks if the spam database is running in headers only mode, and
* then only downloads headers if that is the case.
*
* Revision 1.7 2002/11/10 19:36:26 agmsmith
* Retry launching server a few times, but not too many.
*
* Revision 1.6 2002/11/03 02:21:02 agmsmith
* Never mind, just use the SourceForge version numbers. Ugh.
*
* Revision 1.8 2002/10/21 16:12:09 agmsmith
* Added option for spam if no words found, use new method of saving
* the attribute which avoids hacking the rest of the mail system.
*
* Revision 1.7 2002/10/11 20:01:28 agmsmith
* Added sound effects (system beep) for genuine and spam, plus config option
* for it.
*
* Revision 1.6 2002/10/01 00:45:34 agmsmith
* Changed default spam ratio to 0.56 from 0.9, for use with
* the Gary Robinson method in AGMSBayesianSpamServer 1.49.
*
* Revision 1.5 2002/09/25 13:23:21 agmsmith
* Don't leave the data stream at the initial position, try leaving it
* at the end. Was having mail progress bar problems.
*
* Revision 1.4 2002/09/23 19:14:13 agmsmith
* Added an option to have the server quit when done.
*
* Revision 1.3 2002/09/23 03:33:34 agmsmith
* First working version, with cutoff ratio and subject modification,
* and an attribute added if a patch is made to the Folder filter.
*
* Revision 1.2 2002/09/21 20:57:22 agmsmith
* Fixed bugs so now it compiles.
*
* Revision 1.1 2002/09/21 20:47:15 agmsmith
* Initial revision
*/
#include <Beep.h> #include <Beep.h>
#include <Catalog.h> #include <Catalog.h>
@@ -123,76 +32,62 @@
#include <FindDirectory.h> #include <FindDirectory.h>
#include <Entry.h> #include <Entry.h>
#include <stdlib.h>
#include <stdio.h>
#include "SpamFilter.h"
#undef B_TRANSLATION_CONTEXT #undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "SpamFilter" #define B_TRANSLATION_CONTEXT "SpamFilter"
// The names match the ones set up by spamdbm for sound effects. // The names match the ones set up by spamdbm for sound effects.
static const char *kAGMSBayesBeepGenuineName = "SpamFilter-Genuine"; static const char* kAGMSBayesBeepGenuineName = "SpamFilter-Genuine";
static const char *kAGMSBayesBeepSpamName = "SpamFilter-Spam"; static const char* kAGMSBayesBeepSpamName = "SpamFilter-Spam";
static const char *kAGMSBayesBeepUncertainName = "SpamFilter-Uncertain"; static const char* kAGMSBayesBeepUncertainName = "SpamFilter-Uncertain";
static const char *kServerSignature = "application/x-vnd.agmsmith.spamdbm"; static const char* kServerSignature = "application/x-vnd.agmsmith.spamdbm";
AGMSBayesianSpamFilter::AGMSBayesianSpamFilter(MailProtocol& protocol, SpamFilter::SpamFilter(BMailProtocol& protocol, BMailAddOnSettings* settings)
AddonSettings* addonSettings)
: :
MailFilter(protocol, addonSettings), BMailFilter(protocol, settings)
fAddSpamToSubject(false),
fAutoTraining(true),
fGenuineCutoffRatio(0.01f),
fHeaderOnly(false),
fLaunchAttemptCount(0),
fNoWordsMeansSpam(true),
fQuitServerWhenFinished(false),
fSpamCutoffRatio(0.99f)
{ {
bool tempBool; if (settings->FindBool("AddMarkerToSubject", &fAddSpamToSubject) != B_OK)
float tempFloat; fAddSpamToSubject = false;
BMessenger tempMessenger; if (settings->FindBool("AutoTraining", &fAutoTraining) != B_OK)
fAutoTraining = true;
const BMessage* settings = &addonSettings->Settings(); if (settings->FindFloat("GenuineCutoffRatio", &fGenuineCutoffRatio) != B_OK)
if (settings != NULL) { fGenuineCutoffRatio = 0.01f;
if (settings->FindBool ("AddMarkerToSubject", &tempBool) == B_OK) if (settings->FindBool("NoWordsMeansSpam", &fNoWordsMeansSpam) != B_OK)
fAddSpamToSubject = tempBool; fNoWordsMeansSpam = true;
if (settings->FindBool ("AutoTraining", &tempBool) == B_OK) if (settings->FindBool("QuitServerWhenFinished",
fAutoTraining = tempBool; &fQuitServerWhenFinished) != B_OK)
if (settings->FindFloat ("GenuineCutoffRatio", &tempFloat) == B_OK) fQuitServerWhenFinished = false;
fGenuineCutoffRatio = tempFloat; if (settings->FindFloat("SpamCutoffRatio", &fSpamCutoffRatio) != B_OK)
if (settings->FindBool ("NoWordsMeansSpam", &tempBool) == B_OK) fSpamCutoffRatio = 0.99f;
fNoWordsMeansSpam = tempBool;
if (settings->FindBool ("QuitServerWhenFinished", &tempBool) == B_OK)
fQuitServerWhenFinished = tempBool;
if (settings->FindFloat ("SpamCutoffRatio", &tempFloat) == B_OK)
fSpamCutoffRatio = tempFloat;
}
} }
AGMSBayesianSpamFilter::~AGMSBayesianSpamFilter () SpamFilter::~SpamFilter()
{ {
if (fQuitServerWhenFinished && fMessengerToServer.IsValid ()) if (fQuitServerWhenFinished)
fMessengerToServer.SendMessage(B_QUIT_REQUESTED); fMessengerToServer.SendMessage(B_QUIT_REQUESTED);
} }
BString
SpamFilter::DescriptiveName() const
{
return filter_name();
}
void void
AGMSBayesianSpamFilter::HeaderFetched(const entry_ref& ref, BFile* file) SpamFilter::HeaderFetched(const entry_ref& ref, BFile* file)
{ {
_CheckForSpam(file); _CheckForSpam(file);
} }
void void
AGMSBayesianSpamFilter::BodyFetched(const entry_ref& ref, BFile* file) SpamFilter::BodyFetched(const entry_ref& ref, BFile* file)
{ {
if (fHeaderOnly) if (fHeaderOnly)
return; return;
@@ -210,7 +105,7 @@ AGMSBayesianSpamFilter::BodyFetched(const entry_ref& ref, BFile* file)
status_t status_t
AGMSBayesianSpamFilter::_CheckForSpam(BFile* file) SpamFilter::_CheckForSpam(BFile* file)
{ {
// Get a connection to the spam database server. Launch if needed, should // Get a connection to the spam database server. Launch if needed, should
// only need it once, unless another e-mail thread shuts down the server // only need it once, unless another e-mail thread shuts down the server
@@ -231,7 +126,7 @@ AGMSBayesianSpamFilter::_CheckForSpam(BFile* file)
float spamRatio; float spamRatio;
if (_GetSpamRatio(stringBuffer, dataSize, spamRatio) != B_OK) if (_GetSpamRatio(stringBuffer, dataSize, spamRatio) != B_OK)
return B_ERROR; return B_ERROR;
// If we are auto-training, feed back the message to the server as a // If we are auto-training, feed back the message to the server as a
// training example (don't train if it is uncertain). // training example (don't train if it is uncertain).
if (fAutoTraining && (spamRatio >= fSpamCutoffRatio if (fAutoTraining && (spamRatio >= fSpamCutoffRatio
@@ -243,8 +138,8 @@ AGMSBayesianSpamFilter::_CheckForSpam(BFile* file)
// write attributes // write attributes
const char *classificationString; const char *classificationString;
classificationString = (spamRatio >= fSpamCutoffRatio) ? "Spam" classificationString = spamRatio >= fSpamCutoffRatio ? "Spam"
: ((spamRatio < fGenuineCutoffRatio) ? "Genuine" : "Uncertain"); : spamRatio < fGenuineCutoffRatio ? "Genuine" : "Uncertain";
file->WriteAttr("MAIL:classification", B_STRING_TYPE, 0 /* offset */, file->WriteAttr("MAIL:classification", B_STRING_TYPE, 0 /* offset */,
classificationString, strlen(classificationString) + 1); classificationString, strlen(classificationString) + 1);
@@ -262,63 +157,62 @@ AGMSBayesianSpamFilter::_CheckForSpam(BFile* file)
// "BiPolar" suggested. If the user doesn't want to hear the sound, they // "BiPolar" suggested. If the user doesn't want to hear the sound, they
// can turn it off in the system sound preferences. // can turn it off in the system sound preferences.
if (spamRatio >= fSpamCutoffRatio) { if (spamRatio >= fSpamCutoffRatio)
system_beep(kAGMSBayesBeepSpamName); system_beep(kAGMSBayesBeepSpamName);
} else if (spamRatio < fGenuineCutoffRatio) { else if (spamRatio < fGenuineCutoffRatio)
system_beep(kAGMSBayesBeepGenuineName); system_beep(kAGMSBayesBeepGenuineName);
} else { else
system_beep(kAGMSBayesBeepUncertainName); system_beep(kAGMSBayesBeepUncertainName);
}
return B_OK; return B_OK;
} }
status_t status_t
AGMSBayesianSpamFilter::_CheckForSpamServer() SpamFilter::_CheckForSpamServer()
{ {
// Make sure the server is running. // Make sure the server is running.
if (be_roster->IsRunning (kServerSignature)) if (be_roster->IsRunning (kServerSignature))
return B_OK; return B_OK;
status_t errorCode = be_roster->Launch (kServerSignature); status_t status = be_roster->Launch (kServerSignature);
if (errorCode == B_OK) if (status == B_OK)
return errorCode; return status;
BPath path; BPath path;
entry_ref ref; entry_ref ref;
directory_which places[] = { const directory_which kPlaces[] = {
B_SYSTEM_NONPACKAGED_BIN_DIRECTORY, B_SYSTEM_NONPACKAGED_BIN_DIRECTORY,
B_SYSTEM_BIN_DIRECTORY}; B_SYSTEM_BIN_DIRECTORY};
for (int32 i = 0; i < 2; i++) { for (size_t i = 0; i < sizeof(kPlaces) / sizeof(kPlaces[0]); i++) {
find_directory(places[i],&path); find_directory(kPlaces[i], &path);
path.Append("spamdbm"); path.Append("spamdbm");
if (!BEntry(path.Path()).Exists()) if (!BEntry(path.Path()).Exists())
continue; continue;
get_ref_for_path(path.Path(),&ref); get_ref_for_path(path.Path(), &ref);
if ((errorCode = be_roster->Launch(&ref)) == B_OK) if ((status = be_roster->Launch(&ref)) == B_OK)
break; break;
} }
return errorCode; return status;
} }
status_t status_t
AGMSBayesianSpamFilter::_GetTokenizeMode() SpamFilter::_GetTokenizeMode()
{ {
if (fLaunchAttemptCount > 3) if (fLaunchAttemptCount > 3)
return B_ERROR; // Don't try to start the server too many times. return B_ERROR; // Don't try to start the server too many times.
fLaunchAttemptCount++; fLaunchAttemptCount++;
// Make sure the server is running. // Make sure the server is running.
status_t errorCode = _CheckForSpamServer(); status_t status = _CheckForSpamServer();
if (errorCode != B_OK) if (status != B_OK)
return errorCode; return status;
// Set up the messenger to the database server. // Set up the messenger to the database server.
fMessengerToServer = BMessenger(kServerSignature); fMessengerToServer = BMessenger(kServerSignature);
if (!fMessengerToServer.IsValid ()) if (!fMessengerToServer.IsValid())
return B_ERROR; return B_ERROR;
// Check if the server is running in headers only mode. If so, we only // Check if the server is running in headers only mode. If so, we only
@@ -326,28 +220,26 @@ AGMSBayesianSpamFilter::_GetTokenizeMode()
BMessage scriptingMessage(B_GET_PROPERTY); BMessage scriptingMessage(B_GET_PROPERTY);
scriptingMessage.AddSpecifier("TokenizeMode"); scriptingMessage.AddSpecifier("TokenizeMode");
BMessage replyMessage; BMessage replyMessage;
if ((errorCode = fMessengerToServer.SendMessage (&scriptingMessage, if ((status = fMessengerToServer.SendMessage(&scriptingMessage,
&replyMessage)) != B_OK) &replyMessage)) != B_OK)
return errorCode; return status;
status_t tempErrorCode; status_t errorCode;
if ((errorCode = replyMessage.FindInt32 ("error", &tempErrorCode)) if ((status = replyMessage.FindInt32("error", &errorCode)) != B_OK)
!= B_OK) return status;
return errorCode; if (errorCode != B_OK)
if ((errorCode = tempErrorCode) != B_OK)
return errorCode; return errorCode;
const char *tokenizeModeStringPntr; const char* tokenizeMode;
if ((errorCode = replyMessage.FindString ("result", if ((status = replyMessage.FindString("result", &tokenizeMode)) != B_OK)
&tokenizeModeStringPntr)) != B_OK) return status;
return errorCode;
fHeaderOnly = (tokenizeModeStringPntr != NULL fHeaderOnly = tokenizeMode != NULL && !strcmp(tokenizeMode, "JustHeader");
&& strcmp (tokenizeModeStringPntr, "JustHeader") == 0);
return B_OK; return B_OK;
} }
status_t status_t
AGMSBayesianSpamFilter::_GetSpamRatio(const char* stringBuffer, off_t dataSize, SpamFilter::_GetSpamRatio(const char* stringBuffer, off_t dataSize,
float& ratio) float& ratio)
{ {
// Send off a scripting command to the database server, asking it to // Send off a scripting command to the database server, asking it to
@@ -379,7 +271,7 @@ AGMSBayesianSpamFilter::_GetSpamRatio(const char* stringBuffer, off_t dataSize,
status_t status_t
AGMSBayesianSpamFilter::_TrainServer(const char* stringBuffer, off_t dataSize, SpamFilter::_TrainServer(const char* stringBuffer, off_t dataSize,
float spamRatio) float spamRatio)
{ {
BMessage scriptingMessage(B_SET_PROPERTY); BMessage scriptingMessage(B_SET_PROPERTY);
@@ -401,7 +293,7 @@ AGMSBayesianSpamFilter::_TrainServer(const char* stringBuffer, off_t dataSize,
status_t status_t
AGMSBayesianSpamFilter::_AddSpamToSubject(BNode* file, float spamRatio) SpamFilter::_AddSpamToSubject(BNode* file, float spamRatio)
{ {
attr_info info; attr_info info;
if (file->GetAttrInfo("Subject", &info) != B_OK) if (file->GetAttrInfo("Subject", &info) != B_OK)
@@ -414,7 +306,7 @@ AGMSBayesianSpamFilter::_AddSpamToSubject(BNode* file, float spamRatio)
delete[] buffer; delete[] buffer;
return B_ERROR; return B_ERROR;
} }
BString newSubjectString; BString newSubjectString;
newSubjectString.SetTo("[Spam "); newSubjectString.SetTo("[Spam ");
char percentageString[30]; char percentageString[30];
@@ -431,15 +323,18 @@ AGMSBayesianSpamFilter::_AddSpamToSubject(BNode* file, float spamRatio)
} }
// #pragma mark -
BString BString
descriptive_name() filter_name()
{ {
return B_TRANSLATE("Spam Filter (AGMS Bayesian)"); return B_TRANSLATE("Bayesian Spam Filter");
} }
MailFilter* BMailFilter*
instantiate_mailfilter(MailProtocol& protocol, AddonSettings* settings) instantiate_filter(BMailProtocol& protocol, BMailAddOnSettings* settings)
{ {
return new AGMSBayesianSpamFilter(protocol, settings); return new SpamFilter(protocol, settings);
} }
@@ -4,96 +4,29 @@
* Copyright 2011, Clemens Zeidler <[email protected]> * Copyright 2011, Clemens Zeidler <[email protected]>
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#ifndef AGMS_BAYESIAN_SPAM_FILTER_H #ifndef SPAM_FILTER_H
#define AGMS_BAYESIAN_SPAM_FILTER_H #define SPAM_FILTER_H
/******************************************************************************
* $Id: SpamFilter.h 13952 2005-08-13 19:31:42Z agmsmith $
*
* SpamFilter - Uses Bayesian statistics to evaluate the spaminess of a
* message. The evaluation is done by a separate server, this add-on just gets
* the text and uses scripting commands to get an evaluation from the server.
* If the server isn't running, it will be found and started up. Once the
* evaluation has been received, it is added to the message as an attribute and
* optionally as an addition to the subject. Some other add-on later in the
* pipeline will use the attribute to delete the message or move it to some
* other folder.
*
* Public Domain 2002, by Alexander G. M. Smith, no warranty.
*
* $Log: SpamFilter.cpp,v $ (SVN doesn't support log messages so manually done)
* r11769 | bonefish | 2005-03-17 03:30:54 -0500 (Thu, 17 Mar 2005) | 1 line
* Move trunk into respective module.
*
* r9669 | brunoga | 2004-10-30 18:23:26 -0400 (Sat, 30 Oct 2004) | 2 lines
* AGMS Spam Filter.
*
* Revision 1.8 2004/09/20 15:57:30 nwhitehorn
* Mostly updated the tree to Be/Haiku style identifier naming conventions. I have a few more things to work out, mostly in mail_util.h, and then I'm proceeding to jamify the build system. Then we go into Haiku CVS.
*
* Revision 1.7 2003/05/27 17:12:59 nwhitehorn
* Massive refactoring of the Protocol/ChainRunner/Filter system. You can probably
* examine its scope by examining the number of files changed. Regardless, this is
* preparation for lots of new features, and REAL WORKING IMAP. Yes, you heard me.
* Enjoy, and prepare for bugs (although I've fixed all the ones I've found, I susp
* ect there are some memory leaks in ChainRunner).
*
* Revision 1.6 2003/02/08 21:54:17 agmsmith
* Updated the AGMSBayesianSpamServer documentation to match the current
* version. Also removed the Beep options from the spam filter, now they
* are turned on or off in the system sound preferences.
*
* Revision 1.5 2002/12/18 02:27:45 agmsmith
* Added uncertain classification as suggested by BiPolar.
*
* Revision 1.4 2002/12/12 00:56:28 agmsmith
* Added some new spam filter options - self training (not implemented yet)
* and a button to edit the server settings.
*
* Revision 1.3 2002/11/28 20:20:57 agmsmith
* Now checks if the spam database is running in headers only mode, and
* then only downloads headers if that is the case.
*
* Revision 1.2 2002/11/10 19:36:27 agmsmith
* Retry launching server a few times, but not too many.
*
* Revision 1.1 2002/11/03 02:06:15 agmsmith
* Added initial version.
*
* Revision 1.5 2002/10/21 16:13:59 agmsmith
* Added option to have no words mean spam.
*
* Revision 1.4 2002/10/11 20:01:28 agmsmith
* Added sound effects (system beep) for genuine and spam, plus config option
* for it.
*
* Revision 1.3 2002/09/23 19:14:13 agmsmith
* Added an option to have the server quit when done.
*
* Revision 1.2 2002/09/23 03:33:34 agmsmith
* First working version, with cutoff ratio and subject modification,
* and an attribute added if a patch is made to the Folder filter.
*
* Revision 1.1 2002/09/21 20:47:57 agmsmith
* Initial revision
*/
#include <Message.h>
#include <List.h>
#include <MailAddon.h>
class AGMSBayesianSpamFilter : public MailFilter { #include <MailFilter.h>
#include <Messenger.h>
class SpamFilter : public BMailFilter {
public: public:
AGMSBayesianSpamFilter(MailProtocol& protocol, SpamFilter(BMailProtocol& protocol,
AddonSettings* settings); BMailAddOnSettings* settings);
~AGMSBayesianSpamFilter(); virtual ~SpamFilter();
void HeaderFetched(const entry_ref& ref, BFile* file); virtual BString DescriptiveName() const;
void BodyFetched(const entry_ref& ref, BFile* file);
virtual void HeaderFetched(const entry_ref& ref,
BFile* file);
virtual void BodyFetched(const entry_ref& ref, BFile* file);
private: private:
status_t _CheckForSpam(BFile* file); status_t _CheckForSpam(BFile* file);
//! if the server is not running start it //! If the server is not running start it
status_t _CheckForSpamServer(); status_t _CheckForSpamServer();
status_t _GetTokenizeMode(); status_t _GetTokenizeMode();
status_t _GetSpamRatio(const char* data, off_t dataSize, status_t _GetSpamRatio(const char* data, off_t dataSize,
@@ -102,6 +35,7 @@ private:
float spamRatio); float spamRatio);
status_t _AddSpamToSubject(BNode* file, float spamRatio); status_t _AddSpamToSubject(BNode* file, float spamRatio);
private:
bool fAddSpamToSubject; bool fAddSpamToSubject;
bool fAutoTraining; bool fAutoTraining;
float fGenuineCutoffRatio; float fGenuineCutoffRatio;
@@ -113,4 +47,5 @@ private:
float fSpamCutoffRatio; float fSpamCutoffRatio;
}; };
#endif /* AGMS_BAYESIAN_SPAM_FILTER_H */
#endif // SPAM_FILTER_H
@@ -1,80 +1,15 @@
/****************************************************************************** /*
* $Id: SpamFilterConfig.cpp 19449 2006-12-09 03:38:11Z darkwyrm $ * Copyright 2004-2012, Haiku, Inc. All rights reserved.
* * Copyright 2002 Alexander G. M. Smith.
* SpamFilter's configuration view. Lets the user change various settings * Distributed under the terms of the MIT License.
* related to the add-on, but not the spamdbm server.
*
* $Log: SpamFilter.cpp,v $ (SVN doesn't support log messages so manually done)
* r11769 | bonefish | 2005-03-17 03:30:54 -0500 (Thu, 17 Mar 2005) | 1 line
* Move trunk into respective module.
*
* r10362 | nwhitehorn | 2004-12-06 20:14:05 -0500 (Mon, 06 Dec 2004) | 2 lines
* Fixed the spam filter so it works correctly now.
*
* r10097 | shatty | 2004-11-21 03:38:07 -0500 (Sun, 21 Nov 2004) | 2 lines
* remove unused variables
*
* r9934 | nwhitehorn | 2004-11-11 21:55:05 -0500 (Thu, 11 Nov 2004) | 2 lines
* Added AGMS's excellent spam detection software. Still some weirdness with
* the configuration interface from E-mail prefs.
*
* r9669 | brunoga | 2004-10-30 18:23:26 -0400 (Sat, 30 Oct 2004) | 2 lines
* AGMS Spam Filter.
*
* Revision 1.9 2004/09/20 15:57:30 nwhitehorn
* Mostly updated the tree to Be/Haiku style identifier naming conventions. I have a few more things to work out, mostly in mail_util.h, and then I'm proceeding to jamify the build system. Then we go into Haiku CVS.
*
* Revision 1.8 2003/07/08 21:12:47 agmsmith
* Changed other spam filter defaults to values I find useful.
*
* Revision 1.7 2003/07/08 20:56:40 agmsmith
* Turn on auto-training for the spam filter by default.
*
* Revision 1.6 2003/02/08 21:54:17 agmsmith
* Updated the AGMSBayesianSpamServer documentation to match the current
* version. Also removed the Beep options from the spam filter, now they
* are turned on or off in the system sound preferences.
*
* Revision 1.5 2002/12/18 02:27:45 agmsmith
* Added uncertain classification as suggested by BiPolar.
*
* Revision 1.4 2002/12/16 16:03:27 agmsmith
* Changed spam cutoff to 0.95 to work with default Chi-Squared scoring.
*
* Revision 1.3 2002/12/13 22:04:43 agmsmith
* Changed default to turn on the Spam marker in the subject.
*
* Revision 1.2 2002/12/12 00:56:28 agmsmith
* Added some new spam filter options - self training (not implemented yet)
* and a button to edit the server settings.
*
* Revision 1.1 2002/11/03 02:06:15 agmsmith
* Added initial version.
*
* Revision 1.7 2002/10/21 16:13:27 agmsmith
* Added option to have no words mean spam.
*
* Revision 1.6 2002/10/11 20:01:28 agmsmith
* Added sound effects (system beep) for genuine and spam, plus config option for it.
*
* Revision 1.5 2002/10/01 00:45:34 agmsmith
* Changed default spam ratio to 0.56 from 0.9, for use with
* the Gary Robinson method in AGMSBayesianSpamServer 1.49.
*
* Revision 1.4 2002/09/23 19:14:13 agmsmith
* Added an option to have the server quit when done.
*
* Revision 1.3 2002/09/23 03:33:34 agmsmith
* First working version, with cutoff ratio and subject modification,
* and an attribute added if a patch is made to the Folder filter.
*
* Revision 1.2 2002/09/21 20:57:22 agmsmith
* Fixed bugs so now it compiles.
*
* Revision 1.1 2002/09/21 20:48:11 agmsmith
* Initial revision
*/ */
/*! SpamFilter's configuration view. Lets the user change various settings
related to the add-on, but not the spamdbm server.
*/
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
@@ -82,6 +17,7 @@
#include <Button.h> #include <Button.h>
#include <Catalog.h> #include <Catalog.h>
#include <CheckBox.h> #include <CheckBox.h>
#include <LayoutBuilder.h>
#include <Message.h> #include <Message.h>
#include <Messenger.h> #include <Messenger.h>
#include <Roster.h> #include <Roster.h>
@@ -91,7 +27,7 @@
#include <Entry.h> #include <Entry.h>
#include <Path.h> #include <Path.h>
#include <MailAddon.h> #include <MailFilter.h>
#include <FileConfigView.h> #include <FileConfigView.h>
@@ -99,342 +35,120 @@
#define B_TRANSLATION_CONTEXT "SpamFilterConfig" #define B_TRANSLATION_CONTEXT "SpamFilterConfig"
static const char *kServerSignature = "application/x-vnd.agmsmith.spamdbm"; class SpamFilterConfig : public BView {
public:
SpamFilterConfig(const BMessage* settings);
class AGMSBayesianSpamFilterConfig : public BView { virtual status_t Archive(BMessage* into, bool deep = true) const;
public:
AGMSBayesianSpamFilterConfig (const BMessage *settings);
virtual void MessageReceived (BMessage *msg); private:
virtual void AttachedToWindow (); BCheckBox* fSubjectHintCheckBox;
virtual status_t Archive (BMessage *into, bool deep = true) const; BCheckBox* fAutoTrainingCheckBox;
virtual void GetPreferredSize (float *width, float *height); float fGenuineCutoffRatio;
BTextControl* fGenuineCutoffRatioTextControl;
private: BCheckBox* fNoWordsMeansSpamCheckBox;
void ShowSpamServerConfigurationWindow (); float fSpamCutoffRatio;
BTextControl* fSpamCutoffRatioTextControl;
bool fAddSpamToSubject;
BCheckBox *fAddSpamToSubjectCheckBoxPntr;
bool fAutoTraining;
BCheckBox *fAutoTrainingCheckBoxPntr;
float fGenuineCutoffRatio;
BTextControl *fGenuineCutoffRatioTextBoxPntr;
bool fNoWordsMeansSpam;
BCheckBox *fNoWordsMeansSpamCheckBoxPntr;
bool fQuitServerWhenFinished;
BCheckBox *fQuitServerWhenFinishedCheckBoxPntr;
BButton *fServerSettingsButtonPntr;
float fSpamCutoffRatio;
BTextControl *fSpamCutoffRatioTextBoxPntr;
static const uint32 kAddSpamToSubjectPressed = 'ASbj';
static const uint32 kAutoTrainingPressed = 'AuTr';
static const uint32 kNoWordsMeansSpam = 'NoWd';
static const uint32 kQuitWhenFinishedPressed = 'QuWF';
static const uint32 kServerSettingsPressed = 'SrvS';
}; };
AGMSBayesianSpamFilterConfig::AGMSBayesianSpamFilterConfig( SpamFilterConfig::SpamFilterConfig(const BMessage* settings)
const BMessage *settings) :
: BView (BRect (0,0,260,130), "spamfilter_config", BView("spamfilter_config", 0),
B_FOLLOW_LEFT | B_FOLLOW_TOP, 0), fSubjectHintCheckBox(NULL),
fAddSpamToSubject (false), fAutoTrainingCheckBox(NULL),
fAddSpamToSubjectCheckBoxPntr (NULL), fGenuineCutoffRatioTextControl(NULL),
fAutoTraining (true), fNoWordsMeansSpamCheckBox(NULL),
fAutoTrainingCheckBoxPntr (NULL), fSpamCutoffRatioTextControl(NULL)
fGenuineCutoffRatio (0.01f),
fGenuineCutoffRatioTextBoxPntr (NULL),
fNoWordsMeansSpam (true),
fNoWordsMeansSpamCheckBoxPntr (NULL),
fQuitServerWhenFinished (true),
fQuitServerWhenFinishedCheckBoxPntr (NULL),
fServerSettingsButtonPntr (NULL),
fSpamCutoffRatio (0.99f),
fSpamCutoffRatioTextBoxPntr (NULL)
{ {
bool tempBool; bool subjectHint;
float tempFloat; bool autoTraining;
bool noWordsMeansSpam;
if (settings->FindBool("AddMarkerToSubject", &subjectHint) != B_OK)
subjectHint = false;
if (settings->FindBool("AutoTraining", &autoTraining) != B_OK)
autoTraining = true;
if (settings->FindBool("NoWordsMeansSpam", &noWordsMeansSpam) != B_OK)
noWordsMeansSpam = true;
if (settings->FindBool ("AddMarkerToSubject", &tempBool) == B_OK) if (settings->FindFloat("GenuineCutoffRatio", &fGenuineCutoffRatio) != B_OK)
fAddSpamToSubject = tempBool; fGenuineCutoffRatio = 0.01f;
if (settings->FindBool ("AutoTraining", &tempBool) == B_OK) if (settings->FindFloat("SpamCutoffRatio", &fSpamCutoffRatio) != B_OK)
fAutoTraining = tempBool; fSpamCutoffRatio = 0.99f;
if (settings->FindFloat ("GenuineCutoffRatio", &tempFloat) == B_OK)
fGenuineCutoffRatio = tempFloat;
if (settings->FindBool ("NoWordsMeansSpam", &tempBool) == B_OK)
fNoWordsMeansSpam = tempBool;
if (settings->FindBool ("QuitServerWhenFinished", &tempBool) == B_OK)
fQuitServerWhenFinished = tempBool;
if (settings->FindFloat ("SpamCutoffRatio", &tempFloat) == B_OK)
fSpamCutoffRatio = tempFloat;
}
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
void AGMSBayesianSpamFilterConfig::AttachedToWindow () fSubjectHintCheckBox = new BCheckBox("AddToSubject",
{ B_TRANSLATE("Add spam rating to start of subject"), NULL);
char numberString [30]; fSubjectHintCheckBox->SetValue(subjectHint);
BRect tempRect;
const char *tempStringPntr;
SetViewColor (ui_color (B_PANEL_BACKGROUND_COLOR)); BString number;
number.SetToFormat("%06.4f", (double)fSpamCutoffRatio);
fSpamCutoffRatioTextControl = new BTextControl("spamcutoffratio",
B_TRANSLATE("Spam above:"), number.String(), NULL);
// Make the checkbox for choosing whether the spam is marked by a fNoWordsMeansSpamCheckBox = new BCheckBox("NoWordsMeansSpam",
// modification to the subject of the mail message. B_TRANSLATE("or empty e-mail"), NULL);
fNoWordsMeansSpamCheckBox->SetValue(noWordsMeansSpam);
tempRect = Bounds (); number.SetToFormat("%08.6f", (double)fGenuineCutoffRatio);
fAddSpamToSubjectCheckBoxPntr = new BCheckBox ( fGenuineCutoffRatioTextControl = new BTextControl("genuinecutoffratio",
tempRect, B_TRANSLATE("Genuine below and uncertain above:"),
"AddToSubject", number.String(), NULL);
B_TRANSLATE("Add spam rating to start of subject"),
new BMessage (kAddSpamToSubjectPressed));
AddChild (fAddSpamToSubjectCheckBoxPntr);
fAddSpamToSubjectCheckBoxPntr->ResizeToPreferred ();
fAddSpamToSubjectCheckBoxPntr->SetValue (fAddSpamToSubject);
fAddSpamToSubjectCheckBoxPntr->SetTarget (this);
tempRect = Bounds (); fAutoTrainingCheckBox = new BCheckBox("autoTraining",
tempRect.top = fAddSpamToSubjectCheckBoxPntr->Frame().bottom + 1; B_TRANSLATE("Learn from all incoming e-mail"), NULL);
tempRect.bottom = tempRect.top + 20; fAutoTrainingCheckBox->SetValue(autoTraining);
// Add the checkbox on the right for the no words means spam option. BLayoutBuilder::Group<>(this, B_VERTICAL)
.Add(fSubjectHintCheckBox)
fNoWordsMeansSpamCheckBoxPntr = new BCheckBox ( .AddGroup(B_HORIZONTAL)
tempRect, .Add(fSpamCutoffRatioTextControl->CreateLabelLayoutItem())
"NoWordsMeansSpam", .Add(fSpamCutoffRatioTextControl->CreateTextViewLayoutItem())
B_TRANSLATE("or empty e-mail"), .Add(fNoWordsMeansSpamCheckBox)
new BMessage (kNoWordsMeansSpam)); .End()
AddChild (fNoWordsMeansSpamCheckBoxPntr); .AddGroup(B_HORIZONTAL)
fNoWordsMeansSpamCheckBoxPntr->ResizeToPreferred (); .Add(fGenuineCutoffRatioTextControl->CreateLabelLayoutItem())
fNoWordsMeansSpamCheckBoxPntr->MoveBy ( .Add(fGenuineCutoffRatioTextControl->CreateTextViewLayoutItem())
floorf (tempRect.right - fNoWordsMeansSpamCheckBoxPntr->Frame().right), .End()
0.0); .Add(fAutoTrainingCheckBox);
fNoWordsMeansSpamCheckBoxPntr->SetValue (fNoWordsMeansSpam);
fNoWordsMeansSpamCheckBoxPntr->SetTarget (this);
// Add the box displaying the spam cutoff ratio to the left, in the space
// remaining between the left edge and the no words checkbox.
tempRect.right = fNoWordsMeansSpamCheckBoxPntr->Frame().left -
be_plain_font->StringWidth ("a");
tempStringPntr = B_TRANSLATE("Spam above:");
sprintf (numberString, "%06.4f", (double) fSpamCutoffRatio);
fSpamCutoffRatioTextBoxPntr = new BTextControl (
tempRect,
"spamcutoffratio",
tempStringPntr,
numberString,
NULL /* BMessage */);
AddChild (fSpamCutoffRatioTextBoxPntr);
fSpamCutoffRatioTextBoxPntr->SetDivider (
be_plain_font->StringWidth (tempStringPntr) +
1 * be_plain_font->StringWidth ("a"));
tempRect = Bounds ();
tempRect.top = fSpamCutoffRatioTextBoxPntr->Frame().bottom + 1;
tempRect.bottom = tempRect.top + 20;
// Add the box displaying the genuine cutoff ratio, on a line by itself.
tempStringPntr = B_TRANSLATE("Genuine below and uncertain above:");
sprintf (numberString, "%08.6f", (double) fGenuineCutoffRatio);
fGenuineCutoffRatioTextBoxPntr = new BTextControl (
tempRect,
"genuinecutoffratio",
tempStringPntr,
numberString,
NULL /* BMessage */);
AddChild (fGenuineCutoffRatioTextBoxPntr);
fGenuineCutoffRatioTextBoxPntr->SetDivider (
be_plain_font->StringWidth (tempStringPntr) +
1 * be_plain_font->StringWidth ("a"));
tempRect = Bounds ();
tempRect.top = fGenuineCutoffRatioTextBoxPntr->Frame().bottom + 1;
tempRect.bottom = tempRect.top + 20;
// Checkbox for automatically training on incoming mail.
fAutoTrainingCheckBoxPntr = new BCheckBox (
tempRect,
"autoTraining",
B_TRANSLATE("Learn from all incoming e-mail"),
new BMessage (kAutoTrainingPressed));
AddChild (fAutoTrainingCheckBoxPntr);
fAutoTrainingCheckBoxPntr->ResizeToPreferred ();
fAutoTrainingCheckBoxPntr->SetValue (fAutoTraining);
fAutoTrainingCheckBoxPntr->SetTarget (this);
tempRect = Bounds ();
tempRect.top = fAutoTrainingCheckBoxPntr->Frame().bottom + 1;
tempRect.bottom = tempRect.top + 20;
// Button for editing the server settings.
/* fServerSettingsButtonPntr = new BButton (
tempRect,
"serverSettings",
"Advanced Server Settings…",
new BMessage (kServerSettingsPressed));
AddChild (fServerSettingsButtonPntr);
fServerSettingsButtonPntr->ResizeToPreferred ();
fServerSettingsButtonPntr->SetTarget (this);
tempRect = Bounds ();
tempRect.top = fServerSettingsButtonPntr->Frame().bottom + 1;
tempRect.bottom = tempRect.top + 20;
// Checkbox for closing the server when done.
fQuitServerWhenFinishedCheckBoxPntr = new BCheckBox (
tempRect,
"quitWhenFinished",
"Close spam scanner when finished.",
new BMessage (kQuitWhenFinishedPressed));
AddChild (fQuitServerWhenFinishedCheckBoxPntr);
fQuitServerWhenFinishedCheckBoxPntr->ResizeToPreferred ();
fQuitServerWhenFinishedCheckBoxPntr->SetValue (fQuitServerWhenFinished);
fQuitServerWhenFinishedCheckBoxPntr->SetTarget (this);
tempRect = Bounds ();
tempRect.top = fQuitServerWhenFinishedCheckBoxPntr->Frame().bottom + 1;
tempRect.bottom = tempRect.top + 20;
*/
} }
status_t status_t
AGMSBayesianSpamFilterConfig::Archive (BMessage *into, bool deep) const SpamFilterConfig::Archive(BMessage* into, bool /*deep*/) const
{ {
status_t errorCode;
float tempFloat;
into->MakeEmpty(); into->MakeEmpty();
errorCode = into->AddBool ("AddMarkerToSubject", fAddSpamToSubject);
if (errorCode == B_OK) status_t status = into->AddBool("AddMarkerToSubject",
errorCode = into->AddBool ("AutoTraining", fAutoTraining); fSubjectHintCheckBox->Value() == B_CONTROL_ON);
if (errorCode == B_OK) if (status == B_OK) {
errorCode = into->AddBool ("QuitServerWhenFinished", fQuitServerWhenFinished); status = into->AddBool("AutoTraining",
fAutoTrainingCheckBox->Value() == B_CONTROL_ON);
if (errorCode == B_OK) }
errorCode = into->AddBool ("NoWordsMeansSpam", fNoWordsMeansSpam); if (status == B_OK) {
status = into->AddBool("NoWordsMeansSpam",
if (errorCode == B_OK) { fNoWordsMeansSpamCheckBox->Value() == B_CONTROL_ON);
tempFloat = fGenuineCutoffRatio; }
if (fGenuineCutoffRatioTextBoxPntr != NULL) if (status == B_OK) {
tempFloat = atof (fGenuineCutoffRatioTextBoxPntr->Text()); status = into->AddFloat("GenuineCutoffRatio",
errorCode = into->AddFloat ("GenuineCutoffRatio", tempFloat); atof(fGenuineCutoffRatioTextControl->Text()));
}
if (status == B_OK) {
status = into->AddFloat("SpamCutoffRatio",
atof(fSpamCutoffRatioTextControl->Text()));
} }
if (errorCode == B_OK) { return status;
tempFloat = fSpamCutoffRatio;
if (fSpamCutoffRatioTextBoxPntr != NULL)
tempFloat = atof (fSpamCutoffRatioTextBoxPntr->Text());
errorCode = into->AddFloat ("SpamCutoffRatio", tempFloat);
}
return errorCode;
} }
void // #pragma mark -
AGMSBayesianSpamFilterConfig::GetPreferredSize (float *width, float *height) {
*width = 260;
*height = 130;
}
void
AGMSBayesianSpamFilterConfig::MessageReceived (BMessage *msg)
{
switch (msg->what)
{
case kAddSpamToSubjectPressed:
fAddSpamToSubject = fAddSpamToSubjectCheckBoxPntr->Value ();
break;
case kAutoTrainingPressed:
fAutoTraining = fAutoTrainingCheckBoxPntr->Value ();
break;
case kNoWordsMeansSpam:
fNoWordsMeansSpam = fNoWordsMeansSpamCheckBoxPntr->Value ();
break;
case kQuitWhenFinishedPressed:
fQuitServerWhenFinished =
fQuitServerWhenFinishedCheckBoxPntr->Value ();
break;
case kServerSettingsPressed:
ShowSpamServerConfigurationWindow ();
break;
default:
BView::MessageReceived (msg);
}
}
void
AGMSBayesianSpamFilterConfig::ShowSpamServerConfigurationWindow () {
status_t errorCode = B_OK;
BMessage maximizeCommand;
BMessenger messengerToServer;
BMessage replyMessage;
// Make sure the server is running.
if (!be_roster->IsRunning (kServerSignature)) {
errorCode = be_roster->Launch (kServerSignature);
if (errorCode != B_OK) {
BPath path;
entry_ref ref;
directory_which places[] = {
B_SYSTEM_NONPACKAGED_BIN_DIRECTORY,
B_SYSTEM_BIN_DIRECTORY
};
for (int32 i = 0; i < 2; i++) {
find_directory(places[i],&path);
path.Append("spamdbm");
if (!BEntry(path.Path()).Exists())
continue;
get_ref_for_path(path.Path(),&ref);
if ((errorCode = be_roster->Launch (&ref)) == B_OK)
break;
}
if (errorCode != B_OK)
goto ErrorExit;
}
}
// Set up the messenger to the database server.
messengerToServer =
BMessenger (kServerSignature);
if (!messengerToServer.IsValid ())
goto ErrorExit;
// Wait for the server to finish starting up, and for it to create the window.
snooze (2000000);
// Tell it to show its main window, in case it is hidden in server mode.
maximizeCommand.what = B_SET_PROPERTY;
maximizeCommand.AddBool ("data", false);
maximizeCommand.AddSpecifier ("Minimize");
maximizeCommand.AddSpecifier ("Window", (int32)0);
errorCode = messengerToServer.SendMessage (&maximizeCommand, &replyMessage);
if (errorCode != B_OK)
goto ErrorExit;
return; // Successful.
ErrorExit:
BAlert* alert = new BAlert ("SpamFilterConfig Error", B_TRANSLATE("Sorry, "
"unable to launch the spamdbm program to let you edit the server "
"settings."), B_TRANSLATE("Close"));
alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
alert->Go ();
return;
}
BView* BView*
instantiate_filter_config_panel(AddonSettings& settings) instantiate_filter_config_panel(BMailAddOnSettings& settings)
{ {
return new AGMSBayesianSpamFilterConfig(&settings.Settings()); return new SpamFilterConfig(&settings);
} }
@@ -1,5 +1,5 @@
/* /*
* Copyright 2001-2011, Haiku, Inc. All rights reserved. * Copyright 2001-2012, Haiku, Inc. All rights reserved.
* Copyright 2001-2002 Dr. Zoidberg Enterprises. All rights reserved. * Copyright 2001-2002 Dr. Zoidberg Enterprises. All rights reserved.
* Copyright 2011, Clemens Zeidler <[email protected]> * Copyright 2011, Clemens Zeidler <[email protected]>
* *
@@ -9,10 +9,11 @@
#include <Button.h> #include <Button.h>
#include <Catalog.h> #include <Catalog.h>
#include <GridLayout.h>
#include <Path.h>
#include <TextControl.h> #include <TextControl.h>
#include <MailAddon.h> #include <MailFilter.h>
#include <Path.h>
#include <FileConfigView.h> #include <FileConfigView.h>
#include <ProtocolConfigView.h> #include <ProtocolConfigView.h>
@@ -25,31 +26,32 @@
#define B_TRANSLATION_CONTEXT "imap_config" #define B_TRANSLATION_CONTEXT "imap_config"
using namespace BPrivate;
const uint32 kMsgOpenIMAPFolder = '&OIF'; const uint32 kMsgOpenIMAPFolder = '&OIF';
class ConfigView : public BMailProtocolConfigView { class ConfigView : public MailProtocolConfigView {
public: public:
ConfigView(MailAddonSettings& settings, ConfigView(BMailAccountSettings& settings);
BMailAccountSettings& accountSettings);
virtual ~ConfigView(); virtual ~ConfigView();
virtual status_t Archive(BMessage *into, bool deep = true) const;
virtual void GetPreferredSize(float *width, float *height); virtual status_t Archive(BMessage* into, bool deep = true) const;
virtual void MessageReceived(BMessage* message); virtual void MessageReceived(BMessage* message);
virtual void AttachedToWindow(); virtual void AttachedToWindow();
private: private:
BMailFileConfigView* fFileView; MailFileConfigView* fFileView;
BButton* fIMAPFolderButton; BButton* fFolderButton;
MailAddonSettings& fAddonSettings; BMailProtocolSettings& fSettings;
}; };
ConfigView::ConfigView(MailAddonSettings& settings, ConfigView::ConfigView(BMailAccountSettings& settings)
BMailAccountSettings& accountSettings)
: :
BMailProtocolConfigView(B_MAIL_PROTOCOL_HAS_USERNAME MailProtocolConfigView(B_MAIL_PROTOCOL_HAS_USERNAME
| B_MAIL_PROTOCOL_HAS_PASSWORD | B_MAIL_PROTOCOL_HAS_HOSTNAME | B_MAIL_PROTOCOL_HAS_PASSWORD | B_MAIL_PROTOCOL_HAS_HOSTNAME
| B_MAIL_PROTOCOL_CAN_LEAVE_MAIL_ON_SERVER | B_MAIL_PROTOCOL_CAN_LEAVE_MAIL_ON_SERVER
| B_MAIL_PROTOCOL_PARTIAL_DOWNLOAD | B_MAIL_PROTOCOL_PARTIAL_DOWNLOAD
@@ -57,39 +59,31 @@ ConfigView::ConfigView(MailAddonSettings& settings,
| B_MAIL_PROTOCOL_HAS_FLAVORS | B_MAIL_PROTOCOL_HAS_FLAVORS
#endif #endif
), ),
fAddonSettings(settings) fSettings(settings.InboundSettings())
{ {
#ifdef USE_SSL #ifdef USE_SSL
AddFlavor(B_TRANSLATE("No encryption")); AddFlavor(B_TRANSLATE("No encryption"));
AddFlavor(B_TRANSLATE("SSL")); AddFlavor(B_TRANSLATE("SSL"));
#endif #endif
SetTo(settings); SetTo(settings.InboundSettings());
((BControl*)(FindView("leave_mail_on_server")))->SetValue(B_CONTROL_ON); ((BControl*)(FindView("leave_mail_on_server")))->SetValue(B_CONTROL_ON);
((BControl*)(FindView("leave_mail_on_server")))->Hide(); ((BControl*)(FindView("leave_mail_on_server")))->Hide();
BRect frame = FindView("delete_remote_when_local")->Frame(); fFolderButton = new BButton("IMAP Folders", B_TRANSLATE(
((BControl*)(FindView("delete_remote_when_local")))->SetEnabled(true);
((BControl*)(FindView("delete_remote_when_local")))->MoveBy(0, -25);
fIMAPFolderButton = new BButton(frame, "IMAP Folders", B_TRANSLATE(
"IMAP Folders"), new BMessage(kMsgOpenIMAPFolder)); "IMAP Folders"), new BMessage(kMsgOpenIMAPFolder));
AddChild(fIMAPFolderButton); Layout()->AddView(fFolderButton, 0, Layout()->CountRows(), 2);
frame.right -= 10;
BPath defaultFolder = BPrivate::default_mail_directory(); BPath defaultFolder = BPrivate::default_mail_directory();
defaultFolder.Append(accountSettings.Name()); defaultFolder.Append(settings.Name());
fFileView = new BMailFileConfigView(B_TRANSLATE("Destination:"), fFileView = new MailFileConfigView(B_TRANSLATE("Destination:"),
"destination", false, defaultFolder.Path()); "destination", false, defaultFolder.Path());
fFileView->SetTo(&settings.Settings(), NULL); fFileView->SetTo(&settings.InboundSettings(), NULL);
AddChild(fFileView);
fFileView->MoveBy(0, frame.bottom + 5);
ResizeToPreferred(); Layout()->AddView(fFileView, 0, Layout()->CountRows(),
Layout()->CountColumns());
} }
@@ -99,18 +93,10 @@ ConfigView::~ConfigView()
status_t status_t
ConfigView::Archive(BMessage *into, bool deep) const ConfigView::Archive(BMessage* into, bool deep) const
{ {
fFileView->Archive(into, deep); fFileView->Archive(into, deep);
return BMailProtocolConfigView::Archive(into, deep); return MailProtocolConfigView::Archive(into, deep);
}
void
ConfigView::GetPreferredSize(float *width, float *height)
{
BMailProtocolConfigView::GetPreferredSize(width,height);
*height -= 20;
} }
@@ -129,7 +115,7 @@ ConfigView::MessageReceived(BMessage* message)
} }
default: default:
BMailProtocolConfigView::MessageReceived(message); MailProtocolConfigView::MessageReceived(message);
} }
} }
@@ -137,7 +123,7 @@ ConfigView::MessageReceived(BMessage* message)
void void
ConfigView::AttachedToWindow() ConfigView::AttachedToWindow()
{ {
fIMAPFolderButton->SetTarget(this); fFolderButton->SetTarget(this);
} }
@@ -145,8 +131,7 @@ ConfigView::AttachedToWindow()
BView* BView*
instantiate_config_panel(MailAddonSettings& settings, instantiate_protocol_config_panel(BMailAccountSettings& settings)
BMailAccountSettings& accountSettings)
{ {
return new ConfigView(settings, accountSettings); return new ConfigView(settings);
} }
@@ -1,5 +1,5 @@
/* /*
* Copyright 2007-2011, Haiku, Inc. All rights reserved. * Copyright 2007-2012, Haiku, Inc. All rights reserved.
* Copyright 2001-2002 Dr. Zoidberg Enterprises. All rights reserved. * Copyright 2001-2002 Dr. Zoidberg Enterprises. All rights reserved.
* Copyright 2011, Clemens Zeidler <[email protected]> * Copyright 2011, Clemens Zeidler <[email protected]>
* *
@@ -8,8 +8,10 @@
#include <Catalog.h> #include <Catalog.h>
#include <GridLayout.h>
#include <MailFilter.h>
#include <FileConfigView.h> #include <FileConfigView.h>
#include <MailAddon.h>
#include <MailPrivate.h> #include <MailPrivate.h>
#include <ProtocolConfigView.h> #include <ProtocolConfigView.h>
@@ -18,21 +20,22 @@
#define B_TRANSLATION_CONTEXT "ConfigView" #define B_TRANSLATION_CONTEXT "ConfigView"
class POP3ConfigView : public BMailProtocolConfigView { using namespace BPrivate;
class POP3ConfigView : public MailProtocolConfigView {
public: public:
POP3ConfigView(MailAddonSettings& settings, POP3ConfigView(BMailAccountSettings& settings);
BMailAccountSettings& accountSettings); status_t Archive(BMessage* into, bool deep = true) const;
status_t Archive(BMessage *into, bool deep = true) const;
void GetPreferredSize(float *width, float *height);
private: private:
BMailFileConfigView* fFileView; MailFileConfigView* fFileView;
}; };
POP3ConfigView::POP3ConfigView(MailAddonSettings& settings, POP3ConfigView::POP3ConfigView(BMailAccountSettings& settings)
BMailAccountSettings& accountSettings)
: :
BMailProtocolConfigView(B_MAIL_PROTOCOL_HAS_USERNAME MailProtocolConfigView(B_MAIL_PROTOCOL_HAS_USERNAME
| B_MAIL_PROTOCOL_HAS_AUTH_METHODS | B_MAIL_PROTOCOL_HAS_PASSWORD | B_MAIL_PROTOCOL_HAS_AUTH_METHODS | B_MAIL_PROTOCOL_HAS_PASSWORD
| B_MAIL_PROTOCOL_HAS_HOSTNAME | B_MAIL_PROTOCOL_HAS_HOSTNAME
| B_MAIL_PROTOCOL_CAN_LEAVE_MAIL_ON_SERVER | B_MAIL_PROTOCOL_CAN_LEAVE_MAIL_ON_SERVER
@@ -50,40 +53,30 @@ POP3ConfigView::POP3ConfigView(MailAddonSettings& settings,
AddFlavor(B_TRANSLATE("SSL")); AddFlavor(B_TRANSLATE("SSL"));
#endif #endif
SetTo(settings); SetTo(settings.InboundSettings());
fFileView = new BMailFileConfigView(B_TRANSLATE("Destination:"), fFileView = new MailFileConfigView(B_TRANSLATE("Destination:"),
"destination", false, BPrivate::default_mail_in_directory().Path()); "destination", false, BPrivate::default_mail_in_directory().Path());
fFileView->SetTo(&settings.Settings(), NULL); fFileView->SetTo(&settings.InboundSettings(), NULL);
AddChild(fFileView);
float w, h; Layout()->AddView(fFileView, 0, Layout()->CountRows(),
BMailProtocolConfigView::GetPreferredSize(&w, &h); Layout()->CountColumns());
fFileView->MoveBy(0, h - 10);
GetPreferredSize(&w, &h);
ResizeTo(w, h);
} }
status_t status_t
POP3ConfigView::Archive(BMessage *into, bool deep) const POP3ConfigView::Archive(BMessage* into, bool deep) const
{ {
fFileView->Archive(into, deep); fFileView->Archive(into, deep);
return BMailProtocolConfigView::Archive(into, deep); return MailProtocolConfigView::Archive(into, deep);
} }
void // #pragma mark -
POP3ConfigView::GetPreferredSize(float* width, float* height)
{
BMailProtocolConfigView::GetPreferredSize(width, height);
*height += 20;
}
BView* BView*
instantiate_config_panel(MailAddonSettings& settings, instantiate_protocol_config_panel(BMailAccountSettings& settings)
BMailAccountSettings& accountSettings)
{ {
return new POP3ConfigView(settings, accountSettings); return new POP3ConfigView(settings);
} }
@@ -65,15 +65,15 @@ NotHere(BStringList& that, BStringList& otherList, BStringList* results)
// #pragma mark - // #pragma mark -
POP3Protocol::POP3Protocol(BMailAccountSettings* settings) POP3Protocol::POP3Protocol(const BMailAccountSettings& settings)
: :
InboundProtocol(settings), BInboundMailProtocol(settings),
fNumMessages(-1), fNumMessages(-1),
fMailDropSize(0), fMailDropSize(0),
fServerConnection(NULL) fServerConnection(NULL)
{ {
printf("POP3Protocol::POP3Protocol(BMailAccountSettings* settings)\n"); printf("POP3Protocol::POP3Protocol(BMailAccountSettings* settings)\n");
fSettings = fAccountSettings.InboundSettings().Settings(); fSettings = fAccountSettings.InboundSettings();
fUseSSL = fSettings.FindInt32("flavor") == 1 ? true : false; fUseSSL = fSettings.FindInt32("flavor") == 1 ? true : false;
@@ -145,13 +145,15 @@ POP3Protocol::SyncMessages()
SetTotalItems(2); SetTotalItems(2);
ReportProgress(0, 1, B_TRANSLATE("Connect to server" B_UTF8_ELLIPSIS)); ReportProgress(0, 1, B_TRANSLATE("Connect to server" B_UTF8_ELLIPSIS));
status_t error = Connect(); status_t error = Connect();
if (error < B_OK) { if (error != B_OK) {
ResetProgress(); ResetProgress();
return error; return error;
} }
ReportProgress(0, 1, B_TRANSLATE("Getting UniqueIDs" B_UTF8_ELLIPSIS)); ReportProgress(0, 1, B_TRANSLATE("Getting UniqueIDs" B_UTF8_ELLIPSIS));
error = _RetrieveUniqueIDs(); error = _RetrieveUniqueIDs();
if (error < B_OK) { if (error < B_OK) {
ResetProgress(); ResetProgress();
@@ -256,11 +258,11 @@ POP3Protocol::FetchBody(const entry_ref& ref)
SetTotalItems(1); SetTotalItems(1);
status_t error = Connect(); status_t error = Connect();
if (error < B_OK) if (error != B_OK)
return error; return error;
error = _RetrieveUniqueIDs(); error = _RetrieveUniqueIDs();
if (error < B_OK) { if (error != B_OK) {
Disconnect(); Disconnect();
return error; return error;
} }
@@ -354,14 +356,10 @@ POP3Protocol::Open(const char* server, int port, int)
fLog = ""; fLog = "";
// Prime the error message // Prime the error message
BString error_msg, servString; BString errorMessage(B_TRANSLATE("Error while connecting to server %serv"));
error_msg << B_TRANSLATE("Error while connecting to server %serv"); errorMessage.ReplaceFirst("%serv", server);
servString << server;
error_msg.ReplaceFirst("%serv", servString);
if (port != 110) if (port != 110)
error_msg << ":" << port; errorMessage << ":" << port;
uint32 hostIP = inet_addr(server); uint32 hostIP = inet_addr(server);
// first see if we can parse it as a numeric address // first see if we can parse it as a numeric address
@@ -371,8 +369,8 @@ POP3Protocol::Open(const char* server, int port, int)
} }
if (hostIP == 0) { if (hostIP == 0) {
error_msg << B_TRANSLATE(": Connection refused or host not found"); errorMessage << B_TRANSLATE(": Connection refused or host not found");
ShowError(error_msg.String()); ShowError(errorMessage.String());
return B_NAME_NOT_FOUND; return B_NAME_NOT_FOUND;
} }
@@ -397,19 +395,19 @@ POP3Protocol::Open(const char* server, int port, int)
if (err < 0) { if (err < 0) {
fServerConnection->Disconnect(); fServerConnection->Disconnect();
error_msg << ": " << strerror(err); errorMessage << ": " << strerror(err);
ShowError(error_msg.String()); ShowError(errorMessage.String());
return B_ERROR; return B_ERROR;
} }
if (strncmp(line.String(), "+OK", 3) != 0) { if (strncmp(line.String(), "+OK", 3) != 0) {
if (line.Length() > 0) { if (line.Length() > 0) {
error_msg << B_TRANSLATE(". The server said:\n") errorMessage << B_TRANSLATE(". The server said:\n")
<< line.String(); << line.String();
} else } else
error_msg << B_TRANSLATE(": No reply.\n"); errorMessage << B_TRANSLATE(": No reply.\n");
ShowError(error_msg.String()); ShowError(errorMessage.String());
fServerConnection->Disconnect(); fServerConnection->Disconnect();
return B_ERROR; return B_ERROR;
} }
@@ -877,11 +875,9 @@ POP3Protocol::_RetrieveUniqueIDs()
{ {
fUniqueIDs.MakeEmpty(); fUniqueIDs.MakeEmpty();
status_t ret = B_OK; status_t status = SendCommand("UIDL" CRLF);
if (status != B_OK)
ret = SendCommand("UIDL" CRLF); return status;
if (ret != B_OK)
return ret;
BString result; BString result;
int32 uidOffset; int32 uidOffset;
@@ -897,20 +893,20 @@ POP3Protocol::_RetrieveUniqueIDs()
if (SendCommand("LIST" CRLF) != B_OK) if (SendCommand("LIST" CRLF) != B_OK)
return B_ERROR; return B_ERROR;
int32 b;
while (ReceiveLine(result) > 0) { while (ReceiveLine(result) > 0) {
if (result.ByteAt(0) == '.') if (result.ByteAt(0) == '.')
break; break;
b = result.FindLast(" "); int32 index = result.FindLast(" ");
if (b >= 0) int32 size;
b = atol(&(result.String()[b])); if (index >= 0)
size = atol(&result.String()[index]);
else else
b = 0; size = 0;
fSizes.AddItem((void *)(addr_t)b); fSizes.AddItem((void*)size);
} }
return ret; return B_OK;
} }
@@ -975,15 +971,15 @@ POP3Protocol::_WriteManifest()
// #pragma mark - // #pragma mark -
InboundProtocol* BInboundMailProtocol*
instantiate_inbound_protocol(BMailAccountSettings* settings) instantiate_inbound_protocol(const BMailAccountSettings& settings)
{ {
return new POP3Protocol(settings); return new POP3Protocol(settings);
} }
status_t status_t
pop3_smtp_auth(BMailAccountSettings* settings) pop3_smtp_auth(const BMailAccountSettings& settings)
{ {
POP3Protocol protocol(settings); POP3Protocol protocol(settings);
protocol.Connect(); protocol.Connect();
@@ -15,20 +15,20 @@
#include <DataIO.h> #include <DataIO.h>
#include <List.h> #include <List.h>
#include <String.h> #include <String.h>
#include <StringList.h>
#include <View.h> #include <View.h>
#include "MailAddon.h" #include <MailProtocol.h>
#include "MailProtocol.h" #include <MailSettings.h>
#include "MailSettings.h"
#include <StringList.h>
class BSocket; class BSocket;
class POP3Protocol : public InboundProtocol { class POP3Protocol : public BInboundMailProtocol {
public: public:
POP3Protocol(BMailAccountSettings* settings); POP3Protocol(
const BMailAccountSettings& settings);
~POP3Protocol(); ~POP3Protocol();
status_t Connect(); status_t Connect();
@@ -86,7 +86,7 @@ private:
}; };
extern "C" status_t pop3_smtp_auth(BMessage& settings); extern "C" status_t pop3_smtp_auth(const BMailAccountSettings& settings);
#endif /* POP3_H */ #endif /* POP3_H */
@@ -1,18 +1,19 @@
/* /*
* Copyright 2007-2011, Haiku, Inc. All rights reserved. * Copyright 2007-2012, Haiku, Inc. All rights reserved.
* Copyright 2001-2002 Dr. Zoidberg Enterprises. All rights reserved. * Copyright 2001-2002, Dr. Zoidberg Enterprises. All rights reserved.
* Copyright 2011, Clemens Zeidler <[email protected]> * Copyright 2011, Clemens Zeidler <[email protected]>
* *
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#include <Catalog.h>
#include <GridLayout.h>
#include <MailFilter.h>
#include <MenuField.h>
#include <TextControl.h> #include <TextControl.h>
#include <Catalog.h>
#include <FileConfigView.h> #include <FileConfigView.h>
#include <MailAddon.h>
#include <MenuField.h>
#include <MailPrivate.h> #include <MailPrivate.h>
#include <ProtocolConfigView.h> #include <ProtocolConfigView.h>
@@ -21,21 +22,24 @@
#define B_TRANSLATION_CONTEXT "ConfigView" #define B_TRANSLATION_CONTEXT "ConfigView"
class SMTPConfigView : public BMailProtocolConfigView { using namespace BPrivate;
class SMTPConfigView : public MailProtocolConfigView {
public: public:
SMTPConfigView(MailAddonSettings& settings, SMTPConfigView(BMailAccountSettings& settings);
BMailAccountSettings& accountSettings);
status_t Archive(BMessage *into, bool deep = true) const; status_t Archive(BMessage* into,
void GetPreferredSize(float *width, float *height); bool deep = true) const;
private: private:
BMailFileConfigView* fFileView; MailFileConfigView* fFileView;
}; };
SMTPConfigView::SMTPConfigView(MailAddonSettings& settings, SMTPConfigView::SMTPConfigView(BMailAccountSettings& settings)
BMailAccountSettings& accountSettings)
: :
BMailProtocolConfigView(B_MAIL_PROTOCOL_HAS_AUTH_METHODS MailProtocolConfigView(B_MAIL_PROTOCOL_HAS_AUTH_METHODS
| B_MAIL_PROTOCOL_HAS_USERNAME | B_MAIL_PROTOCOL_HAS_PASSWORD | B_MAIL_PROTOCOL_HAS_USERNAME | B_MAIL_PROTOCOL_HAS_PASSWORD
| B_MAIL_PROTOCOL_HAS_HOSTNAME | B_MAIL_PROTOCOL_HAS_HOSTNAME
#ifdef USE_SSL #ifdef USE_SSL
@@ -57,58 +61,33 @@ SMTPConfigView::SMTPConfigView(MailAddonSettings& settings,
AddAuthMethod(B_TRANSLATE("ESMTP")); AddAuthMethod(B_TRANSLATE("ESMTP"));
AddAuthMethod(B_TRANSLATE("POP3 before SMTP"), false); AddAuthMethod(B_TRANSLATE("POP3 before SMTP"), false);
BTextControl *control = (BTextControl *)(FindView("host")); BTextControl* control = (BTextControl*)FindView("host");
control->SetLabel(B_TRANSLATE("SMTP server:")); control->SetLabel(B_TRANSLATE("SMTP server:"));
// Reset the dividers after changing one SetTo(settings.OutboundSettings());
float widestLabel = 0;
for (int32 i = CountChildren(); i-- > 0;) {
if (BTextControl *text = dynamic_cast<BTextControl *>(ChildAt(i)))
widestLabel = MAX(widestLabel,text->StringWidth(text->Label()) + 5);
}
for (int32 i = CountChildren(); i-- > 0;) {
if (BTextControl *text = dynamic_cast<BTextControl *>(ChildAt(i)))
text->SetDivider(widestLabel);
}
BMenuField *field = (BMenuField *)(FindView("auth_method")); fFileView = new MailFileConfigView(B_TRANSLATE("Destination:"), "path",
field->SetDivider(widestLabel);
SetTo(settings);
fFileView = new BMailFileConfigView(B_TRANSLATE("Destination:"), "path",
false, BPrivate::default_mail_out_directory().Path()); false, BPrivate::default_mail_out_directory().Path());
fFileView->SetTo(&settings.Settings(), NULL); fFileView->SetTo(&settings.OutboundSettings(), NULL);
AddChild(fFileView);
float w, h; Layout()->AddView(fFileView, 0, Layout()->CountRows(),
BMailProtocolConfigView::GetPreferredSize(&w, &h); Layout()->CountColumns());
fFileView->MoveBy(0, h - 10);
GetPreferredSize(&w, &h);
ResizeTo(w, h);
} }
status_t status_t
SMTPConfigView::Archive(BMessage *into, bool deep) const SMTPConfigView::Archive(BMessage* into, bool deep) const
{ {
fFileView->Archive(into, deep); fFileView->Archive(into, deep);
return BMailProtocolConfigView::Archive(into, deep); return MailProtocolConfigView::Archive(into, deep);
} }
void // #pragma mark -
SMTPConfigView::GetPreferredSize(float* width, float* height)
{
BMailProtocolConfigView::GetPreferredSize(width, height);
*width += 20;
*height += 20;
}
BView* BView*
instantiate_config_panel(MailAddonSettings& settings, instantiate_protocol_config_panel(BMailAccountSettings& settings)
BMailAccountSettings& accountSettings)
{ {
return new SMTPConfigView(settings, accountSettings); return new SMTPConfigView(settings);
} }
@@ -1,5 +1,5 @@
/* /*
* Copyright 2007-2011, Haiku, Inc. All rights reserved. * Copyright 2007-2012, Haiku, Inc. All rights reserved.
* Copyright 2001-2002 Dr. Zoidberg Enterprises. All rights reserved. * Copyright 2001-2002 Dr. Zoidberg Enterprises. All rights reserved.
* Copyright 2011, Clemens Zeidler <[email protected]> * Copyright 2011, Clemens Zeidler <[email protected]>
* *
@@ -63,6 +63,16 @@
# define D(x) ; # define D(x) ;
#endif #endif
// Authentication types recognized. Not all methods are implemented.
enum AuthType {
LOGIN = 1,
PLAIN = 1 << 2,
CRAM_MD5 = 1 << 3,
DIGEST_MD5 = 1 << 4
};
using namespace std; using namespace std;
/* /*
@@ -233,34 +243,27 @@ SplitChallengeIntoMap(BString str, map<BString,BString>& m)
} }
// Authentication types recognized. Not all methods are implemented. // #pragma mark -
enum AuthType {
LOGIN = 1,
PLAIN = 1 << 2,
CRAM_MD5 = 1 << 3,
DIGEST_MD5 = 1 << 4
};
SMTPProtocol::SMTPProtocol(BMailAccountSettings* settings) SMTPProtocol::SMTPProtocol(BMailAccountSettings& settings)
: :
OutboundProtocol(settings), BOutboundMailProtocol(settings),
fAuthType(0) fAuthType(0)
{ {
fSettingsMessage = settings->OutboundSettings().Settings(); fSettingsMessage = settings.OutboundSettings();
} }
SMTPProtocol::~SMTPProtocol() SMTPProtocol::~SMTPProtocol()
{ {
} }
status_t status_t
SMTPProtocol::Connect() SMTPProtocol::Connect()
{ {
BString error_msg; BString errorMessage;
int32 authMethod = fSettingsMessage.FindInt32("auth_method"); int32 authMethod = fSettingsMessage.FindInt32("auth_method");
status_t status = B_ERROR; status_t status = B_ERROR;
@@ -271,9 +274,9 @@ SMTPProtocol::Connect()
// to the SMTP server first... // to the SMTP server first...
status_t status = _POP3Authentication(); status_t status = _POP3Authentication();
if (status < B_OK) { if (status < B_OK) {
error_msg << B_TRANSLATE("POP3 authentication failed. The server " errorMessage << B_TRANSLATE("POP3 authentication failed. The "
"said:\n") << fLog; "server said:\n") << fLog;
ShowError(error_msg.String()); ShowError(errorMessage.String());
return status; return status;
} }
} }
@@ -281,19 +284,22 @@ SMTPProtocol::Connect()
status = Open(fSettingsMessage.FindString("server"), status = Open(fSettingsMessage.FindString("server"),
fSettingsMessage.FindInt32("port"), authMethod == 1); fSettingsMessage.FindInt32("port"), authMethod == 1);
if (status < B_OK) { if (status < B_OK) {
error_msg << B_TRANSLATE("Error while opening connection to %serv"); errorMessage << B_TRANSLATE("Error while opening connection to %serv");
error_msg.ReplaceFirst("%serv", fSettingsMessage.FindString("server")); errorMessage.ReplaceFirst("%serv",
fSettingsMessage.FindString("server"));
if (fSettingsMessage.FindInt32("port") > 0) if (fSettingsMessage.FindInt32("port") > 0)
error_msg << ":" << fSettingsMessage.FindInt32("port"); errorMessage << ":" << fSettingsMessage.FindInt32("port");
// << strerror(err) - BNetEndpoint sucks, we can't use this; // << strerror(err) - BNetEndpoint sucks, we can't use this;
if (fLog.Length() > 0) if (fLog.Length() > 0)
error_msg << B_TRANSLATE(". The server says:\n") << fLog; errorMessage << B_TRANSLATE(". The server says:\n") << fLog;
else else {
error_msg << B_TRANSLATE(": Connection refused or host not found."); errorMessage
<< B_TRANSLATE(": Connection refused or host not found.");
}
ShowError(error_msg.String()); ShowError(errorMessage.String());
return status; return status;
} }
@@ -303,13 +309,12 @@ SMTPProtocol::Connect()
delete[] password; delete[] password;
if (status != B_OK) { if (status != B_OK) {
//-----This is a really cool kind of error message. How can we make it work for POP3? errorMessage << B_TRANSLATE("Error while logging in to %serv")
error_msg << B_TRANSLATE("Error while logging in to %serv")
<< B_TRANSLATE(". The server said:\n") << fLog; << B_TRANSLATE(". The server said:\n") << fLog;
errorMessage.ReplaceFirst("%serv",
fSettingsMessage.FindString("server"));
error_msg.ReplaceFirst("%serv", fSettingsMessage.FindString("server")); ShowError(errorMessage.String());
ShowError(error_msg.String());
} }
return B_OK; return B_OK;
} }
@@ -549,23 +554,23 @@ SMTPProtocol::_SendMessage(const entry_ref& mail)
status_t status_t
SMTPProtocol::_POP3Authentication() SMTPProtocol::_POP3Authentication()
{ {
const entry_ref& entry = fAccountSettings.InboundPath(); const entry_ref& entry = fAccountSettings.InboundAddOnRef();
if (strcmp(entry.name, "POP3") != 0) if (strcmp(entry.name, "POP3") != 0)
return B_ERROR; return B_ERROR;
status_t (*pop3_smtp_auth)(BMailAccountSettings*); status_t (*pop3_smtp_auth)(const BMailAccountSettings&);
BPath path(&entry); BPath path(&entry);
image_id image = load_add_on(path.Path()); image_id image = load_add_on(path.Path());
if (image < 0) if (image < 0)
return B_ERROR; return B_ERROR;
if (get_image_symbol(image, "pop3_smtp_auth", if (get_image_symbol(image, "pop3_smtp_auth",
B_SYMBOL_TYPE_TEXT, (void **)&pop3_smtp_auth) != B_OK) { B_SYMBOL_TYPE_TEXT, (void **)&pop3_smtp_auth) != B_OK) {
unload_add_on(image); unload_add_on(image);
image = -1; image = -1;
return B_ERROR; return B_ERROR;
} }
status_t status = (*pop3_smtp_auth)(&fAccountSettings); status_t status = (*pop3_smtp_auth)(fAccountSettings);
unload_add_on(image); unload_add_on(image);
return status; return status;
} }
@@ -1047,8 +1052,8 @@ SMTPProtocol::SendCommand(const char *cmd)
// #pragma mark - // #pragma mark -
OutboundProtocol* BOutboundMailProtocol*
instantiate_outbound_protocol(BMailAccountSettings* settings) instantiate_outbound_protocol(BMailAccountSettings& settings)
{ {
return new SMTPProtocol(settings); return new SMTPProtocol(settings);
} }
@@ -1,5 +1,5 @@
/* /*
* Copyright 2007-2011, Haiku Inc. All Rights Reserved. * Copyright 2007-2012, Haiku Inc. All Rights Reserved.
* Copyright 2001-2002 Dr. Zoidberg Enterprises. All rights reserved. * Copyright 2001-2002 Dr. Zoidberg Enterprises. All rights reserved.
* Copyright 2011, Clemens Zeidler <[email protected]> * Copyright 2011, Clemens Zeidler <[email protected]>
* *
@@ -11,20 +11,19 @@
#include <String.h> #include <String.h>
#include <MailAddon.h> #include <MailFilter.h>
#include <MailProtocol.h> #include <MailProtocol.h>
#include <MailSettings.h> #include <MailSettings.h>
#ifdef USE_SSL #ifdef USE_SSL
# include <openssl/ssl.h> # include <openssl/ssl.h>
# include <openssl/rand.h> # include <openssl/rand.h>
#endif #endif
class SMTPProtocol : public OutboundProtocol { class SMTPProtocol : public BOutboundMailProtocol {
public: public:
SMTPProtocol(BMailAccountSettings* settings); SMTPProtocol(BMailAccountSettings& settings);
~SMTPProtocol(); ~SMTPProtocol();
status_t Connect(); status_t Connect();
@@ -33,7 +32,6 @@ public:
status_t SendMessages(const std::vector<entry_ref>& status_t SendMessages(const std::vector<entry_ref>&
mails, size_t totalBytes); mails, size_t totalBytes);
//----Perfectly good holdovers from the old days
status_t Open(const char *server, int port, bool esmtp); status_t Open(const char *server, int port, bool esmtp);
void Close(); void Close();
status_t Login(const char *uid, const char *password); status_t Login(const char *uid, const char *password);
@@ -53,12 +51,12 @@ private:
int32 fAuthType; int32 fAuthType;
#ifdef USE_SSL #ifdef USE_SSL
SSL_CTX *ctx; SSL_CTX* ctx;
SSL *ssl; SSL* ssl;
BIO *sbio; BIO* sbio;
bool use_ssl; bool use_ssl;
bool use_STARTTLS; bool use_STARTTLS;
#endif #endif
status_t fStatus; status_t fStatus;
+46 -74
View File
@@ -1,99 +1,81 @@
/* BMailFileConfigView - a file configuration view for filters /*
** * Copyright 2004-2012, Haiku, Inc. All rights reserved.
** Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved. * Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved.
*/ *
* Distributed under the terms of the MIT License.
*/
//! A file configuration view for filters
#include <FileConfigView.h>
#include <stdio.h> #include <stdio.h>
#include <Button.h> #include <Button.h>
#include <Catalog.h> #include <Catalog.h>
#include <GroupLayout.h>
#include <Message.h> #include <Message.h>
#include <Path.h> #include <Path.h>
#include <String.h> #include <String.h>
#include <TextControl.h> #include <TextControl.h>
#include <FileConfigView.h>
class _EXPORT BFileControl;
class _EXPORT BMailFileConfigView;
#undef B_TRANSLATION_CONTEXT #undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "MailKit" #define B_TRANSLATION_CONTEXT "MailKit"
const uint32 kMsgSelectButton = 'fsel'; static const uint32 kMsgSelectButton = 'fsel';
BFileControl::BFileControl(BRect rect, const char* name, const char* label, namespace BPrivate {
const char *pathOfFile,uint32 flavors)
FileControl::FileControl(const char* name, const char* label,
const char* pathOfFile, uint32 flavors)
: :
BView(rect, name, B_FOLLOW_LEFT | B_FOLLOW_TOP, 0) BView(name, 0)
{ {
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
SetLayout(new BGroupLayout(B_HORIZONTAL));
// determine font height fText = new BTextControl("file_path", label, pathOfFile, NULL);
font_height fontHeight;
GetFontHeight(&fontHeight);
float itemHeight = (int32)(fontHeight.ascent + fontHeight.descent
+ fontHeight.leading) + 13;
BString selectString = B_TRANSLATE("Select" B_UTF8_ELLIPSIS);
float labelWidth = StringWidth(selectString) + 20;
rect = Bounds();
rect.right -= labelWidth;
rect.top = 4;
rect.bottom = itemHeight + 2;
fText = new BTextControl(rect,"file_path", label, pathOfFile, NULL);
if (label)
fText->SetDivider(fText->StringWidth(label) + 6);
AddChild(fText); AddChild(fText);
fButton = new BButton(BRect(0, 0, 1, 1), "select_file", selectString, fButton = new BButton("select_file", B_TRANSLATE("Select" B_UTF8_ELLIPSIS),
new BMessage(kMsgSelectButton)); new BMessage(kMsgSelectButton));
fButton->ResizeToPreferred();
fButton->MoveBy(rect.right + 6,
(rect.Height() - fButton->Frame().Height()) / 2);
AddChild(fButton); AddChild(fButton);
fPanel = new BFilePanel(B_OPEN_PANEL, NULL, NULL, flavors, false); fPanel = new BFilePanel(B_OPEN_PANEL, NULL, NULL, flavors, false);
ResizeToPreferred();
} }
BFileControl::~BFileControl() FileControl::~FileControl()
{ {
delete fPanel; delete fPanel;
} }
void void
BFileControl::AttachedToWindow() FileControl::AttachedToWindow()
{ {
fButton->SetTarget(this); fButton->SetTarget(this);
fPanel->SetTarget(this);
BMessenger messenger(this);
if (messenger.IsValid())
fPanel->SetTarget(messenger);
} }
void void
BFileControl::MessageReceived(BMessage* msg) FileControl::MessageReceived(BMessage* msg)
{ {
switch (msg->what) switch (msg->what) {
{
case kMsgSelectButton: case kMsgSelectButton:
{ {
fPanel->Hide(); fPanel->Hide();
//fPanel->Window()->SetTitle(title);
BPath path(fText->Text()); BPath path(fText->Text());
if (path.InitCheck() >= B_OK) if (path.InitCheck() == B_OK && path.GetParent(&path) == B_OK)
if (path.GetParent(&path) >= B_OK) fPanel->SetPanelDirectory(path.Path());
fPanel->SetPanelDirectory(path.Path());
fPanel->Show(); fPanel->Show();
break; break;
@@ -101,11 +83,9 @@ BFileControl::MessageReceived(BMessage* msg)
case B_REFS_RECEIVED: case B_REFS_RECEIVED:
{ {
entry_ref ref; entry_ref ref;
if (msg->FindRef("refs", &ref) >= B_OK) if (msg->FindRef("refs", &ref) == B_OK) {
{
BEntry entry(&ref); BEntry entry(&ref);
if (entry.InitCheck() >= B_OK) if (entry.InitCheck() == B_OK) {
{
BPath path; BPath path;
entry.GetPath(&path); entry.GetPath(&path);
@@ -114,6 +94,7 @@ BFileControl::MessageReceived(BMessage* msg)
} }
break; break;
} }
default: default:
BView::MessageReceived(msg); BView::MessageReceived(msg);
break; break;
@@ -122,42 +103,34 @@ BFileControl::MessageReceived(BMessage* msg)
void void
BFileControl::SetText(const char* pathOfFile) FileControl::SetText(const char* pathOfFile)
{ {
fText->SetText(pathOfFile); fText->SetText(pathOfFile);
} }
const char* const char*
BFileControl::Text() const FileControl::Text() const
{ {
return fText->Text(); return fText->Text();
} }
void void
BFileControl::SetEnabled(bool enabled) FileControl::SetEnabled(bool enabled)
{ {
fText->SetEnabled(enabled); fText->SetEnabled(enabled);
fButton->SetEnabled(enabled); fButton->SetEnabled(enabled);
} }
void
BFileControl::GetPreferredSize(float* width, float* height)
{
*width = fButton->Frame().right + 5;
*height = fText->Bounds().Height() + 8;
}
//--------------------------------------------------------------------------
// #pragma mark - // #pragma mark -
BMailFileConfigView::BMailFileConfigView(const char* label, const char*name,
MailFileConfigView::MailFileConfigView(const char* label, const char* name,
bool useMeta, const char* defaultPath, uint32 flavors) bool useMeta, const char* defaultPath, uint32 flavors)
: :
BFileControl(BRect(5, 0, 255, 10), name, label, defaultPath, flavors), FileControl(name, label, defaultPath, flavors),
fUseMeta(useMeta), fUseMeta(useMeta),
fName(name) fName(name)
{ {
@@ -165,24 +138,23 @@ BMailFileConfigView::BMailFileConfigView(const char* label, const char*name,
void void
BMailFileConfigView::SetTo(const BMessage* archive, BMessage* meta) MailFileConfigView::SetTo(const BMessage* archive, BMessage* meta)
{ {
SetText((fUseMeta ? meta : archive)->FindString(fName));
fMeta = meta; fMeta = meta;
BString path = (fUseMeta ? meta : archive)->FindString(fName);
if (path != "")
SetText(path.String());
} }
status_t status_t
BMailFileConfigView::Archive(BMessage* into, bool /*deep*/) const MailFileConfigView::Archive(BMessage* into, bool /*deep*/) const
{ {
const char* path = Text();
BMessage* archive = fUseMeta ? fMeta : into; BMessage* archive = fUseMeta ? fMeta : into;
if (archive->ReplaceString(fName,path) != B_OK) if (archive->ReplaceString(fName, Text()) != B_OK)
archive->AddString(fName,path); archive->AddString(fName, Text());
return B_OK; return B_OK;
} }
} // namespace BPrivate
+22 -9
View File
@@ -1,7 +1,8 @@
/* /*
* Copyright 2011, Haiku, Inc. All rights reserved. * Copyright 2011-2012, Haiku, Inc. All rights reserved.
* Copyright 2011, Clemens Zeidler <[email protected]> * Copyright 2011, Clemens Zeidler <[email protected]>
* Copyright 2001-2003 Dr. Zoidberg Enterprises. All rights reserved. * Copyright 2001-2003 Dr. Zoidberg Enterprises. All rights reserved.
*
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
@@ -76,15 +77,23 @@ sanitize_white_space(BString& string)
// #pragma mark - // #pragma mark -
HaikuMailFormatFilter::HaikuMailFormatFilter(MailProtocol& protocol, HaikuMailFormatFilter::HaikuMailFormatFilter(BMailProtocol& protocol,
BMailAccountSettings* settings) const BMailAccountSettings& settings)
: :
MailFilter(protocol, NULL), BMailFilter(protocol, NULL),
fAccountID(settings->AccountID()), fAccountID(settings.AccountID()),
fAccountName(settings->Name()) fAccountName(settings.Name())
{ {
const BMessage* outboundSettings = &settings->OutboundSettings().Settings(); const BMessage& outboundSettings = settings.OutboundSettings();
outboundSettings->FindString("destination", &fOutboundDirectory); outboundSettings.FindString("destination", &fOutboundDirectory);
}
BString
HaikuMailFormatFilter::DescriptiveName() const
{
// This will not be called by the UI; no need to translate it
return "built-in";
} }
@@ -225,7 +234,11 @@ HaikuMailFormatFilter::MessageSent(const entry_ref& ref, BFile* file)
if (!fOutboundDirectory.IsEmpty()) { if (!fOutboundDirectory.IsEmpty()) {
create_directory(fOutboundDirectory, 755); create_directory(fOutboundDirectory, 755);
BDirectory dir(fOutboundDirectory); BDirectory dir(fOutboundDirectory);
fMailProtocol.Looper()->TriggerFileMove(ref, dir); // TODO:
// fMailProtocol.Looper()->TriggerFileMove(ref, dir);
BEntry entry(&ref);
entry.MoveTo(&dir);
// TODO: report error (via BMailProtocol::MailNotifier())
} }
} }
+9 -8
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2011, Haiku, Inc. All rights reserved. * Copyright 2011-2012, Haiku, Inc. All rights reserved.
* Copyright 2011, Clemens Zeidler <[email protected]> * Copyright 2011, Clemens Zeidler <[email protected]>
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
@@ -7,22 +7,23 @@
#define IMAP_LISTENER_H #define IMAP_LISTENER_H
#include "MailProtocol.h" #include <MailFilter.h>
#include <String.h> #include <String.h>
class HaikuMailFormatFilter : public MailFilter { class HaikuMailFormatFilter : public BMailFilter {
public: public:
HaikuMailFormatFilter(MailProtocol& protocol, HaikuMailFormatFilter(BMailProtocol& protocol,
BMailAccountSettings* settings); const BMailAccountSettings& settings);
virtual BString DescriptiveName() const;
void HeaderFetched(const entry_ref& ref, void HeaderFetched(const entry_ref& ref,
BFile* file); BFile* file);
void BodyFetched(const entry_ref& ref, BFile* file); void BodyFetched(const entry_ref& ref, BFile* file);
void MessageSent(const entry_ref& ref, void MessageSent(const entry_ref& ref, BFile* file);
BFile* file);
private: private:
status_t _SetFileName(const entry_ref& ref, status_t _SetFileName(const entry_ref& ref,
const BString& name); const BString& name);
+1
View File
@@ -25,6 +25,7 @@ local sources =
MailComponent.cpp MailComponent.cpp
MailContainer.cpp MailContainer.cpp
MailDaemon.cpp MailDaemon.cpp
MailFilter.cpp
MailMessage.cpp MailMessage.cpp
MailProtocol.cpp MailProtocol.cpp
MailSettings.cpp MailSettings.cpp
+49
View File
@@ -0,0 +1,49 @@
/*
* Copyright 2011-2012, Haiku, Inc. All rights reserved.
*/
#include <MailFilter.h>
BMailFilter::BMailFilter(BMailProtocol& protocol, BMailAddOnSettings* settings)
:
fMailProtocol(protocol),
fSettings(settings)
{
}
BMailFilter::~BMailFilter()
{
}
void
BMailFilter::HeaderFetched(const entry_ref& ref, BFile* file)
{
}
void
BMailFilter::BodyFetched(const entry_ref& ref, BFile* file)
{
}
void
BMailFilter::MailboxSynchronized(status_t status)
{
}
void
BMailFilter::MessageReadyToSend(const entry_ref& ref, BFile* file)
{
}
void
BMailFilter::MessageSent(const entry_ref& ref, BFile* file)
{
}
+3 -3
View File
@@ -1,10 +1,11 @@
/* /*
* Copyright 2007-2012, Haiku Inc. All Rights Reserved.
* Copyright 2001-2004 Dr. Zoidberg Enterprises. All rights reserved. * Copyright 2001-2004 Dr. Zoidberg Enterprises. All rights reserved.
* Copyright 2007, 2010, Haiku Inc. All Rights Reserved.
* *
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
//! The main general purpose mail message class //! The main general purpose mail message class
@@ -926,8 +927,7 @@ BEmailMessage::Send(bool sendNow)
} }
BString path; BString path;
if (account->OutboundSettings().Settings().FindString("path", &path) if (account->OutboundSettings().FindString("path", &path) != B_OK) {
!= B_OK) {
BPath defaultMailOutPath; BPath defaultMailOutPath;
if (find_directory(B_USER_DIRECTORY, &defaultMailOutPath) != B_OK if (find_directory(B_USER_DIRECTORY, &defaultMailOutPath) != B_OK
|| defaultMailOutPath.Append("mail/out") != B_OK) || defaultMailOutPath.Append("mail/out") != B_OK)
+208 -465
View File
@@ -1,34 +1,37 @@
/* /*
* Copyright 2011, Haiku, Inc. All rights reserved. * Copyright 2011-2012, Haiku, Inc. All rights reserved.
* Copyright 2001-2003 Dr. Zoidberg Enterprises. All rights reserved. * Copyright 2001-2003 Dr. Zoidberg Enterprises. All rights reserved.
*/ */
//#include <assert.h>
#include <stdio.h> #include <stdio.h>
#include <fs_attr.h>
#include <stdlib.h> #include <stdlib.h>
#include <assert.h>
#include <fs_attr.h>
#include <Alert.h> #include <Alert.h>
#include <Directory.h> #include <Directory.h>
#include <FindDirectory.h> #include <FindDirectory.h>
#include <Query.h>
#include <E-mail.h> #include <E-mail.h>
#include <Locker.h>
#include <Node.h> #include <Node.h>
#include <NodeInfo.h> #include <NodeInfo.h>
#include <NodeMonitor.h> #include <NodeMonitor.h>
#include <Path.h> #include <Path.h>
#include <Query.h>
#include <Roster.h> #include <Roster.h>
#include <String.h> #include <String.h>
#include <StringList.h> #include <StringList.h>
#include <VolumeRoster.h> #include <VolumeRoster.h>
#include <mail_util.h> #include <MailFilter.h>
#include <MailAddon.h>
#include <MailDaemon.h> #include <MailDaemon.h>
#include <MailProtocol.h> #include <MailProtocol.h>
#include <MailSettings.h> #include <MailSettings.h>
#include <mail_util.h>
#include "HaikuMailFormatFilter.h" #include "HaikuMailFormatFilter.h"
@@ -48,64 +51,16 @@ const uint32 kMsgInit = '&Ini';
const uint32 kMsgSendMessage = '&SeM'; const uint32 kMsgSendMessage = '&SeM';
MailFilter::MailFilter(MailProtocol& protocol, AddonSettings* settings) BMailProtocol::BMailProtocol(const BMailAccountSettings& settings)
: :
fMailProtocol(protocol), fAccountSettings(settings),
fAddonSettings(settings) fMailNotifier(NULL)
{ {
}
MailFilter::~MailFilter()
{
}
void
MailFilter::HeaderFetched(const entry_ref& ref, BFile* file)
{
}
void
MailFilter::BodyFetched(const entry_ref& ref, BFile* file)
{
}
void
MailFilter::MailboxSynced(status_t status)
{
}
void
MailFilter::MessageReadyToSend(const entry_ref& ref, BFile* file)
{
}
void
MailFilter::MessageSent(const entry_ref& ref, BFile* file)
{
}
// #pragma mark -
MailProtocol::MailProtocol(BMailAccountSettings* settings)
:
fMailNotifier(NULL),
fProtocolThread(NULL)
{
fAccountSettings = *settings;
AddFilter(new HaikuMailFormatFilter(*this, settings)); AddFilter(new HaikuMailFormatFilter(*this, settings));
} }
MailProtocol::~MailProtocol() BMailProtocol::~BMailProtocol()
{ {
delete fMailNotifier; delete fMailNotifier;
@@ -118,205 +73,118 @@ MailProtocol::~MailProtocol()
} }
BMailAccountSettings& const BMailAccountSettings&
MailProtocol::AccountSettings() BMailProtocol::AccountSettings() const
{ {
return fAccountSettings; return fAccountSettings;
} }
void void
MailProtocol::SetProtocolThread(MailProtocolThread* protocolThread) BMailProtocol::SetMailNotifier(BMailNotifier* mailNotifier)
{
if (fProtocolThread) {
fProtocolThread->Lock();
for (int i = 0; i < fHandlerList.CountItems(); i++)
fProtocolThread->RemoveHandler(fHandlerList.ItemAt(i));
fProtocolThread->Unlock();
}
fProtocolThread = protocolThread;
if (!fProtocolThread)
return;
fProtocolThread->Lock();
for (int i = 0; i < fHandlerList.CountItems(); i++)
fProtocolThread->AddHandler(fHandlerList.ItemAt(i));
fProtocolThread->Unlock();
AddedToLooper();
}
MailProtocolThread*
MailProtocol::Looper()
{
return fProtocolThread;
}
bool
MailProtocol::AddHandler(BHandler* handler)
{
if (!fHandlerList.AddItem(handler))
return false;
if (fProtocolThread) {
fProtocolThread->Lock();
fProtocolThread->AddHandler(handler);
fProtocolThread->Unlock();
}
return true;
}
bool
MailProtocol::RemoveHandler(BHandler* handler)
{
if (!fHandlerList.RemoveItem(handler))
return false;
if (fProtocolThread) {
fProtocolThread->Lock();
fProtocolThread->RemoveHandler(handler);
fProtocolThread->Unlock();
}
return true;
}
void
MailProtocol::SetMailNotifier(BMailNotifier* mailNotifier)
{ {
delete fMailNotifier; delete fMailNotifier;
fMailNotifier = mailNotifier; fMailNotifier = mailNotifier;
} }
void BMailNotifier*
MailProtocol::ShowError(const char* error) BMailProtocol::MailNotifier() const
{ {
if (fMailNotifier) return fMailNotifier;
fMailNotifier->ShowError(error);
}
void
MailProtocol::ShowMessage(const char* message)
{
if (fMailNotifier)
fMailNotifier->ShowMessage(message);
}
void
MailProtocol::SetTotalItems(int32 items)
{
if (fMailNotifier)
fMailNotifier->SetTotalItems(items);
}
void
MailProtocol::SetTotalItemsSize(int32 size)
{
if (fMailNotifier)
fMailNotifier->SetTotalItemsSize(size);
}
void
MailProtocol::ReportProgress(int bytes, int messages, const char* message)
{
if (fMailNotifier)
fMailNotifier->ReportProgress(bytes, messages, message);
}
void
MailProtocol::ResetProgress(const char* message)
{
if (fMailNotifier)
fMailNotifier->ResetProgress(message);
} }
bool bool
MailProtocol::AddFilter(MailFilter* filter) BMailProtocol::AddFilter(BMailFilter* filter)
{ {
BLocker locker(this);
return fFilterList.AddItem(filter); return fFilterList.AddItem(filter);
} }
int32 int32
MailProtocol::CountFilter() BMailProtocol::CountFilter() const
{ {
BLocker locker(this);
return fFilterList.CountItems(); return fFilterList.CountItems();
} }
MailFilter* BMailFilter*
MailProtocol::FilterAt(int32 index) BMailProtocol::FilterAt(int32 index) const
{ {
BLocker locker(this);
return fFilterList.ItemAt(index); return fFilterList.ItemAt(index);
} }
MailFilter* BMailFilter*
MailProtocol::RemoveFilter(int32 index) BMailProtocol::RemoveFilter(int32 index)
{ {
BLocker locker(this);
return fFilterList.RemoveItemAt(index); return fFilterList.RemoveItemAt(index);
} }
bool bool
MailProtocol::RemoveFilter(MailFilter* filter) BMailProtocol::RemoveFilter(BMailFilter* filter)
{ {
BLocker locker(this);
return fFilterList.RemoveItem(filter); return fFilterList.RemoveItem(filter);
} }
void void
MailProtocol::NotifyNewMessagesToFetch(int32 nMessages) BMailProtocol::MessageReceived(BMessage* message)
{ {
ResetProgress(); switch (message->what) {
SetTotalItems(nMessages); case kMsgMoveFile:
} {
entry_ref file;
message->FindRef("file", &file);
entry_ref dir;
message->FindRef("directory", &dir);
BDirectory directory(&dir);
MoveMessage(file, directory);
break;
}
case kMsgDeleteFile:
{
entry_ref file;
message->FindRef("file", &file);
DeleteMessage(file);
break;
}
void case kMsgFileRenamed:
MailProtocol::NotifyHeaderFetched(const entry_ref& ref, BFile* data) {
{ entry_ref from;
for (int i = 0; i < fFilterList.CountItems(); i++) message->FindRef("from", &from);
fFilterList.ItemAt(i)->HeaderFetched(ref, data); entry_ref to;
} message->FindRef("to", &to);
FileRenamed(from, to);
break;
}
case kMsgFileDeleted:
{
node_ref node;
message->FindInt32("device",&node.device);
message->FindInt64("node", &node.node);
FileDeleted(node);
break;
}
void default:
MailProtocol::NotifyBodyFetched(const entry_ref& ref, BFile* data) BLooper::MessageReceived(message);
{ }
for (int i = 0; i < fFilterList.CountItems(); i++)
fFilterList.ItemAt(i)->BodyFetched(ref, data);
}
void
MailProtocol::NotifyMessageReadyToSend(const entry_ref& ref, BFile* data)
{
for (int i = 0; i < fFilterList.CountItems(); i++)
fFilterList.ItemAt(i)->MessageReadyToSend(ref, data);
}
void
MailProtocol::NotifyMessageSent(const entry_ref& ref, BFile* data)
{
for (int i = 0; i < fFilterList.CountItems(); i++)
fFilterList.ItemAt(i)->MessageSent(ref, data);
} }
status_t status_t
MailProtocol::MoveMessage(const entry_ref& ref, BDirectory& dir) BMailProtocol::MoveMessage(const entry_ref& ref, BDirectory& dir)
{ {
BEntry entry(&ref); BEntry entry(&ref);
return entry.MoveTo(&dir); return entry.MoveTo(&dir);
@@ -324,7 +192,7 @@ MailProtocol::MoveMessage(const entry_ref& ref, BDirectory& dir)
status_t status_t
MailProtocol::DeleteMessage(const entry_ref& ref) BMailProtocol::DeleteMessage(const entry_ref& ref)
{ {
BEntry entry(&ref); BEntry entry(&ref);
return entry.Remove(); return entry.Remove();
@@ -332,36 +200,122 @@ MailProtocol::DeleteMessage(const entry_ref& ref)
void void
MailProtocol::FileRenamed(const entry_ref& from, const entry_ref& to) BMailProtocol::FileRenamed(const entry_ref& from, const entry_ref& to)
{ {
} }
void void
MailProtocol::FileDeleted(const node_ref& node) BMailProtocol::FileDeleted(const node_ref& node)
{ {
} }
void void
MailProtocol::LoadFilters(MailAddonSettings& settings) BMailProtocol::ShowError(const char* error)
{
if (MailNotifier() != NULL)
MailNotifier()->ShowError(error);
}
void
BMailProtocol::ShowMessage(const char* message)
{
if (MailNotifier() != NULL)
MailNotifier()->ShowMessage(message);
}
void
BMailProtocol::SetTotalItems(uint32 items)
{
if (MailNotifier() != NULL)
MailNotifier()->SetTotalItems(items);
}
void
BMailProtocol::SetTotalItemsSize(uint64 size)
{
if (MailNotifier() != NULL)
MailNotifier()->SetTotalItemsSize(size);
}
void
BMailProtocol::ReportProgress(uint32 messages, uint64 bytes,
const char* message)
{
if (MailNotifier() != NULL)
MailNotifier()->ReportProgress(messages, bytes, message);
}
void
BMailProtocol::ResetProgress(const char* message)
{
if (MailNotifier() != NULL)
MailNotifier()->ResetProgress(message);
}
void
BMailProtocol::NotifyNewMessagesToFetch(int32 count)
{
ResetProgress();
SetTotalItems(count);
}
void
BMailProtocol::NotifyHeaderFetched(const entry_ref& ref, BFile* data)
{
for (int i = 0; i < fFilterList.CountItems(); i++)
fFilterList.ItemAt(i)->HeaderFetched(ref, data);
}
void
BMailProtocol::NotifyBodyFetched(const entry_ref& ref, BFile* data)
{
for (int i = 0; i < fFilterList.CountItems(); i++)
fFilterList.ItemAt(i)->BodyFetched(ref, data);
}
void
BMailProtocol::NotifyMessageReadyToSend(const entry_ref& ref, BFile* data)
{
for (int i = 0; i < fFilterList.CountItems(); i++)
fFilterList.ItemAt(i)->MessageReadyToSend(ref, data);
}
void
BMailProtocol::NotifyMessageSent(const entry_ref& ref, BFile* data)
{
for (int i = 0; i < fFilterList.CountItems(); i++)
fFilterList.ItemAt(i)->MessageSent(ref, data);
}
void
BMailProtocol::LoadFilters(const BMailProtocolSettings& settings)
{ {
for (int i = 0; i < settings.CountFilterSettings(); i++) { for (int i = 0; i < settings.CountFilterSettings(); i++) {
AddonSettings* filterSettings = settings.FilterSettingsAt(i); BMailAddOnSettings* filterSettings = settings.FilterSettingsAt(i);
MailFilter* filter = _LoadFilter(filterSettings); BMailFilter* filter = _LoadFilter(filterSettings);
if (!filter) if (filter != NULL)
continue; AddFilter(filter);
AddFilter(filter);
} }
} }
MailFilter* BMailFilter*
MailProtocol::_LoadFilter(AddonSettings* filterSettings) BMailProtocol::_LoadFilter(BMailAddOnSettings* filterSettings)
{ {
const entry_ref& ref = filterSettings->AddonRef(); const entry_ref& ref = filterSettings->AddOnRef();
map<entry_ref, image_id>::iterator it = fFilterImages.find(ref); map<entry_ref, image_id>::iterator it = fFilterImages.find(ref);
image_id image; image_id image;
if (it != fFilterImages.end()) if (it != fFilterImages.end())
@@ -374,209 +328,42 @@ MailProtocol::_LoadFilter(AddonSettings* filterSettings)
if (image < 0) if (image < 0)
return NULL; return NULL;
MailFilter* (*instantiate_mailfilter)(MailProtocol& protocol, BMailFilter* (*instantiate_filter)(BMailProtocol& protocol,
AddonSettings* settings); BMailAddOnSettings* settings);
if (get_image_symbol(image, "instantiate_mailfilter", if (get_image_symbol(image, "instantiate_filter", B_SYMBOL_TYPE_TEXT,
B_SYMBOL_TYPE_TEXT, (void **)&instantiate_mailfilter) (void**)&instantiate_filter) != B_OK) {
!= B_OK) {
unload_add_on(image); unload_add_on(image);
return NULL; return NULL;
} }
fFilterImages[ref] = image; fFilterImages[ref] = image;
return (*instantiate_mailfilter)(*this, filterSettings); return (*instantiate_filter)(*this, filterSettings);
} }
// #pragma mark - // #pragma mark -
InboundProtocol::InboundProtocol(BMailAccountSettings* settings) BInboundMailProtocol::BInboundMailProtocol(const BMailAccountSettings& settings)
: :
MailProtocol(settings) BMailProtocol(settings)
{ {
LoadFilters(fAccountSettings.InboundSettings()); LoadFilters(fAccountSettings.InboundSettings());
} }
InboundProtocol::~InboundProtocol() BInboundMailProtocol::~BInboundMailProtocol()
{ {
}
status_t
InboundProtocol::AppendMessage(const entry_ref& ref)
{
return false;
}
status_t
InboundProtocol::MarkMessageAsRead(const entry_ref& ref, read_flags flag)
{
BNode node(&ref);
return write_read_attr(node, flag);
}
// #pragma mark -
OutboundProtocol::OutboundProtocol(BMailAccountSettings* settings)
:
MailProtocol(settings)
{
LoadFilters(fAccountSettings.OutboundSettings());
}
OutboundProtocol::~OutboundProtocol()
{
}
// #pragma mark -
MailProtocolThread::MailProtocolThread(MailProtocol* protocol)
:
fMailProtocol(protocol)
{
PostMessage(kMsgInit);
} }
void void
MailProtocolThread::SetStopNow() BInboundMailProtocol::MessageReceived(BMessage* message)
{
fMailProtocol->SetStopNow();
}
void
MailProtocolThread::MessageReceived(BMessage* message)
{
switch (message->what) {
case kMsgInit:
fMailProtocol->SetProtocolThread(this);
break;
case kMsgMoveFile:
{
entry_ref file;
message->FindRef("file", &file);
entry_ref dir;
message->FindRef("directory", &dir);
BDirectory directory(&dir);
fMailProtocol->MoveMessage(file, directory);
break;
}
case kMsgDeleteFile:
{
entry_ref file;
message->FindRef("file", &file);
fMailProtocol->DeleteMessage(file);
break;
}
case kMsgFileRenamed:
{
entry_ref from;
message->FindRef("from", &from);
entry_ref to;
message->FindRef("to", &to);
fMailProtocol->FileRenamed(from, to);
break;
}
case kMsgFileDeleted:
{
node_ref node;
message->FindInt32("device",&node.device);
message->FindInt64("node", &node.node);
fMailProtocol->FileDeleted(node);
break;
}
default:
BLooper::MessageReceived(message);
}
}
void
MailProtocolThread::TriggerFileMove(const entry_ref& ref, BDirectory& dir)
{
BMessage message(kMsgMoveFile);
message.AddRef("file", &ref);
BEntry entry;
dir.GetEntry(&entry);
entry_ref dirRef;
entry.GetRef(&dirRef);
message.AddRef("directory", &dirRef);
PostMessage(&message);
}
void
MailProtocolThread::TriggerFileDeletion(const entry_ref& ref)
{
BMessage message(kMsgDeleteFile);
message.AddRef("file", &ref);
PostMessage(&message);
}
void
MailProtocolThread::TriggerFileRenamed(const entry_ref& from,
const entry_ref& to)
{
BMessage message(kMsgFileRenamed);
message.AddRef("from", &from);
message.AddRef("to", &to);
PostMessage(&message);
}
void
MailProtocolThread::TriggerFileDeleted(const node_ref& node)
{
BMessage message(kMsgFileDeleted);
message.AddInt32("device", node.device);
message.AddInt64("node", node.node);
PostMessage(&message);
}
// #pragma mark -
InboundProtocolThread::InboundProtocolThread(InboundProtocol* protocol)
:
MailProtocolThread(protocol),
fProtocol(protocol)
{
}
InboundProtocolThread::~InboundProtocolThread()
{
fProtocol->SetProtocolThread(NULL);
}
void
InboundProtocolThread::MessageReceived(BMessage* message)
{ {
switch (message->what) { switch (message->what) {
case kMsgSyncMessages: case kMsgSyncMessages:
{ {
status_t status = fProtocol->SyncMessages(); NotiyMailboxSynchronized(SyncMessages());
_NotiyMailboxSynced(status);
break; break;
} }
@@ -584,7 +371,7 @@ InboundProtocolThread::MessageReceived(BMessage* message)
{ {
entry_ref ref; entry_ref ref;
message->FindRef("ref", &ref); message->FindRef("ref", &ref);
status_t status = fProtocol->FetchBody(ref); status_t status = FetchBody(ref);
BMessenger target; BMessenger target;
if (message->FindMessenger("target", &target) != B_OK) if (message->FindMessenger("target", &target) != B_OK)
@@ -602,7 +389,7 @@ InboundProtocolThread::MessageReceived(BMessage* message)
entry_ref ref; entry_ref ref;
message->FindRef("ref", &ref); message->FindRef("ref", &ref);
read_flags read = (read_flags)message->FindInt32("read"); read_flags read = (read_flags)message->FindInt32("read");
fProtocol->MarkMessageAsRead(ref, read); MarkMessageAsRead(ref, read);
break; break;
} }
@@ -610,7 +397,7 @@ InboundProtocolThread::MessageReceived(BMessage* message)
{ {
entry_ref ref; entry_ref ref;
message->FindRef("ref", &ref); message->FindRef("ref", &ref);
fProtocol->DeleteMessage(ref); DeleteMessage(ref);
break; break;
} }
@@ -618,91 +405,59 @@ InboundProtocolThread::MessageReceived(BMessage* message)
{ {
entry_ref ref; entry_ref ref;
message->FindRef("ref", &ref); message->FindRef("ref", &ref);
fProtocol->AppendMessage(ref); AppendMessage(ref);
break; break;
} }
default: default:
MailProtocolThread::MessageReceived(message); BMailProtocol::MessageReceived(message);
break; break;
} }
} }
void status_t
InboundProtocolThread::SyncMessages() BInboundMailProtocol::MarkMessageAsRead(const entry_ref& ref, read_flags flag)
{ {
PostMessage(kMsgSyncMessages); BNode node(&ref);
return write_read_attr(node, flag);
}
status_t
BInboundMailProtocol::AppendMessage(const entry_ref& ref)
{
return B_OK;
} }
void void
InboundProtocolThread::FetchBody(const entry_ref& ref, BMessenger* listener) BInboundMailProtocol::NotiyMailboxSynchronized(status_t status)
{ {
BMessage message(kMsgFetchBody); for (int32 i = 0; i < CountFilter(); i++)
message.AddRef("ref", &ref); FilterAt(i)->MailboxSynchronized(status);
if (listener)
message.AddMessenger("target", *listener);
PostMessage(&message);
}
void
InboundProtocolThread::MarkMessageAsRead(const entry_ref& ref, read_flags flag)
{
BMessage message(kMsgMarkMessageAsRead);
message.AddRef("ref", &ref);
message.AddInt32("read", flag);
PostMessage(&message);
}
void
InboundProtocolThread::DeleteMessage(const entry_ref& ref)
{
BMessage message(kMsgDeleteMessage);
message.AddRef("ref", &ref);
PostMessage(&message);
}
void
InboundProtocolThread::AppendMessage(const entry_ref& ref)
{
BMessage message(kMsgAppendMessage);
message.AddRef("ref", &ref);
PostMessage(&message);
}
void
InboundProtocolThread::_NotiyMailboxSynced(status_t status)
{
for (int i = 0; i < fProtocol->CountFilter(); i++)
fProtocol->FilterAt(i)->MailboxSynced(status);
} }
// #pragma mark - // #pragma mark -
OutboundProtocolThread::OutboundProtocolThread(OutboundProtocol* protocol) BOutboundMailProtocol::BOutboundMailProtocol(
const BMailAccountSettings& settings)
: :
MailProtocolThread(protocol), BMailProtocol(settings)
fProtocol(protocol)
{ {
LoadFilters(fAccountSettings.OutboundSettings());
} }
OutboundProtocolThread::~OutboundProtocolThread() BOutboundMailProtocol::~BOutboundMailProtocol()
{ {
fProtocol->SetProtocolThread(NULL);
} }
void void
OutboundProtocolThread::MessageReceived(BMessage* message) BOutboundMailProtocol::MessageReceived(BMessage* message)
{ {
switch (message->what) { switch (message->what) {
case kMsgSendMessage: case kMsgSendMessage:
@@ -715,23 +470,11 @@ OutboundProtocolThread::MessageReceived(BMessage* message)
mails.push_back(ref); mails.push_back(ref);
} }
size_t size = message->FindInt32("size"); size_t size = message->FindInt32("size");
fProtocol->SendMessages(mails, size); SendMessages(mails, size);
break; break;
} }
default: default:
MailProtocolThread::MessageReceived(message); BMailProtocol::MessageReceived(message);
} }
} }
void
OutboundProtocolThread::SendMessages(const std::vector<entry_ref>& mails,
size_t totalBytes)
{
BMessage message(kMsgSendMessage);
for (unsigned int i = 0; i < mails.size(); i++)
message.AddRef("ref", &mails[i]);
message.AddInt32("size", totalBytes);
PostMessage(&message);
}
+143 -114
View File
@@ -1,6 +1,6 @@
/* /*
* Copyright 2004-2012, Haiku Inc. All rights reserved.
* Copyright 2001-2003 Dr. Zoidberg Enterprises. All rights reserved. * Copyright 2001-2003 Dr. Zoidberg Enterprises. All rights reserved.
* Copyright 2004-2011, Haiku Inc. All rights reserved.
* *
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
@@ -419,177 +419,196 @@ BMailAccounts::AccountByName(const char* name)
// #pragma mark - // #pragma mark -
AddonSettings::AddonSettings() BMailAddOnSettings::BMailAddOnSettings()
:
fModified(false)
{ {
} }
bool BMailAddOnSettings::~BMailAddOnSettings()
AddonSettings::Load(const BMessage& message)
{ {
const char* addonPath = NULL;
if (message.FindString("add-on path", &addonPath) != B_OK
|| get_ref_for_path(addonPath, &fAddonRef) != B_OK
|| message.FindMessage("settings", &fSettings) != B_OK)
return false;
fModified = false;
return true;
} }
bool status_t
AddonSettings::Save(BMessage& message) BMailAddOnSettings::Load(const BMessage& message)
{ {
BPath path(&fAddonRef); const char* path = NULL;
message.AddString("add-on path", path.Path()); if (message.FindString("add-on path", &path) != B_OK)
message.AddMessage("settings", &fSettings); return B_BAD_VALUE;
fModified = false;
return true; status_t status = get_ref_for_path(path, &fRef);
if (status != B_OK)
return status;
BMessage settings;
message.FindMessage("settings", &settings);
MakeEmpty();
Append(settings);
fOriginalSettings = *this;
fOriginalRef = fRef;
return B_OK;
}
status_t
BMailAddOnSettings::Save(BMessage& message)
{
BPath path(&fRef);
status_t status = message.AddString("add-on path", path.Path());
if (status == B_OK)
status = message.AddMessage("settings", this);
if (status != B_OK)
return status;
fOriginalSettings = *this;
fOriginalRef = fRef;
return B_OK;
} }
void void
AddonSettings::SetAddonRef(const entry_ref& ref) BMailAddOnSettings::SetAddOnRef(const entry_ref& ref)
{ {
fAddonRef = ref; fRef = ref;
} }
const entry_ref& const entry_ref&
AddonSettings::AddonRef() const BMailAddOnSettings::AddOnRef() const
{ {
return fAddonRef; return fRef;
}
const BMessage&
AddonSettings::Settings() const
{
return fSettings;
}
BMessage&
AddonSettings::EditSettings()
{
fModified = true;
return fSettings;
} }
bool bool
AddonSettings::HasBeenModified() BMailAddOnSettings::HasBeenModified() const
{ {
return fModified; return fRef != fOriginalRef
|| !fOriginalSettings.HasSameData(*this, true, true);
} }
// #pragma mark - // #pragma mark -
bool BMailProtocolSettings::BMailProtocolSettings()
MailAddonSettings::Load(const BMessage& message) :
fFiltersSettings(5, true)
{ {
if (!AddonSettings::Load(message)) }
return false;
BMailProtocolSettings::~BMailProtocolSettings()
{
}
status_t
BMailProtocolSettings::Load(const BMessage& message)
{
status_t status = BMailAddOnSettings::Load(message);
if (status != B_OK)
return status;
type_code typeFound; type_code typeFound;
int32 countFound; int32 countFound;
message.GetInfo("filters", &typeFound, &countFound); message.GetInfo("filters", &typeFound, &countFound);
if (typeFound != B_MESSAGE_TYPE) if (typeFound != B_MESSAGE_TYPE)
return false; return B_BAD_VALUE;
for (int i = 0; i < countFound; i++) { for (int i = 0; i < countFound; i++) {
int32 index = AddFilterSettings(); int32 index = AddFilterSettings();
AddonSettings& filterSettings = fFiltersSettings[index]; if (index < 0)
return B_NO_MEMORY;
BMailAddOnSettings* filterSettings = fFiltersSettings.ItemAt(index);
BMessage filterMessage; BMessage filterMessage;
message.FindMessage("filters", i, &filterMessage); message.FindMessage("filters", i, &filterMessage);
if (!filterSettings.Load(filterMessage)) if (filterSettings->Load(filterMessage) != B_OK)
RemoveFilterSettings(index); RemoveFilterSettings(index);
} }
return true; return B_OK;
} }
bool status_t
MailAddonSettings::Save(BMessage& message) BMailProtocolSettings::Save(BMessage& message)
{ {
if (!AddonSettings::Save(message)) status_t status = BMailAddOnSettings::Save(message);
return false; if (status != B_OK)
return status;
for (int i = 0; i < CountFilterSettings(); i++) { for (int i = 0; i < CountFilterSettings(); i++) {
BMessage filter; BMessage filter;
AddonSettings& filterSettings = fFiltersSettings[i]; BMailAddOnSettings* filterSettings = fFiltersSettings.ItemAt(i);
filterSettings.Save(filter); filterSettings->Save(filter);
message.AddMessage("filters", &filter); message.AddMessage("filters", &filter);
} }
return true; return B_OK;
} }
int32 int32
MailAddonSettings::CountFilterSettings() BMailProtocolSettings::CountFilterSettings() const
{ {
return fFiltersSettings.size(); return fFiltersSettings.CountItems();
} }
int32 int32
MailAddonSettings::AddFilterSettings(const entry_ref* ref) BMailProtocolSettings::AddFilterSettings(const entry_ref* ref)
{ {
AddonSettings filterSettings; BMailAddOnSettings* filterSettings = new BMailAddOnSettings();
if (ref != NULL) if (ref != NULL)
filterSettings.SetAddonRef(*ref); filterSettings->SetAddOnRef(*ref);
fFiltersSettings.push_back(filterSettings);
return fFiltersSettings.size() - 1; if (fFiltersSettings.AddItem(filterSettings))
return fFiltersSettings.CountItems() - 1;
delete filterSettings;
return -1;
}
void
BMailProtocolSettings::RemoveFilterSettings(int32 index)
{
fFiltersSettings.RemoveItemAt(index);
} }
bool bool
MailAddonSettings::RemoveFilterSettings(int32 index) BMailProtocolSettings::MoveFilterSettings(int32 from, int32 to)
{ {
fFiltersSettings.erase(fFiltersSettings.begin() + index); if (from < 0 || from >= (int32)CountFilterSettings() || to < 0
return true; || to >= (int32)CountFilterSettings())
}
bool
MailAddonSettings::MoveFilterSettings(int32 from, int32 to)
{
if (from < 0 || from >= (int32)fFiltersSettings.size() || to < 0
|| to >= (int32)fFiltersSettings.size())
return false; return false;
AddonSettings fromSettings = fFiltersSettings[from]; if (from == to)
fFiltersSettings.erase(fFiltersSettings.begin() + from); return true;
if (to == (int32)fFiltersSettings.size())
fFiltersSettings.push_back(fromSettings); BMailAddOnSettings* settings = fFiltersSettings.RemoveItemAt(from);
else { fFiltersSettings.AddItem(settings, to);
std::vector<AddonSettings>::iterator it = fFiltersSettings.begin() + to;
fFiltersSettings.insert(it, fromSettings);
}
return true; return true;
} }
AddonSettings* BMailAddOnSettings*
MailAddonSettings::FilterSettingsAt(int32 index) BMailProtocolSettings::FilterSettingsAt(int32 index) const
{ {
if (index < 0 || index >= (int32)fFiltersSettings.size()) return fFiltersSettings.ItemAt(index);
return NULL;
return &fFiltersSettings[index];
} }
bool bool
MailAddonSettings::HasBeenModified() BMailProtocolSettings::HasBeenModified() const
{ {
if (AddonSettings::HasBeenModified()) if (BMailAddOnSettings::HasBeenModified())
return true; return true;
for (unsigned int i = 0; i < fFiltersSettings.size(); i++) { for (int32 i = 0; i < CountFilterSettings(); i++) {
if (fFiltersSettings[i].HasBeenModified()) if (FilterSettingsAt(i)->HasBeenModified())
return true; return true;
} }
return false; return false;
@@ -634,7 +653,7 @@ BMailAccountSettings::SetAccountID(int32 id)
int32 int32
BMailAccountSettings::AccountID() BMailAccountSettings::AccountID() const
{ {
return fAccountID; return fAccountID;
} }
@@ -686,7 +705,7 @@ BMailAccountSettings::ReturnAddress() const
bool bool
BMailAccountSettings::SetInboundAddon(const char* name) BMailAccountSettings::SetInboundAddOn(const char* name)
{ {
BPath path; BPath path;
status_t status = find_directory(B_BEOS_ADDONS_DIRECTORY, &path); status_t status = find_directory(B_BEOS_ADDONS_DIRECTORY, &path);
@@ -697,15 +716,14 @@ BMailAccountSettings::SetInboundAddon(const char* name)
path.Append(name); path.Append(name);
entry_ref ref; entry_ref ref;
get_ref_for_path(path.Path(), &ref); get_ref_for_path(path.Path(), &ref);
fInboundSettings.SetAddonRef(ref); fInboundSettings.SetAddOnRef(ref);
fModified = true;
return true; return true;
} }
bool bool
BMailAccountSettings::SetOutboundAddon(const char* name) BMailAccountSettings::SetOutboundAddOn(const char* name)
{ {
BPath path; BPath path;
status_t status = find_directory(B_BEOS_ADDONS_DIRECTORY, &path); status_t status = find_directory(B_BEOS_ADDONS_DIRECTORY, &path);
@@ -716,52 +734,65 @@ BMailAccountSettings::SetOutboundAddon(const char* name)
path.Append(name); path.Append(name);
entry_ref ref; entry_ref ref;
get_ref_for_path(path.Path(), &ref); get_ref_for_path(path.Path(), &ref);
fOutboundSettings.SetAddonRef(ref); fOutboundSettings.SetAddOnRef(ref);
fModified = true;
return true; return true;
} }
const entry_ref& const entry_ref&
BMailAccountSettings::InboundPath() const BMailAccountSettings::InboundAddOnRef() const
{ {
return fInboundSettings.AddonRef(); return fInboundSettings.AddOnRef();
} }
const entry_ref& const entry_ref&
BMailAccountSettings::OutboundPath() const BMailAccountSettings::OutboundAddOnRef() const
{ {
return fOutboundSettings.AddonRef(); return fOutboundSettings.AddOnRef();
} }
MailAddonSettings& BMailProtocolSettings&
BMailAccountSettings::InboundSettings() BMailAccountSettings::InboundSettings()
{ {
return fInboundSettings; return fInboundSettings;
} }
MailAddonSettings& const BMailProtocolSettings&
BMailAccountSettings::InboundSettings() const
{
return fInboundSettings;
}
BMailProtocolSettings&
BMailAccountSettings::OutboundSettings() BMailAccountSettings::OutboundSettings()
{ {
return fOutboundSettings; return fOutboundSettings;
} }
const BMailProtocolSettings&
BMailAccountSettings::OutboundSettings() const
{
return fOutboundSettings;
}
bool bool
BMailAccountSettings::HasInbound() BMailAccountSettings::HasInbound()
{ {
return BEntry(&fInboundSettings.AddonRef()).Exists(); return BEntry(&fInboundSettings.AddOnRef()).Exists();
} }
bool bool
BMailAccountSettings::HasOutbound() BMailAccountSettings::HasOutbound()
{ {
return BEntry(&fOutboundSettings.AddonRef()).Exists(); return BEntry(&fOutboundSettings.AddOnRef()).Exists();
} }
@@ -870,18 +901,16 @@ BMailAccountSettings::Delete()
bool bool
BMailAccountSettings::HasBeenModified() BMailAccountSettings::HasBeenModified() const
{ {
if (fInboundSettings.HasBeenModified()) return fModified
return true; || fInboundSettings.HasBeenModified()
if (fOutboundSettings.HasBeenModified()) || fOutboundSettings.HasBeenModified();
return true;
return fModified;
} }
const BEntry& const BEntry&
BMailAccountSettings::AccountFile() BMailAccountSettings::AccountFile() const
{ {
return fAccountFile; return fAccountFile;
} }
+222 -288
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 20011, Haiku Inc. All Rights Reserved. * Copyright 2011-2012, Haiku Inc. All Rights Reserved.
* Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved. * Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
@@ -15,6 +15,7 @@
#include <Catalog.h> #include <Catalog.h>
#include <CheckBox.h> #include <CheckBox.h>
#include <GridLayout.h>
#include <MenuField.h> #include <MenuField.h>
#include <MenuItem.h> #include <MenuItem.h>
#include <Message.h> #include <Message.h>
@@ -29,7 +30,14 @@
#define B_TRANSLATION_CONTEXT "ProtocolConfigView" #define B_TRANSLATION_CONTEXT "ProtocolConfigView"
const char* kPartialDownloadLimit = "partial_download_limit"; static const char* kPartialDownloadLimit = "partial_download_limit";
static const uint32 kMsgLeaveOnServer = 'lmos';
static const uint32 kMsgNoPassword = 'none';
static const uint32 kMsgNeedPassword = 'some';
namespace BPrivate {
BodyDownloadConfig::BodyDownloadConfig() BodyDownloadConfig::BodyDownloadConfig()
@@ -62,13 +70,11 @@ BodyDownloadConfig::BodyDownloadConfig()
void void
BodyDownloadConfig::SetTo(MailAddonSettings& addonSettings) BodyDownloadConfig::SetTo(BMailProtocolSettings& settings)
{ {
const BMessage* settings = &addonSettings.Settings();
int32 limit = 0; int32 limit = 0;
if (settings->HasInt32(kPartialDownloadLimit)) if (settings.HasInt32(kPartialDownloadLimit))
limit = settings->FindInt32(kPartialDownloadLimit); limit = settings.FindInt32(kPartialDownloadLimit);
if (limit < 0) { if (limit < 0) {
fPartialBox->SetValue(B_CONTROL_OFF); fPartialBox->SetValue(B_CONTROL_OFF);
fSizeBox->SetText("0"); fSizeBox->SetText("0");
@@ -122,375 +128,303 @@ BodyDownloadConfig::Archive(BMessage* into, bool) const
} }
namespace { // #pragma mark -
//--------------------Support functions and #defines---------------
#define enable_control(name) if (FindView(name) != NULL) ((BControl *)(FindView(name)))->SetEnabled(true)
#define disable_control(name) if (FindView(name) != NULL) ((BControl *)(FindView(name)))->SetEnabled(false)
BTextControl *AddTextField (BRect &rect, const char *name, const char *label);
BMenuField *AddMenuField (BRect &rect, const char *name, const char *label);
float FindWidestLabel(BView *view);
static float sItemHeight;
inline const char *
TextControl(BView *parent,const char *name)
{
BTextControl *control = (BTextControl *)(parent->FindView(name));
if (control != NULL)
return control->Text();
return "";
}
BTextControl * MailProtocolConfigView::MailProtocolConfigView(uint32 optionsMask)
AddTextField(BRect &rect, const char *name, const char *label)
{
BTextControl *text_control = new BTextControl(rect,name,label,"",NULL,B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP);
// text_control->SetDivider(be_plain_font->StringWidth(label));
rect.OffsetBy(0,sItemHeight);
return text_control;
}
BMenuField *AddMenuField (BRect &rect, const char *name, const char *label) {
BPopUpMenu *menu = new BPopUpMenu("Select");
BMenuField *control = new BMenuField(rect,name,label,menu,B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP);
control->SetDivider(be_plain_font->StringWidth(label) + 6);
rect.OffsetBy(0,sItemHeight);
return control;
}
inline BCheckBox *
AddCheckBox(BRect &rect, const char *name, const char *label, BMessage *msg = NULL)
{
BCheckBox *control = new BCheckBox(rect,name,label,msg);
rect.OffsetBy(0,sItemHeight);
return control;
}
inline void
SetTextControl(BView *parent, const char *name, const char *text)
{
BTextControl *control = (BTextControl *)(parent->FindView(name));
if (control != NULL)
control->SetText(text);
}
float
FindWidestLabel(BView *view)
{
float width = 0;
for (int32 i = view->CountChildren();i-- > 0;) {
if (BControl *control = dynamic_cast<BControl *>(view->ChildAt(i))) {
float labelWidth = control->StringWidth(control->Label());
if (labelWidth > width)
width = labelWidth;
}
}
return width;
}
} // unnamed namspace
//----------------Real code----------------------
BMailProtocolConfigView::BMailProtocolConfigView(uint32 options_mask)
: :
BView (BRect(0,0,100,20), "protocol_config_view", B_FOLLOW_LEFT BView("protocol_config_view", B_WILL_DRAW),
| B_FOLLOW_TOP, B_WILL_DRAW), fHostControl(NULL),
fUserControl(NULL),
fPasswordControl(NULL),
fLeaveOnServerCheckBox(NULL),
fRemoveFromServerCheckBox(NULL),
fBodyDownloadConfig(NULL) fBodyDownloadConfig(NULL)
{ {
BRect rect(5,5,245,25);
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
// determine font height BGridLayout* layout = new BGridLayout();
font_height fontHeight; SetLayout(layout);
GetFontHeight(&fontHeight);
sItemHeight = (int32)(fontHeight.ascent + fontHeight.descent + fontHeight.leading) + 13;
rect.bottom = rect.top - 2 + sItemHeight;
if (options_mask & B_MAIL_PROTOCOL_HAS_HOSTNAME) if ((optionsMask & B_MAIL_PROTOCOL_HAS_HOSTNAME) != 0) {
AddChild(AddTextField(rect, "host", B_TRANSLATE("Mail server:"))); fHostControl = _AddTextControl(layout, "host",
B_TRANSLATE("Mail server:"));
}
if ((optionsMask & B_MAIL_PROTOCOL_HAS_USERNAME) != 0) {
fUserControl = _AddTextControl(layout, "user",
B_TRANSLATE("Username:"));
}
if (options_mask & B_MAIL_PROTOCOL_HAS_USERNAME) if ((optionsMask & B_MAIL_PROTOCOL_HAS_PASSWORD) != 0) {
AddChild(AddTextField(rect, "user", B_TRANSLATE("Username:"))); fPasswordControl = _AddTextControl(layout, "pass",
if (options_mask & B_MAIL_PROTOCOL_HAS_PASSWORD) {
BTextControl *control = AddTextField(rect, "pass",
B_TRANSLATE("Password:")); B_TRANSLATE("Password:"));
control->TextView()->HideTyping(true); fPasswordControl->TextView()->HideTyping(true);
AddChild(control);
} }
if (options_mask & B_MAIL_PROTOCOL_HAS_FLAVORS) if ((optionsMask & B_MAIL_PROTOCOL_HAS_FLAVORS) != 0) {
AddChild(AddMenuField(rect, "flavor", B_TRANSLATE("Connection type:"))); fFlavorField = _AddMenuField(layout, "flavor",
B_TRANSLATE("Connection type:"));
if (options_mask & B_MAIL_PROTOCOL_HAS_AUTH_METHODS)
AddChild(AddMenuField(rect, "auth_method", B_TRANSLATE("Login type:")));
// set divider
float width = FindWidestLabel(this);
for (int32 i = CountChildren();i-- > 0;) {
if (BTextControl *text = dynamic_cast<BTextControl *>(ChildAt(i)))
text->SetDivider(width + 6);
} }
if (options_mask & B_MAIL_PROTOCOL_CAN_LEAVE_MAIL_ON_SERVER) { if ((optionsMask & B_MAIL_PROTOCOL_HAS_AUTH_METHODS) != 0) {
AddChild(AddCheckBox(rect, "leave_mail_on_server", fAuthenticationField = _AddMenuField(layout, "auth_method",
B_TRANSLATE("Leave mail on server"), new BMessage('lmos'))); B_TRANSLATE("Login type:"));
BCheckBox* box = AddCheckBox(rect, "delete_remote_when_local",
B_TRANSLATE("Remove mail from server when deleted"));
box->SetEnabled(false);
AddChild(box);
} }
if (options_mask & B_MAIL_PROTOCOL_PARTIAL_DOWNLOAD) { if ((optionsMask & B_MAIL_PROTOCOL_CAN_LEAVE_MAIL_ON_SERVER) != 0) {
fLeaveOnServerCheckBox = new BCheckBox("leave_mail_on_server",
B_TRANSLATE("Leave mail on server"),
new BMessage(kMsgLeaveOnServer));
layout->AddView(fLeaveOnServerCheckBox, 0, layout->CountRows(), 2);
fRemoveFromServerCheckBox = new BCheckBox("delete_remote_when_local",
B_TRANSLATE("Remove mail from server when deleted"), NULL);
fRemoveFromServerCheckBox->SetEnabled(false);
layout->AddView(fRemoveFromServerCheckBox, 0, layout->CountRows(), 2);
}
if ((optionsMask & B_MAIL_PROTOCOL_PARTIAL_DOWNLOAD) != 0) {
fBodyDownloadConfig = new BodyDownloadConfig(); fBodyDownloadConfig = new BodyDownloadConfig();
fBodyDownloadConfig->MoveBy(0, rect.bottom + 5); layout->AddView(fBodyDownloadConfig, 0, layout->CountRows(), 2);
AddChild(fBodyDownloadConfig);
}
// resize views
float height;
GetPreferredSize(&width,&height);
ResizeTo(width,height);
for (int32 i = CountChildren();i-- > 0;) {
// this doesn't work with BTextControl, does anyone know why? -- axeld.
if (BView *view = ChildAt(i))
view->ResizeTo(width - 10,view->Bounds().Height());
} }
} }
BMailProtocolConfigView::~BMailProtocolConfigView() MailProtocolConfigView::~MailProtocolConfigView()
{ {
} }
void void
BMailProtocolConfigView::SetTo(MailAddonSettings& settings) MailProtocolConfigView::SetTo(BMailProtocolSettings& settings)
{ {
const BMessage* archive = &settings.Settings(); BString host = settings.FindString("server");
if (settings.HasInt32("port"))
host << ':' << settings.FindInt32("port");
BString host = archive->FindString("server"); if (fHostControl != NULL)
if (archive->HasInt32("port")) fHostControl->SetText(host.String());
host << ':' << archive->FindInt32("port"); if (fUserControl != NULL)
fUserControl->SetText(settings.FindString("username"));
SetTextControl(this,"host", host.String()); if (fPasswordControl != NULL) {
SetTextControl(this,"user", archive->FindString("username")); char* password = get_passwd(&settings, "cpasswd");
if (password != NULL) {
fPasswordControl->SetText(password);
delete[] password;
} else
fPasswordControl->SetText(settings.FindString("password"));
}
char *password = get_passwd(archive, "cpasswd"); if (settings.HasInt32("flavor") && fFlavorField != NULL) {
if (password) { if (BMenuItem* item = fFlavorField->Menu()->ItemAt(
SetTextControl(this,"pass", password); settings.FindInt32("flavor")))
delete[] password; item->SetMarked(true);
} else }
SetTextControl(this,"pass", archive->FindString("password"));
if (archive->HasInt32("flavor")) { if (settings.HasInt32("auth_method") && fAuthenticationField != NULL) {
BMenuField *menu = (BMenuField *)(FindView("flavor")); if (BMenuItem* item = fAuthenticationField->Menu()->ItemAt(
if (menu != NULL) { settings.FindInt32("auth_method"))) {
if (BMenuItem *item = menu->Menu()->ItemAt(archive->FindInt32("flavor"))) item->SetMarked(true);
item->SetMarked(true); _SetCredentialsEnabled(item->Command() != kMsgNoPassword);
} }
} }
if (archive->HasInt32("auth_method")) { if (fLeaveOnServerCheckBox != NULL) {
BMenuField *menu = (BMenuField *)(FindView("auth_method")); fLeaveOnServerCheckBox->SetValue(settings.FindBool(
if (menu != NULL) { "leave_mail_on_server") ? B_CONTROL_ON : B_CONTROL_OFF);
if (BMenuItem *item = menu->Menu()->ItemAt(archive->FindInt32("auth_method"))) {
item->SetMarked(true);
if (item->Command() != 'none') {
enable_control("user");
enable_control("pass");
}
}
}
} }
if (fRemoveFromServerCheckBox != NULL) {
BCheckBox *box = (BCheckBox *)(FindView("leave_mail_on_server")); fRemoveFromServerCheckBox->SetValue(settings.FindBool(
if (box != NULL) "delete_remote_when_local") ? B_CONTROL_ON : B_CONTROL_OFF);
box->SetValue(archive->FindBool("leave_mail_on_server") ? B_CONTROL_ON : B_CONTROL_OFF); fRemoveFromServerCheckBox->SetEnabled(
settings.FindBool("leave_mail_on_server"));
box = (BCheckBox *)(FindView("delete_remote_when_local"));
if (box != NULL) {
box->SetValue(archive->FindBool("delete_remote_when_local") ? B_CONTROL_ON : B_CONTROL_OFF);
if (archive->FindBool("leave_mail_on_server"))
box->SetEnabled(true);
else
box->SetEnabled(false);
} }
if (fBodyDownloadConfig) if (fBodyDownloadConfig != NULL)
fBodyDownloadConfig->SetTo(settings); fBodyDownloadConfig->SetTo(settings);
} }
void void
BMailProtocolConfigView::AddFlavor(const char *label) MailProtocolConfigView::AddFlavor(const char* label)
{ {
BMenuField *menu = (BMenuField *)(FindView("flavor")); if (fFlavorField != NULL) {
if (menu != NULL) { fFlavorField->Menu()->AddItem(new BMenuItem(label, NULL));
menu->Menu()->AddItem(new BMenuItem(label,NULL));
if (menu->Menu()->FindMarked() == NULL) if (fFlavorField->Menu()->FindMarked() == NULL)
menu->Menu()->ItemAt(0)->SetMarked(true); fFlavorField->Menu()->ItemAt(0)->SetMarked(true);
} }
} }
void void
BMailProtocolConfigView::AddAuthMethod(const char *label,bool needUserPassword) MailProtocolConfigView::AddAuthMethod(const char* label, bool needUserPassword)
{ {
BMenuField *menu = (BMenuField *)(FindView("auth_method")); if (fAuthenticationField != NULL) {
if (menu != NULL) { fAuthenticationField->Menu()->AddItem(new BMenuItem(label,
BMenuItem *item = new BMenuItem(label,new BMessage(needUserPassword ? 'some' : 'none')); new BMessage(needUserPassword
? kMsgLeaveOnServer : kMsgNoPassword)));
menu->Menu()->AddItem(item); if (fAuthenticationField->Menu()->FindMarked() == NULL) {
BMenuItem* item = fAuthenticationField->Menu()->ItemAt(0);
if (menu->Menu()->FindMarked() == NULL) { item->SetMarked(true);
menu->Menu()->ItemAt(0)->SetMarked(true); MessageReceived(item->Message());
MessageReceived(menu->Menu()->ItemAt(0)->Message());
} }
} }
} }
void BGridLayout*
BMailProtocolConfigView::AttachedToWindow() MailProtocolConfigView::Layout() const
{ {
BMenuField *menu = (BMenuField *)(FindView("auth_method")); return (BGridLayout*)BView::GetLayout();
if (menu != NULL)
menu->Menu()->SetTargetForItems(this);
BCheckBox *box = (BCheckBox *)(FindView("leave_mail_on_server"));
if (box != NULL)
box->SetTarget(this);
} }
void void
BMailProtocolConfigView::MessageReceived(BMessage *msg) MailProtocolConfigView::AttachedToWindow()
{ {
switch (msg->what) { if (fAuthenticationField != NULL)
case 'some': fAuthenticationField->Menu()->SetTargetForItems(this);
enable_control("user");
enable_control("pass"); if (fLeaveOnServerCheckBox != NULL)
fLeaveOnServerCheckBox->SetTarget(this);
}
void
MailProtocolConfigView::MessageReceived(BMessage* message)
{
switch (message->what) {
case kMsgNeedPassword:
_SetCredentialsEnabled(true);
break; break;
case 'none': case kMsgNoPassword:
disable_control("user"); _SetCredentialsEnabled(false);
disable_control("pass");
break; break;
case 'lmos': case kMsgLeaveOnServer:
if (msg->FindInt32("be:value") == 1) { fRemoveFromServerCheckBox->SetEnabled(
enable_control("delete_remote_when_local"); message->FindInt32("be:value") == B_CONTROL_ON);
} else {
disable_control("delete_remote_when_local");
}
break; break;
} }
} }
status_t status_t
BMailProtocolConfigView::Archive(BMessage *into, bool deep) const MailProtocolConfigView::Archive(BMessage* into, bool deep) const
{ {
const char *host = TextControl((BView *)this,"host"); if (fHostControl != NULL) {
int32 port = -1; int32 port = -1;
BString host_name = host; BString hostName = fHostControl->Text();
if (host_name.FindFirst(':') > -1) { if (hostName.FindFirst(':') > -1) {
port = atol(host_name.String() + host_name.FindFirst(':') + 1); port = atol(hostName.String() + hostName.FindFirst(':') + 1);
host_name.Truncate(host_name.FindFirst(':')); hostName.Truncate(hostName.FindFirst(':'));
}
if (into->ReplaceString("server", hostName.String()) != B_OK)
into->AddString("server", hostName.String());
// since there is no need for the port option, remove it here
into->RemoveName("port");
if (port != -1)
into->AddInt32("port", port);
} else {
into->RemoveName("server");
into->RemoveName("port");
} }
if (into->ReplaceString("server",host_name.String()) != B_OK) if (fUserControl != NULL) {
into->AddString("server",host_name.String()); if (into->ReplaceString("username", fUserControl->Text()) != B_OK)
into->AddString("username", fUserControl->Text());
// since there is no need for the port option, remove it here } else
into->RemoveName("port"); into->RemoveName("username");
if (port != -1)
into->AddInt32("port",port);
if (into->ReplaceString("username",TextControl((BView *)this,"user")) != B_OK)
into->AddString("username",TextControl((BView *)this,"user"));
// remove old unencrypted passwords // remove old unencrypted passwords
into->RemoveName("password"); into->RemoveName("password");
set_passwd(into,"cpasswd",TextControl((BView *)this,"pass")); if (fPasswordControl != NULL)
set_passwd(into, "cpasswd", fPasswordControl->Text());
else
into->RemoveName("cpasswd");
BMenuField *field; _StoreIndexOfMarked(*into, "flavor", fFlavorField);
int32 index = -1; _StoreIndexOfMarked(*into, "auth_method", fAuthenticationField);
if ((field = (BMenuField *)(FindView("flavor"))) != NULL) { _StoreCheckBox(*into, "leave_mail_on_server", fLeaveOnServerCheckBox);
BMenuItem *item = field->Menu()->FindMarked(); _StoreCheckBox(*into, "delete_remote_when_local",
if (item != NULL) fRemoveFromServerCheckBox);
index = field->Menu()->IndexOf(item);
}
if (into->ReplaceInt32("flavor",index) != B_OK) if (fBodyDownloadConfig != NULL)
into->AddInt32("flavor",index); return fBodyDownloadConfig->Archive(into, deep);
index = -1;
if ((field = (BMenuField *)(FindView("auth_method"))) != NULL) {
BMenuItem *item = field->Menu()->FindMarked();
if (item != NULL)
index = field->Menu()->IndexOf(item);
}
if (into->ReplaceInt32("auth_method",index) != B_OK)
into->AddInt32("auth_method",index);
if (FindView("leave_mail_on_server") != NULL) {
BControl* control = (BControl*)FindView("leave_mail_on_server");
bool on = (control->Value() == B_CONTROL_ON);
if (into->ReplaceBool("leave_mail_on_server", on) != B_OK)
into->AddBool("leave_mail_on_server", on);
control = (BControl*)FindView("delete_remote_when_local");
on = (control->Value() == B_CONTROL_ON);
if (into->ReplaceBool("delete_remote_when_local", on)) {
into->AddBool("delete_remote_when_local", on);
}
} else {
if (into->ReplaceBool("leave_mail_on_server", false) != B_OK)
into->AddBool("leave_mail_on_server", false);
if (into->ReplaceBool("delete_remote_when_local", false) != B_OK)
into->AddBool("delete_remote_when_local", false);
}
if (fBodyDownloadConfig)
fBodyDownloadConfig->Archive(into, deep);
return B_OK; return B_OK;
} }
void BTextControl*
BMailProtocolConfigView::GetPreferredSize(float *width, float *height) MailProtocolConfigView::_AddTextControl(BGridLayout* layout, const char* name,
const char* label)
{ {
float minWidth = 250; BTextControl* control = new BTextControl(name, label, "", NULL);
if (BView *view = FindView("delete_remote_when_local")) { int32 row = layout->CountRows();
float ignore; layout->AddItem(control->CreateLabelLayoutItem(), 0, row);
view->GetPreferredSize(&minWidth,&ignore); layout->AddItem(control->CreateTextViewLayoutItem(), 1, row);
} return control;
if (minWidth < 250) }
minWidth = 250;
*width = minWidth + 10;
*height = (CountChildren() * sItemHeight) + 5;
if (fBodyDownloadConfig) {
float bodyW, bodyH; BMenuField*
fBodyDownloadConfig->GetPreferredSize(&bodyW, &bodyH); MailProtocolConfigView::_AddMenuField(BGridLayout* layout, const char* name,
*height+= bodyH; const char* label)
{
BPopUpMenu* menu = new BPopUpMenu("");
BMenuField* field = new BMenuField(name, label, menu);
int32 row = layout->CountRows();
layout->AddItem(field->CreateLabelLayoutItem(), 0, row);
layout->AddItem(field->CreateMenuBarLayoutItem(), 1, row);
return field;
}
void
MailProtocolConfigView::_StoreIndexOfMarked(BMessage& message, const char* name,
BMenuField* field) const
{
int32 index = -1;
if (field != NULL) {
BMenuItem* item = field->Menu()->FindMarked();
if (item != NULL)
index = field->Menu()->IndexOf(item);
}
if (message.ReplaceInt32(name, index) != B_OK)
message.AddInt32(name, index);
}
void
MailProtocolConfigView::_StoreCheckBox(BMessage& message, const char* name,
BCheckBox* checkBox) const
{
bool value = checkBox != NULL && checkBox->Value() == B_CONTROL_ON;
if (value) {
if (message.ReplaceBool(name, value) != B_OK)
message.AddBool(name, value);
} else
message.RemoveName(name);
}
void
MailProtocolConfigView::_SetCredentialsEnabled(bool enabled)
{
if (fUserControl != NULL && fPasswordControl != NULL) {
fUserControl->SetEnabled(enabled);
fPasswordControl->SetEnabled(enabled);
} }
} }
} // namespace BPrivate
+15 -17
View File
@@ -27,10 +27,10 @@ check_for_mail(int32 * incoming_count)
status_t err = BMailDaemon::CheckMail(true); status_t err = BMailDaemon::CheckMail(true);
if (err < B_OK) if (err < B_OK)
return err; return err;
if (incoming_count != NULL) if (incoming_count != NULL)
*incoming_count = BMailDaemon::CountNewMessages(true); *incoming_count = BMailDaemon::CountNewMessages(true);
return B_OK; return B_OK;
} }
@@ -74,20 +74,19 @@ get_pop_account(mail_pop_account* account, int32 index)
if (accountSettings == NULL) if (accountSettings == NULL)
return B_BAD_INDEX; return B_BAD_INDEX;
const BMessage& settings = accountSettings->InboundSettings().Settings(); const BMessage& settings = accountSettings->InboundSettings();
strcpy(account->pop_name, settings.FindString("username")); strcpy(account->pop_name, settings.FindString("username"));
strcpy(account->pop_host, settings.FindString("server")); strcpy(account->pop_host, settings.FindString("server"));
strcpy(account->real_name, accountSettings->RealName()); strcpy(account->real_name, accountSettings->RealName());
strcpy(account->reply_to, accountSettings->ReturnAddress()); strcpy(account->reply_to, accountSettings->ReturnAddress());
const char *password, *passwd; const char* encryptedPassword = get_passwd(&settings, "cpasswd");
password = settings.FindString("password"); const char* password = encryptedPassword;
passwd = get_passwd(&settings, "cpasswd"); if (password == NULL)
if (passwd) password = settings.FindString("password");
password = passwd;
strcpy(account->pop_password, password); strcpy(account->pop_password, password);
free((char *)passwd); delete[] encryptedPassword;
return B_OK; return B_OK;
} }
@@ -107,14 +106,13 @@ get_smtp_host(char* buffer)
BMailSettings().DefaultOutboundAccount()); BMailSettings().DefaultOutboundAccount());
if (account == NULL) if (account == NULL)
return B_ERROR; return B_ERROR;
const BMessage& settings = account->OutboundSettings().Settings(); const BMessage& settings = account->OutboundSettings();
if (settings.HasString("server")) if (!settings.HasString("server"))
strcpy(buffer,settings.FindString("server"));
else
return B_NAME_NOT_FOUND; return B_NAME_NOT_FOUND;
strcpy(buffer, settings.FindString("server"));
return B_OK; return B_OK;
} }
@@ -136,6 +134,6 @@ forward_mail(entry_ref *ref, const char *recipients, bool now)
BEmailMessage mail(&file); BEmailMessage mail(&file);
mail.SetTo(recipients); mail.SetTo(recipients);
return mail.Send(now); return mail.Send(now);
} }