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>
class BMailFilter;
class BMailNotifier {
public:
virtual ~BMailNotifier() {}
@@ -38,71 +41,47 @@ public:
};
class MailProtocol;
class MailFilter {
class BMailProtocol : BLooper {
public:
MailFilter(MailProtocol& protocol,
AddonSettings* settings);
virtual ~MailFilter();
BMailProtocol(
const BMailAccountSettings& settings);
virtual ~BMailProtocol();
//! 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 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);
const BMailAccountSettings& AccountSettings() const;
void SetMailNotifier(BMailNotifier* mailNotifier);
BMailNotifier* MailNotifier() const;
virtual void ShowError(const char* error);
virtual void ShowMessage(const char* message);
virtual void SetTotalItems(int32 items);
virtual void SetTotalItemsSize(int32 size);
virtual void ReportProgress(int bytes, int messages,
//! We take ownership of the filters
bool AddFilter(BMailFilter* filter);
int32 CountFilter() const;
BMailFilter* FilterAt(int32 index) const;
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);
virtual 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);
void ResetProgress(const char* message = NULL);
// Filter notifications
void NotifyNewMessagesToFetch(int32 nMessages);
void NotifyHeaderFetched(const entry_ref& ref,
BFile* mail);
@@ -113,35 +92,29 @@ public:
void NotifyMessageSent(const entry_ref& ref,
BFile* mail);
//! mail storage operations
virtual status_t MoveMessage(const entry_ref& ref,
BDirectory& dir);
virtual status_t DeleteMessage(const entry_ref& ref);
void LoadFilters(
const BMailProtocolSettings& settings);
virtual void FileRenamed(const entry_ref& from,
const entry_ref& to);
virtual void FileDeleted(const node_ref& node);
private:
BMailFilter* _LoadFilter(BMailAddOnSettings* filterSettings);
protected:
void LoadFilters(MailAddonSettings& settings);
BMailAccountSettings fAccountSettings;
const BMailAccountSettings fAccountSettings;
BMailNotifier* fMailNotifier;
private:
MailFilter* _LoadFilter(AddonSettings* filterSettings);
MailProtocolThread* fProtocolThread;
BObjectList<BHandler> fHandlerList;
BObjectList<MailFilter> fFilterList;
std::map<entry_ref, image_id> fFilterImages;
BObjectList<BMailFilter> fFilterList;
std::map<entry_ref, image_id> fFilterImages;
};
class InboundProtocol : public MailProtocol {
class BInboundMailProtocol : public BMailProtocol {
public:
InboundProtocol(BMailAccountSettings* settings);
virtual ~InboundProtocol();
BInboundMailProtocol(
const BMailAccountSettings& settings);
virtual ~BInboundMailProtocol();
virtual void MessageReceived(BMessage* message);
virtual status_t SyncMessages() = 0;
virtual status_t FetchBody(const entry_ref& ref) = 0;
@@ -149,78 +122,33 @@ public:
read_flags flag = B_READ);
virtual status_t DeleteMessage(const entry_ref& ref) = 0;
virtual status_t AppendMessage(const entry_ref& ref);
protected:
void NotiyMailboxSynchronized(status_t status);
};
class OutboundProtocol : public MailProtocol {
class BOutboundMailProtocol : public BMailProtocol {
public:
OutboundProtocol(
BMailAccountSettings* settings);
virtual ~OutboundProtocol();
BOutboundMailProtocol(
const BMailAccountSettings& settings);
virtual ~BOutboundMailProtocol();
virtual status_t SendMessages(const std::vector<entry_ref>&
mails, size_t totalBytes) = 0;
virtual void MessageReceived(BMessage* message);
virtual status_t SendMessages(
const std::vector<entry_ref>& mails,
size_t totalBytes) = 0;
};
class MailProtocolThread : public BLooper {
public:
MailProtocolThread(MailProtocol* protocol);
virtual void MessageReceived(BMessage* message);
MailProtocol* Protocol() { return fMailProtocol; }
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;
};
// Your protocol needs to export these hooks in order to be picked up
extern "C" _EXPORT BInboundMailProtocol* instantiate_inbound_protocol(
const BMailAccountSettings& settings);
extern "C" _EXPORT BOutboundMailProtocol* instantiate_outbound_protocol(
const BMailAccountSettings& settings);
extern "C" _EXPORT BView* instantiate_protocol_config_panel(
BMailAccountSettings& settings);
#endif // MAIL_PROTOCOL_H
@@ -1,9 +1,11 @@
/* ProtocolConfigView - the standard config view for all protocols
**
** Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved.
*/
#ifndef ZOIDBERG_PROTOCOL_CONFIG_VIEW_H
#define ZOIDBERG_PROTOCOL_CONFIG_VIEW_H
/*
* Copyright 2004-2012, Haiku Inc. All rights reserved.
* Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved.
*
* Distributed under the terms of the MIT License.
*/
#ifndef _PROTOCOL_CONFIG_VIEW_H
#define _PROTOCOL_CONFIG_VIEW_H
#include <CheckBox.h>
@@ -11,19 +13,29 @@
#include <TextControl.h>
#include <View.h>
#include "MailSettings.h"
#include <MailSettings.h>
class BCheckBox;
class BGridLayout;
class BMenuField;
class BTextControl;
namespace BPrivate {
class BodyDownloadConfig : public BView {
public:
BodyDownloadConfig();
void SetTo(MailAddonSettings& settings);
void SetTo(BMailProtocolSettings& settings);
void MessageReceived(BMessage *msg);
void MessageReceived(BMessage* message);
void AttachedToWindow();
void GetPreferredSize(float *width, float *height);
status_t Archive(BMessage *into, bool) const;
void GetPreferredSize(float* width, float* height);
status_t Archive(BMessage* into, bool deep = true) const;
private:
BTextControl* fSizeBox;
BCheckBox* fPartialBox;
@@ -31,39 +43,64 @@ private:
};
typedef enum {
B_MAIL_PROTOCOL_HAS_AUTH_METHODS = 1,
enum mail_protocol_config_options {
B_MAIL_PROTOCOL_HAS_AUTH_METHODS = 1,
B_MAIL_PROTOCOL_HAS_FLAVORS = 2,
B_MAIL_PROTOCOL_HAS_USERNAME = 4,
B_MAIL_PROTOCOL_HAS_PASSWORD = 8,
B_MAIL_PROTOCOL_HAS_HOSTNAME = 16,
B_MAIL_PROTOCOL_CAN_LEAVE_MAIL_ON_SERVER = 32,
B_MAIL_PROTOCOL_PARTIAL_DOWNLOAD = 64
} b_mail_protocol_config_options;
B_MAIL_PROTOCOL_HAS_USERNAME = 4,
B_MAIL_PROTOCOL_HAS_PASSWORD = 8,
B_MAIL_PROTOCOL_HAS_HOSTNAME = 16,
B_MAIL_PROTOCOL_CAN_LEAVE_MAIL_ON_SERVER = 32,
B_MAIL_PROTOCOL_PARTIAL_DOWNLOAD = 64
};
class BMailProtocolConfigView : public BView {
class MailProtocolConfigView : public BView {
public:
BMailProtocolConfigView(uint32 options_mask
= B_MAIL_PROTOCOL_HAS_FLAVORS
| B_MAIL_PROTOCOL_HAS_USERNAME
| B_MAIL_PROTOCOL_HAS_PASSWORD
| B_MAIL_PROTOCOL_HAS_HOSTNAME);
virtual ~BMailProtocolConfigView();
void SetTo(MailAddonSettings& archive);
void AddFlavor(const char *label);
void AddAuthMethod(const char *label,
MailProtocolConfigView(uint32 optionsMask
= B_MAIL_PROTOCOL_HAS_FLAVORS
| B_MAIL_PROTOCOL_HAS_USERNAME
| B_MAIL_PROTOCOL_HAS_PASSWORD
| B_MAIL_PROTOCOL_HAS_HOSTNAME);
virtual ~MailProtocolConfigView();
void SetTo(BMailProtocolSettings& settings);
void AddFlavor(const char* label);
void AddAuthMethod(const char* label,
bool needUserPassword = true);
virtual status_t Archive(BMessage *into, bool deep = true) const;
virtual void GetPreferredSize(float *width, float *height);
BGridLayout* Layout() const;
virtual status_t Archive(BMessage* into, bool deep = true) const;
virtual void AttachedToWindow();
virtual void MessageReceived(BMessage *msg);
virtual void MessageReceived(BMessage* message);
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;
};
#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 2011 Clemens Zeidler.
*
* Distributed under the terms of the MIT License.
*/
#ifndef MAIL_SETTINGS_H
@@ -77,49 +79,49 @@ private:
};
class AddonSettings {
class BMailAddOnSettings : public BMessage {
public:
AddonSettings();
BMailAddOnSettings();
virtual ~BMailAddOnSettings();
bool Load(const BMessage& message);
bool Save(BMessage& message);
virtual status_t Load(const BMessage& message);
virtual status_t Save(BMessage& message);
void SetAddonRef(const entry_ref& ref);
const entry_ref& AddonRef() const;
void SetAddOnRef(const entry_ref& ref);
const entry_ref& AddOnRef() const;
const BMessage& Settings() const;
BMessage& EditSettings();
bool HasBeenModified();
virtual bool HasBeenModified() const;
private:
BMessage fSettings;
entry_ref fAddonRef;
bool fModified;
BMessage fOriginalSettings;
entry_ref fRef;
entry_ref fOriginalRef;
};
class MailAddonSettings : public AddonSettings {
class BMailProtocolSettings : public BMailAddOnSettings {
public:
bool Load(const BMessage& message);
bool Save(BMessage& message);
BMailProtocolSettings();
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);
bool RemoveFilterSettings(int32 index);
void RemoveFilterSettings(int32 index);
bool MoveFilterSettings(int32 from, int32 to);
AddonSettings* FilterSettingsAt(int32 index);
BMailAddOnSettings* FilterSettingsAt(int32 index) const;
bool HasBeenModified();
virtual bool HasBeenModified() const;
private:
std::vector<AddonSettings> fFiltersSettings;
BObjectList<BMailAddOnSettings> fFiltersSettings;
};
class BMailAccountSettings {
public:
public:
BMailAccountSettings();
BMailAccountSettings(BEntry account);
~BMailAccountSettings();
@@ -127,24 +129,26 @@ class BMailAccountSettings {
status_t InitCheck() { return fStatus; }
void SetAccountID(int32 id);
int32 AccountID();
int32 AccountID() const;
void SetName(const char* name);
const char* Name() const;
const char* Name() const;
void SetRealName(const char* realName);
const char* RealName() const;
const char* RealName() const;
void SetReturnAddress(const char* returnAddress);
const char* ReturnAddress() const;
const char* ReturnAddress() const;
bool SetInboundAddon(const char* name);
bool SetOutboundAddon(const char* name);
const entry_ref& InboundPath() const;
const entry_ref& OutboundPath() const;
bool SetInboundAddOn(const char* name);
bool SetOutboundAddOn(const char* name);
const entry_ref& InboundAddOnRef() const;
const entry_ref& OutboundAddOnRef() const;
MailAddonSettings& InboundSettings();
MailAddonSettings& OutboundSettings();
BMailProtocolSettings& InboundSettings();
const BMailProtocolSettings& InboundSettings() const;
BMailProtocolSettings& OutboundSettings();
const BMailProtocolSettings& OutboundSettings() const;
bool HasInbound();
bool HasOutbound();
@@ -158,9 +162,9 @@ class BMailAccountSettings {
status_t Save();
status_t Delete();
bool HasBeenModified();
bool HasBeenModified() const;
const BEntry& AccountFile();
const BEntry& AccountFile() const;
private:
status_t _CreateAccountFilePath();
@@ -175,8 +179,8 @@ private:
BString fRealName;
BString fReturnAdress;
MailAddonSettings fInboundSettings;
MailAddonSettings fOutboundSettings;
BMailProtocolSettings fInboundSettings;
BMailProtocolSettings fOutboundSettings;
bool fInboundEnabled;
bool fOutboundEnabled;
+48 -35
View File
@@ -1,9 +1,11 @@
#ifndef FILE_CONFIG_VIEW
#define FILE_CONFIG_VIEW
/* FileConfigView - a file configuration view for filters
**
** Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved.
*/
/*
* Copyright 2004-2012, Haiku, Inc. 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>
@@ -13,45 +15,56 @@
class BTextControl;
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();
virtual void MessageReceived(BMessage *msg);
namespace BPrivate {
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:
BTextControl *fText;
BButton *fButton;
void SetText(const char* pathOfFile);
const char* Text() const;
BFilePanel *fPanel;
uint32 _reserved[5];
void SetEnabled(bool enabled);
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);
virtual status_t Archive(BMessage *into, bool deep = true) const;
class MailFileConfigView : public FileControl {
public:
MailFileConfigView(const char* label,
const char* name, bool useMeta = false,
const char* defaultPath = NULL,
uint32 flavors = B_DIRECTORY_NODE);
private:
BMessage *fMeta;
bool fUseMeta;
const char *fName;
void SetTo(const BMessage* archive,
BMessage* metadata);
virtual status_t Archive(BMessage* into, bool deep = true) const;
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 2001 Dr. Zoidberg Enterprises. All rights reserved.
*/
/*
* Copyright 2004-2012, Haiku, Inc. All rights reserved.
* Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved.
*
* Distributed under the terms of the MIT License.
*/
#include <stdio.h>
#include <Catalog.h>
#include <MenuField.h>
#include <PopUpMenu.h>
#include <Message.h>
#include <TextControl.h>
#include <MenuItem.h>
#include <MailAddon.h>
#include <FileConfigView.h>
#include <LayoutBuilder.h>
#include <MailFilter.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
#define B_TRANSLATION_CONTEXT "ConfigView"
const uint32 kMsgActionMoveTo = 'argm';
const uint32 kMsgActionDelete = 'argd';
const uint32 kMsgActionSetTo = 'args';
const uint32 kMsgActionReplyWith = 'argr';
const uint32 kMsgActionSetRead = 'arge';
using namespace BPrivate;
static const uint32 kMsgActionChanged = 'actC';
class RuleFilterConfig : public BView {
public:
RuleFilterConfig(const BMessage *settings);
public:
RuleFilterConfig(const BMessage& settings);
virtual void MessageReceived(BMessage *msg);
virtual void AttachedToWindow();
virtual status_t Archive(BMessage *into, bool deep = true) const;
virtual void GetPreferredSize(float *width, float *height);
private:
BTextControl *attr, *regex;
BFileControl *arg;
BPopUpMenu *menu, *outbound;
BMenuField *outbound_field;
int staging;
int32 chain;
virtual void MessageReceived(BMessage* message);
virtual void AttachedToWindow();
virtual status_t Archive(BMessage* into, bool deep = true) const;
private:
void _SetVisible(BView* view, bool visible);
private:
BTextControl* fAttributeControl;
BTextControl* fRegexControl;
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,
0), menu(NULL)
BView("rulefilter_config", 0),
fActionMenu(NULL)
{
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 "
"*spam*)"), NULL);
regex->SetDivider(be_plain_font->StringWidth(B_TRANSLATE("has")) + 4);
if (settings->HasString("regex"))
regex->SetText(settings->FindString("regex"));
AddChild(regex);
"*spam*)"), NULL);
if (settings.HasString("regex"))
fRegexControl->SetText(settings.FindString("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"));
if (BControl *control = (BControl *)arg->FindView("select_file"))
if (BControl* control = (BControl*)fFileControl->FindView("select_file"))
control->SetEnabled(false);
if (settings->HasString("argument"))
arg->SetText(settings->FindString("argument"));
if (fAction == ACTION_MOVE_TO && settings.HasString("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"))
staging = settings->FindInt32("do_what");
// Populate account menu
fAccountMenu = new BPopUpMenu(B_TRANSLATE("<Choose account>"));
if (fAction == ACTION_REPLY_WITH)
fAccountID = settings.FindInt32("argument");
else
staging = -1;
if (staging == 3)
chain = settings->FindInt32("argument");
else
chain = -1;
printf("Chain: %" B_PRId32 "\n",chain);
fAccountID = -1;
BMailAccounts accounts;
for (int32 i = 0; i < accounts.CountAccounts(); i++) {
BMailAccountSettings* account = accounts.AccountAt(i);
if (!account->HasOutbound())
continue;
BMenuItem *item = new BMenuItem(account->Name(),
new BMessage(account->AccountID()));
outbound->AddItem(item);
if (account->AccountID() == chain)
BMessage* message = new BMessage();
message->AddInt32("account id", account->AccountID());
BMenuItem* item = new BMenuItem(account->Name(), message);
fAccountMenu->AddItem(item);
if (account->AccountID() == fAccountID)
item->SetMarked(true);
}
}
void RuleFilterConfig::AttachedToWindow() {
if (menu != NULL)
return; // We switched back from another tab
menu = new BPopUpMenu(B_TRANSLATE("<Choose action>"));
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);
fAccountField = new BMenuField("reply", "Foo", fAccountMenu);
if (fAction >= 0) {
BMenuItem* item = fActionMenu->ItemAt(fAction);
if (item != NULL) {
item->SetMarked(true);
MessageReceived(item->Message());
}
}
// 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->AddInt32("do_what",menu->IndexOf(menu->FindMarked()));
into->AddString("attribute",attr->Text());
into->AddString("regex",regex->Text());
if (into->FindInt32("do_what") == 3)
into->AddInt32("argument", outbound->FindMarked()->Message()->what);
else
into->AddString("argument",arg->Text());
into->AddInt32("do_what", fActionMenu->IndexOf(fActionMenu->FindMarked()));
into->AddString("attribute", fAttributeControl->Text());
into->AddString("regex", fRegexControl->Text());
if (into->FindInt32("do_what") == ACTION_REPLY_WITH) {
BMenuItem* item = fAccountMenu->FindMarked();
if (item != NULL) {
into->AddInt32("argument",
item->Message()->FindInt32("account id"));
}
} else
into->AddString("argument", fFileControl->Text());
return B_OK;
}
void RuleFilterConfig::MessageReceived(BMessage *msg) {
switch (msg->what)
{
case kMsgActionMoveTo:
case kMsgActionSetTo:
if (arg->FindView("file_path"))
arg->SetEnabled(true);
if (BControl *control = (BControl *)arg->FindView("select_file"))
control->SetEnabled(msg->what == kMsgActionMoveTo);
if (arg->Parent() == NULL) {
outbound_field->RemoveSelf();
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);
}
void
RuleFilterConfig::MessageReceived(BMessage* message)
{
switch (message->what) {
case kMsgActionChanged:
fAction = message->FindInt32("action");
_SetVisible(fFileControl, fAction == ACTION_MOVE_TO);
_SetVisible(fFlagsControl, fAction == ACTION_SET_FLAGS_TO);
_SetVisible(fAccountField, fAction == ACTION_REPLY_WITH);
break;
default:
BView::MessageReceived(msg);
BView::MessageReceived(message);
}
}
void RuleFilterConfig::GetPreferredSize(float *width, float *height) {
*width = 260;
*height = 55;
}
BView* instantiate_filter_config_panel(AddonSettings& settings)
void
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 2001 Dr. Zoidberg Enterprises. All rights reserved.
*/
/*
* Copyright 2004-2012, Haiku, Inc. 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"
@@ -22,38 +27,46 @@
#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
settings->FindString("attribute", &fAttribute);
fAttribute.CapitalizeEachWord();
BString regex;
settings->FindString("regex", &regex);
int32 index = regex.FindFirst("REGEX:");
settings->FindString("regex", &fExpression);
int32 index = fExpression.FindFirst("REGEX:");
if (index == B_ERROR || index > 0)
EscapeRegexTokens(regex);
EscapeRegexTokens(fExpression);
else
regex.RemoveFirst("REGEX:");
fMatcher.SetPattern(regex, false);
settings->FindString("argument",&fArg);
settings->FindInt32("do_what", (int32*)&fDoWhat);
if (fDoWhat == Z_SET_REPLY)
fExpression.RemoveFirst("REGEX:");
fMatcher.SetPattern(fExpression, false);
settings->FindString("argument", &fArg);
settings->FindInt32("do_what", (int32*)&fAction);
if (fAction == ACTION_REPLY_WITH)
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
RuleFilter::HeaderFetched(const entry_ref& ref, BFile* file)
{
// That field doesn't exist? NO match
if (fAttribute == "")
return; //----That field doesn't exist? NO match
return;
attr_info info;
if (file->GetAttrInfo("Subject", &info) != B_OK
@@ -68,72 +81,59 @@ RuleFilter::HeaderFetched(const entry_ref& ref, BFile* file)
BString data = buffer;
delete[] buffer;
if (!fMatcher.Match(data))
return; //-----There wasn't an error. We're just not supposed to do anything
switch (fDoWhat) {
case Z_MOVE_TO:
if (!fMatcher.Match(data)) {
// We're not supposed to do anything
return;
}
switch (fAction) {
case ACTION_MOVE_TO:
{
BDirectory dir(fArg);
fMailProtocol.Looper()->TriggerFileMove(ref, dir);
// TODO: move is currently broken!
// fMailProtocol.Looper()->TriggerFileMove(ref, dir);
break;
}
case Z_TRASH:
case ACTION_DELETE_MESSAGE:
// TODO trash!?
fMailProtocol.Looper()->TriggerFileDeletion(ref);
// fMailProtocol.Looper()->TriggerFileDeletion(ref);
break;
case Z_FLAG:
case ACTION_SET_FLAGS_TO:
file->WriteAttrString("MAIL:filter_flags", &fArg);
break;
case Z_SET_REPLY:
case ACTION_REPLY_WITH:
file->WriteAttr("MAIL:reply_with", B_INT32_TYPE, 0, &fReplyAccount,
4);
sizeof(int32));
break;
case Z_SET_READ:
case ACTION_SET_AS_READ:
{
InboundProtocol& protocol = (InboundProtocol&)fMailProtocol;
BInboundMailProtocol& protocol
= (BInboundMailProtocol&)fMailProtocol;
protocol.MarkMessageAsRead(ref, B_READ);
break;
}
default:
fprintf(stderr,"Unknown do_what: 0x%04x!\n", fDoWhat);
fprintf(stderr,"Unknown do_what: 0x%04x!\n", fAction);
}
return;
}
// #pragma mark -
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");
}
MailFilter*
instantiate_mailfilter(MailProtocol& protocol, AddonSettings* settings)
BMailFilter*
instantiate_filter(BMailProtocol& protocol, BMailAddOnSettings* settings)
{
return new RuleFilter(protocol, settings);
}
@@ -1,40 +1,47 @@
#ifndef ZOIDBERG_RULE_FILTER_H
#define ZOIDBERG_RULE_FILTER_H
/* RuleFilter - performs action depending on matching a header value
**
** Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved.
*/
/*
* Copyright 2004-2012, Haiku, Inc. 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 <List.h>
#include <MailAddon.h>
#include <MailFilter.h>
#include "StringMatcher.h"
typedef enum {
Z_MOVE_TO,
Z_FLAG,
Z_TRASH,
Z_SET_REPLY,
Z_SET_READ
} z_mail_action_flags;
enum rule_action {
ACTION_MOVE_TO,
ACTION_SET_FLAGS_TO,
ACTION_DELETE_MESSAGE,
ACTION_REPLY_WITH,
ACTION_SET_AS_READ
};
class RuleFilter : public MailFilter {
class RuleFilter : public BMailFilter {
public:
RuleFilter(MailProtocol& protocol,
AddonSettings* settings);
void HeaderFetched(const entry_ref& ref,
RuleFilter(BMailProtocol& protocol,
BMailAddOnSettings* settings);
virtual BString DescriptiveName() const;
virtual void HeaderFetched(const entry_ref& ref,
BFile* file);
private:
StringMatcher fMatcher;
BString fAttribute;
BString fExpression;
StringMatcher fMatcher;
BString fArg;
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 2001 Dr. Zoidberg Enterprises. All rights reserved.
*/
/*
* Copyright 2004-2012, Haiku, Inc. All rights reserved.
* Copyright 2001, Dr. Zoidberg Enterprises. All rights reserved.
*
* Distributed under the terms of the MIT License.
*/
#include "ConfigView.h"
#include <Catalog.h>
#include <CheckBox.h>
#include <LayoutBuilder.h>
#include <PopUpMenu.h>
#include <MenuItem.h>
#include <MenuField.h>
#include <String.h>
#include <Message.h>
#include <MailAddon.h>
#include <MailFilter.h>
#include <MailSettings.h>
@@ -26,18 +29,12 @@ const uint32 kMsgNotifyMethod = 'nomt';
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));
// determine font height
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);
BPopUpMenu *menu = new BPopUpMenu(B_EMPTY_STRING, false, false);
const char *notifyMethods[] = {
B_TRANSLATE("Beep"),
@@ -47,29 +44,26 @@ ConfigView::ConfigView()
B_TRANSLATE("Central beep"),
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],
new BMessage(kMsgNotifyMethod)));
}
BMenuField *field = new BMenuField(frame,"notify", B_TRANSLATE("Method:"),
menu);
field->ResizeToPreferred();
field->SetDivider(field->StringWidth(B_TRANSLATE("Method:")) + 6);
AddChild(field);
ResizeToPreferred();
}
BLayoutBuilder::Group<>(this).Add(
new BMenuField("notify", B_TRANSLATE("Method:"), menu));
}
void ConfigView::AttachedToWindow()
void
ConfigView::AttachedToWindow()
{
if (BMenuField *field = dynamic_cast<BMenuField *>(FindView("notify")))
field->Menu()->SetTargetForItems(this);
}
void ConfigView::SetTo(const BMessage *archive)
void
ConfigView::SetTo(const BMessage *archive)
{
int32 method = archive->FindInt32("notification_method");
if (method < 0)
@@ -79,8 +73,7 @@ void ConfigView::SetTo(const BMessage *archive)
if ((field = dynamic_cast<BMenuField *>(FindView("notify"))) == NULL)
return;
for (int32 i = field->Menu()->CountItems();i-- > 0;)
{
for (int32 i = field->Menu()->CountItems(); i-- > 0;) {
BMenuItem *item = field->Menu()->ItemAt(i);
item->SetMarked((method & (1L << i)) != 0);
}
@@ -88,15 +81,15 @@ void ConfigView::SetTo(const BMessage *archive)
}
void ConfigView::UpdateNotifyText()
void
ConfigView::UpdateNotifyText()
{
BMenuField *field;
if ((field = dynamic_cast<BMenuField *>(FindView("notify"))) == NULL)
return;
BString label;
for (int32 i = field->Menu()->CountItems();i-- > 0;)
{
for (int32 i = field->Menu()->CountItems(); i-- > 0;) {
BMenuItem *item = field->Menu()->ItemAt(i);
if (!item->IsMarked())
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:
{
BMenuItem *item;
if (msg->FindPointer("source",(void **)&item) < B_OK)
break;
item->SetMarked(!item->IsMarked());
UpdateNotifyText();
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;
BMenuField *field;
if ((field = dynamic_cast<BMenuField *>(FindView("notify"))) != NULL)
{
for (int32 i = field->Menu()->CountItems();i-- > 0;)
{
if ((field = dynamic_cast<BMenuField *>(FindView("notify"))) != NULL) {
for (int32 i = field->Menu()->CountItems(); i-- > 0;) {
BMenuItem *item = field->Menu()->ItemAt(i);
if (item->IsMarked())
method |= 1L << i;
}
}
if (into->ReplaceInt32("notification_method",method) != B_OK)
into->AddInt32("notification_method",method);
if (into->ReplaceInt32("notification_method", method) != B_OK)
into->AddInt32("notification_method", method);
return B_OK;
}
void ConfigView::GetPreferredSize(float *width, float *height)
{
*width = 258;
*height = ChildAt(0)->Bounds().Height() + 8;
}
// #pragma mark -
BView*
instantiate_filter_config_panel(AddonSettings& settings)
instantiate_filter_config_panel(BMailAddOnSettings& settings)
{
ConfigView *view = new ConfigView();
view->SetTo(&settings.Settings());
view->SetTo(&settings);
return view;
}
BString
descriptive_name()
{
return B_TRANSLATE("New mails notification");
}
@@ -1,35 +1,39 @@
#ifndef CONFIG_VIEW
#define CONFIG_VIEW
/* ConfigView - the configuration view for the Notifier filter
**
** Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved.
*/
/*
* Copyright 2004-2012, Haiku, Inc. 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>
enum {
do_beep = 1,
alert = 2,
blink_leds = 4,
big_doozy_alert = 8,
one_central_beep = 16,
log_window = 32
NOTIFY_BEEP = 1,
NOTIFY_ALERT = 2,
NOTIFY_BLINK_LEDS = 4,
NOTIFY_CENTRAL_ALERT = 8,
NOTIFY_CENTRAL_BEEP = 16,
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();
virtual void MessageReceived(BMessage *msg);
virtual void GetPreferredSize(float *width, float *height);
class ConfigView : public BView {
public:
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 2011, Clemens Zeidler <haiku@clemens-zeidler.de>
*/
*
* Distributed under the terms of the MIT License.
*/
//! Notifies incoming e-mail
#include <Alert.h>
@@ -14,7 +19,7 @@
#include <Path.h>
#include <String.h>
#include <MailAddon.h>
#include <MailFilter.h>
#include "ConfigView.h"
@@ -23,33 +28,44 @@
#define B_TRANSLATION_CONTEXT "filter"
class NotifyFilter : public MailFilter
{
class NotifyFilter : public BMailFilter {
public:
NotifyFilter(MailProtocol& protocol,
AddonSettings* settings);
NotifyFilter(BMailProtocol& protocol,
BMailAddOnSettings* settings);
virtual BString DescriptiveName() const;
void HeaderFetched(const entry_ref& ref,
BFile* file);
void MailboxSynced(status_t status);
void MailboxSynchronized(status_t status);
private:
int32 fStrategy;
int32 fNNewMessages;
};
NotifyFilter::NotifyFilter(MailProtocol& protocol, AddonSettings* settings)
NotifyFilter::NotifyFilter(BMailProtocol& protocol,
BMailAddOnSettings* settings)
:
MailFilter(protocol, settings),
BMailFilter(protocol, settings),
fNNewMessages(0)
{
fStrategy = settings->Settings().FindInt32("notification_method");
fStrategy = settings->FindInt32("notification_method");
}
BString
NotifyFilter::DescriptiveName() const
{
return filter_name();
}
void
NotifyFilter::HeaderFetched(const entry_ref& ref, BFile* file)
{
// TODO: do not use MAIL:status here!
char statusString[256];
if (file->ReadAttr("MAIL:status", B_STRING_TYPE, 0, statusString, 256) < 0)
return;
@@ -59,17 +75,17 @@ NotifyFilter::HeaderFetched(const entry_ref& ref, BFile* file)
void
NotifyFilter::MailboxSynced(status_t status)
NotifyFilter::MailboxSynchronized(status_t status)
{
if (fNNewMessages == 0)
return;
if (fStrategy & do_beep)
if ((fStrategy & NOTIFY_BEEP) != 0)
system_beep("New E-mail");
if (fStrategy & alert) {
static BMessageFormat format(B_TRANSLATE(
"You have {0, plural, one{# new message} other{# new messages}} "
if ((fStrategy & NOTIFY_ALERT) != 0) {
BMessageFormat format(B_TRANSLATE(
"You have {0, plural, one{One new message} other{# new messages}} "
"for %account."));
BString text;
@@ -83,13 +99,13 @@ NotifyFilter::MailboxSynced(status_t status)
alert->Go(NULL);
}
if (fStrategy & blink_leds)
if ((fStrategy & NOTIFY_BLINK_LEDS) != 0)
be_app->PostMessage('mblk');
if (fStrategy & one_central_beep)
if ((fStrategy & NOTIFY_CENTRAL_BEEP) != 0)
be_app->PostMessage('mcbp');
if (fStrategy & big_doozy_alert) {
if ((fStrategy & NOTIFY_CENTRAL_ALERT) != 0) {
BMessage msg('numg');
msg.AddInt32("num_messages", fNNewMessages);
msg.AddString("name", fMailProtocol.AccountSettings().Name());
@@ -97,9 +113,9 @@ NotifyFilter::MailboxSynced(status_t status)
be_app->PostMessage(&msg);
}
if (fStrategy & log_window) {
static BMessageFormat format(B_TRANSLATE("{0, plural, "
"one{# new message} other{# new messages}}"));
if ((fStrategy & NOTIFY_NOTIFICATION) != 0) {
BMessageFormat format(B_TRANSLATE("{0, plural, "
"one{One new message} other{# new messages}}"));
BString message;
format.Format(message, fNNewMessages);
@@ -110,8 +126,18 @@ NotifyFilter::MailboxSynced(status_t status)
}
MailFilter*
instantiate_mailfilter(MailProtocol& protocol, AddonSettings* settings)
// #pragma mark -
BString
filter_name()
{
return B_TRANSLATE("New mails notification");
}
BMailFilter*
instantiate_filter(BMailProtocol& protocol, BMailAddOnSettings* settings)
{
return new NotifyFilter(protocol, settings);
}
@@ -4,113 +4,22 @@
* Copyright 2011, Clemens Zeidler <haiku@clemens-zeidler.de>
* Distributed under the terms of the MIT License.
*/
/******************************************************************************
* $Id: SpamFilter.cpp 29284 2009-02-22 13:45:40Z bga $
*
* 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.
*
* 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
*/
/*! 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.
*/
#include "SpamFilter.h"
#include <stdlib.h>
#include <stdio.h>
#include <Beep.h>
#include <Catalog.h>
@@ -123,76 +32,62 @@
#include <FindDirectory.h>
#include <Entry.h>
#include <stdlib.h>
#include <stdio.h>
#include "SpamFilter.h"
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "SpamFilter"
// The names match the ones set up by spamdbm for sound effects.
static const char *kAGMSBayesBeepGenuineName = "SpamFilter-Genuine";
static const char *kAGMSBayesBeepSpamName = "SpamFilter-Spam";
static const char *kAGMSBayesBeepUncertainName = "SpamFilter-Uncertain";
static const char* kAGMSBayesBeepGenuineName = "SpamFilter-Genuine";
static const char* kAGMSBayesBeepSpamName = "SpamFilter-Spam";
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,
AddonSettings* addonSettings)
SpamFilter::SpamFilter(BMailProtocol& protocol, BMailAddOnSettings* settings)
:
MailFilter(protocol, addonSettings),
fAddSpamToSubject(false),
fAutoTraining(true),
fGenuineCutoffRatio(0.01f),
fHeaderOnly(false),
fLaunchAttemptCount(0),
fNoWordsMeansSpam(true),
fQuitServerWhenFinished(false),
fSpamCutoffRatio(0.99f)
BMailFilter(protocol, settings)
{
bool tempBool;
float tempFloat;
BMessenger tempMessenger;
const BMessage* settings = &addonSettings->Settings();
if (settings != NULL) {
if (settings->FindBool ("AddMarkerToSubject", &tempBool) == B_OK)
fAddSpamToSubject = tempBool;
if (settings->FindBool ("AutoTraining", &tempBool) == B_OK)
fAutoTraining = tempBool;
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;
}
if (settings->FindBool("AddMarkerToSubject", &fAddSpamToSubject) != B_OK)
fAddSpamToSubject = false;
if (settings->FindBool("AutoTraining", &fAutoTraining) != B_OK)
fAutoTraining = true;
if (settings->FindFloat("GenuineCutoffRatio", &fGenuineCutoffRatio) != B_OK)
fGenuineCutoffRatio = 0.01f;
if (settings->FindBool("NoWordsMeansSpam", &fNoWordsMeansSpam) != B_OK)
fNoWordsMeansSpam = true;
if (settings->FindBool("QuitServerWhenFinished",
&fQuitServerWhenFinished) != B_OK)
fQuitServerWhenFinished = false;
if (settings->FindFloat("SpamCutoffRatio", &fSpamCutoffRatio) != B_OK)
fSpamCutoffRatio = 0.99f;
}
AGMSBayesianSpamFilter::~AGMSBayesianSpamFilter ()
SpamFilter::~SpamFilter()
{
if (fQuitServerWhenFinished && fMessengerToServer.IsValid ())
if (fQuitServerWhenFinished)
fMessengerToServer.SendMessage(B_QUIT_REQUESTED);
}
BString
SpamFilter::DescriptiveName() const
{
return filter_name();
}
void
AGMSBayesianSpamFilter::HeaderFetched(const entry_ref& ref, BFile* file)
SpamFilter::HeaderFetched(const entry_ref& ref, BFile* file)
{
_CheckForSpam(file);
}
void
AGMSBayesianSpamFilter::BodyFetched(const entry_ref& ref, BFile* file)
SpamFilter::BodyFetched(const entry_ref& ref, BFile* file)
{
if (fHeaderOnly)
return;
@@ -210,7 +105,7 @@ AGMSBayesianSpamFilter::BodyFetched(const entry_ref& ref, BFile* file)
status_t
AGMSBayesianSpamFilter::_CheckForSpam(BFile* file)
SpamFilter::_CheckForSpam(BFile* file)
{
// 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
@@ -231,7 +126,7 @@ AGMSBayesianSpamFilter::_CheckForSpam(BFile* file)
float spamRatio;
if (_GetSpamRatio(stringBuffer, dataSize, spamRatio) != B_OK)
return B_ERROR;
// If we are auto-training, feed back the message to the server as a
// training example (don't train if it is uncertain).
if (fAutoTraining && (spamRatio >= fSpamCutoffRatio
@@ -243,8 +138,8 @@ AGMSBayesianSpamFilter::_CheckForSpam(BFile* file)
// write attributes
const char *classificationString;
classificationString = (spamRatio >= fSpamCutoffRatio) ? "Spam"
: ((spamRatio < fGenuineCutoffRatio) ? "Genuine" : "Uncertain");
classificationString = spamRatio >= fSpamCutoffRatio ? "Spam"
: spamRatio < fGenuineCutoffRatio ? "Genuine" : "Uncertain";
file->WriteAttr("MAIL:classification", B_STRING_TYPE, 0 /* offset */,
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
// can turn it off in the system sound preferences.
if (spamRatio >= fSpamCutoffRatio) {
if (spamRatio >= fSpamCutoffRatio)
system_beep(kAGMSBayesBeepSpamName);
} else if (spamRatio < fGenuineCutoffRatio) {
else if (spamRatio < fGenuineCutoffRatio)
system_beep(kAGMSBayesBeepGenuineName);
} else {
else
system_beep(kAGMSBayesBeepUncertainName);
}
return B_OK;
}
status_t
AGMSBayesianSpamFilter::_CheckForSpamServer()
SpamFilter::_CheckForSpamServer()
{
// Make sure the server is running.
if (be_roster->IsRunning (kServerSignature))
return B_OK;
status_t errorCode = be_roster->Launch (kServerSignature);
if (errorCode == B_OK)
return errorCode;
status_t status = be_roster->Launch (kServerSignature);
if (status == B_OK)
return status;
BPath path;
entry_ref ref;
directory_which places[] = {
const directory_which kPlaces[] = {
B_SYSTEM_NONPACKAGED_BIN_DIRECTORY,
B_SYSTEM_BIN_DIRECTORY};
for (int32 i = 0; i < 2; i++) {
find_directory(places[i],&path);
for (size_t i = 0; i < sizeof(kPlaces) / sizeof(kPlaces[0]); i++) {
find_directory(kPlaces[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)
get_ref_for_path(path.Path(), &ref);
if ((status = be_roster->Launch(&ref)) == B_OK)
break;
}
return errorCode;
return status;
}
status_t
AGMSBayesianSpamFilter::_GetTokenizeMode()
SpamFilter::_GetTokenizeMode()
{
if (fLaunchAttemptCount > 3)
return B_ERROR; // Don't try to start the server too many times.
fLaunchAttemptCount++;
// Make sure the server is running.
status_t errorCode = _CheckForSpamServer();
if (errorCode != B_OK)
return errorCode;
status_t status = _CheckForSpamServer();
if (status != B_OK)
return status;
// Set up the messenger to the database server.
fMessengerToServer = BMessenger(kServerSignature);
if (!fMessengerToServer.IsValid ())
if (!fMessengerToServer.IsValid())
return B_ERROR;
// 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);
scriptingMessage.AddSpecifier("TokenizeMode");
BMessage replyMessage;
if ((errorCode = fMessengerToServer.SendMessage (&scriptingMessage,
&replyMessage)) != B_OK)
return errorCode;
status_t tempErrorCode;
if ((errorCode = replyMessage.FindInt32 ("error", &tempErrorCode))
!= B_OK)
return errorCode;
if ((errorCode = tempErrorCode) != B_OK)
if ((status = fMessengerToServer.SendMessage(&scriptingMessage,
&replyMessage)) != B_OK)
return status;
status_t errorCode;
if ((status = replyMessage.FindInt32("error", &errorCode)) != B_OK)
return status;
if (errorCode != B_OK)
return errorCode;
const char *tokenizeModeStringPntr;
if ((errorCode = replyMessage.FindString ("result",
&tokenizeModeStringPntr)) != B_OK)
return errorCode;
fHeaderOnly = (tokenizeModeStringPntr != NULL
&& strcmp (tokenizeModeStringPntr, "JustHeader") == 0);
const char* tokenizeMode;
if ((status = replyMessage.FindString("result", &tokenizeMode)) != B_OK)
return status;
fHeaderOnly = tokenizeMode != NULL && !strcmp(tokenizeMode, "JustHeader");
return B_OK;
}
status_t
AGMSBayesianSpamFilter::_GetSpamRatio(const char* stringBuffer, off_t dataSize,
SpamFilter::_GetSpamRatio(const char* stringBuffer, off_t dataSize,
float& ratio)
{
// 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
AGMSBayesianSpamFilter::_TrainServer(const char* stringBuffer, off_t dataSize,
SpamFilter::_TrainServer(const char* stringBuffer, off_t dataSize,
float spamRatio)
{
BMessage scriptingMessage(B_SET_PROPERTY);
@@ -401,7 +293,7 @@ AGMSBayesianSpamFilter::_TrainServer(const char* stringBuffer, off_t dataSize,
status_t
AGMSBayesianSpamFilter::_AddSpamToSubject(BNode* file, float spamRatio)
SpamFilter::_AddSpamToSubject(BNode* file, float spamRatio)
{
attr_info info;
if (file->GetAttrInfo("Subject", &info) != B_OK)
@@ -414,7 +306,7 @@ AGMSBayesianSpamFilter::_AddSpamToSubject(BNode* file, float spamRatio)
delete[] buffer;
return B_ERROR;
}
BString newSubjectString;
newSubjectString.SetTo("[Spam ");
char percentageString[30];
@@ -431,15 +323,18 @@ AGMSBayesianSpamFilter::_AddSpamToSubject(BNode* file, float spamRatio)
}
// #pragma mark -
BString
descriptive_name()
filter_name()
{
return B_TRANSLATE("Spam Filter (AGMS Bayesian)");
return B_TRANSLATE("Bayesian Spam Filter");
}
MailFilter*
instantiate_mailfilter(MailProtocol& protocol, AddonSettings* settings)
BMailFilter*
instantiate_filter(BMailProtocol& protocol, BMailAddOnSettings* settings)
{
return new AGMSBayesianSpamFilter(protocol, settings);
return new SpamFilter(protocol, settings);
}
@@ -4,96 +4,29 @@
* Copyright 2011, Clemens Zeidler <haiku@clemens-zeidler.de>
* Distributed under the terms of the MIT License.
*/
#ifndef AGMS_BAYESIAN_SPAM_FILTER_H
#define AGMS_BAYESIAN_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>
#ifndef SPAM_FILTER_H
#define SPAM_FILTER_H
class AGMSBayesianSpamFilter : public MailFilter {
#include <MailFilter.h>
#include <Messenger.h>
class SpamFilter : public BMailFilter {
public:
AGMSBayesianSpamFilter(MailProtocol& protocol,
AddonSettings* settings);
~AGMSBayesianSpamFilter();
SpamFilter(BMailProtocol& protocol,
BMailAddOnSettings* settings);
virtual ~SpamFilter();
void HeaderFetched(const entry_ref& ref, BFile* file);
void BodyFetched(const entry_ref& ref, BFile* file);
virtual BString DescriptiveName() const;
virtual void HeaderFetched(const entry_ref& ref,
BFile* file);
virtual void BodyFetched(const entry_ref& ref, BFile* file);
private:
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 _GetTokenizeMode();
status_t _GetSpamRatio(const char* data, off_t dataSize,
@@ -102,6 +35,7 @@ private:
float spamRatio);
status_t _AddSpamToSubject(BNode* file, float spamRatio);
private:
bool fAddSpamToSubject;
bool fAutoTraining;
float fGenuineCutoffRatio;
@@ -113,4 +47,5 @@ private:
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 $
*
* SpamFilter's configuration view. Lets the user change various settings
* 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
/*
* Copyright 2004-2012, Haiku, Inc. All rights reserved.
* Copyright 2002 Alexander G. M. Smith.
* Distributed under the terms of the MIT License.
*/
/*! SpamFilter's configuration view. Lets the user change various settings
related to the add-on, but not the spamdbm server.
*/
#include <stdlib.h>
#include <stdio.h>
@@ -82,6 +17,7 @@
#include <Button.h>
#include <Catalog.h>
#include <CheckBox.h>
#include <LayoutBuilder.h>
#include <Message.h>
#include <Messenger.h>
#include <Roster.h>
@@ -91,7 +27,7 @@
#include <Entry.h>
#include <Path.h>
#include <MailAddon.h>
#include <MailFilter.h>
#include <FileConfigView.h>
@@ -99,342 +35,120 @@
#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 {
public:
AGMSBayesianSpamFilterConfig (const BMessage *settings);
virtual status_t Archive(BMessage* into, bool deep = true) const;
virtual void MessageReceived (BMessage *msg);
virtual void AttachedToWindow ();
virtual status_t Archive (BMessage *into, bool deep = true) const;
virtual void GetPreferredSize (float *width, float *height);
private:
void ShowSpamServerConfigurationWindow ();
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';
private:
BCheckBox* fSubjectHintCheckBox;
BCheckBox* fAutoTrainingCheckBox;
float fGenuineCutoffRatio;
BTextControl* fGenuineCutoffRatioTextControl;
BCheckBox* fNoWordsMeansSpamCheckBox;
float fSpamCutoffRatio;
BTextControl* fSpamCutoffRatioTextControl;
};
AGMSBayesianSpamFilterConfig::AGMSBayesianSpamFilterConfig(
const BMessage *settings)
: BView (BRect (0,0,260,130), "spamfilter_config",
B_FOLLOW_LEFT | B_FOLLOW_TOP, 0),
fAddSpamToSubject (false),
fAddSpamToSubjectCheckBoxPntr (NULL),
fAutoTraining (true),
fAutoTrainingCheckBoxPntr (NULL),
fGenuineCutoffRatio (0.01f),
fGenuineCutoffRatioTextBoxPntr (NULL),
fNoWordsMeansSpam (true),
fNoWordsMeansSpamCheckBoxPntr (NULL),
fQuitServerWhenFinished (true),
fQuitServerWhenFinishedCheckBoxPntr (NULL),
fServerSettingsButtonPntr (NULL),
fSpamCutoffRatio (0.99f),
fSpamCutoffRatioTextBoxPntr (NULL)
SpamFilterConfig::SpamFilterConfig(const BMessage* settings)
:
BView("spamfilter_config", 0),
fSubjectHintCheckBox(NULL),
fAutoTrainingCheckBox(NULL),
fGenuineCutoffRatioTextControl(NULL),
fNoWordsMeansSpamCheckBox(NULL),
fSpamCutoffRatioTextControl(NULL)
{
bool tempBool;
float tempFloat;
bool subjectHint;
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)
fAddSpamToSubject = tempBool;
if (settings->FindBool ("AutoTraining", &tempBool) == B_OK)
fAutoTraining = tempBool;
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;
}
if (settings->FindFloat("GenuineCutoffRatio", &fGenuineCutoffRatio) != B_OK)
fGenuineCutoffRatio = 0.01f;
if (settings->FindFloat("SpamCutoffRatio", &fSpamCutoffRatio) != B_OK)
fSpamCutoffRatio = 0.99f;
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
void AGMSBayesianSpamFilterConfig::AttachedToWindow ()
{
char numberString [30];
BRect tempRect;
const char *tempStringPntr;
fSubjectHintCheckBox = new BCheckBox("AddToSubject",
B_TRANSLATE("Add spam rating to start of subject"), NULL);
fSubjectHintCheckBox->SetValue(subjectHint);
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
// modification to the subject of the mail message.
fNoWordsMeansSpamCheckBox = new BCheckBox("NoWordsMeansSpam",
B_TRANSLATE("or empty e-mail"), NULL);
fNoWordsMeansSpamCheckBox->SetValue(noWordsMeansSpam);
tempRect = Bounds ();
fAddSpamToSubjectCheckBoxPntr = new BCheckBox (
tempRect,
"AddToSubject",
B_TRANSLATE("Add spam rating to start of subject"),
new BMessage (kAddSpamToSubjectPressed));
AddChild (fAddSpamToSubjectCheckBoxPntr);
fAddSpamToSubjectCheckBoxPntr->ResizeToPreferred ();
fAddSpamToSubjectCheckBoxPntr->SetValue (fAddSpamToSubject);
fAddSpamToSubjectCheckBoxPntr->SetTarget (this);
number.SetToFormat("%08.6f", (double)fGenuineCutoffRatio);
fGenuineCutoffRatioTextControl = new BTextControl("genuinecutoffratio",
B_TRANSLATE("Genuine below and uncertain above:"),
number.String(), NULL);
tempRect = Bounds ();
tempRect.top = fAddSpamToSubjectCheckBoxPntr->Frame().bottom + 1;
tempRect.bottom = tempRect.top + 20;
fAutoTrainingCheckBox = new BCheckBox("autoTraining",
B_TRANSLATE("Learn from all incoming e-mail"), NULL);
fAutoTrainingCheckBox->SetValue(autoTraining);
// Add the checkbox on the right for the no words means spam option.
fNoWordsMeansSpamCheckBoxPntr = new BCheckBox (
tempRect,
"NoWordsMeansSpam",
B_TRANSLATE("or empty e-mail"),
new BMessage (kNoWordsMeansSpam));
AddChild (fNoWordsMeansSpamCheckBoxPntr);
fNoWordsMeansSpamCheckBoxPntr->ResizeToPreferred ();
fNoWordsMeansSpamCheckBoxPntr->MoveBy (
floorf (tempRect.right - fNoWordsMeansSpamCheckBoxPntr->Frame().right),
0.0);
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;
*/
BLayoutBuilder::Group<>(this, B_VERTICAL)
.Add(fSubjectHintCheckBox)
.AddGroup(B_HORIZONTAL)
.Add(fSpamCutoffRatioTextControl->CreateLabelLayoutItem())
.Add(fSpamCutoffRatioTextControl->CreateTextViewLayoutItem())
.Add(fNoWordsMeansSpamCheckBox)
.End()
.AddGroup(B_HORIZONTAL)
.Add(fGenuineCutoffRatioTextControl->CreateLabelLayoutItem())
.Add(fGenuineCutoffRatioTextControl->CreateTextViewLayoutItem())
.End()
.Add(fAutoTrainingCheckBox);
}
status_t
AGMSBayesianSpamFilterConfig::Archive (BMessage *into, bool deep) const
SpamFilterConfig::Archive(BMessage* into, bool /*deep*/) const
{
status_t errorCode;
float tempFloat;
into->MakeEmpty();
errorCode = into->AddBool ("AddMarkerToSubject", fAddSpamToSubject);
if (errorCode == B_OK)
errorCode = into->AddBool ("AutoTraining", fAutoTraining);
status_t status = into->AddBool("AddMarkerToSubject",
fSubjectHintCheckBox->Value() == B_CONTROL_ON);
if (errorCode == B_OK)
errorCode = into->AddBool ("QuitServerWhenFinished", fQuitServerWhenFinished);
if (errorCode == B_OK)
errorCode = into->AddBool ("NoWordsMeansSpam", fNoWordsMeansSpam);
if (errorCode == B_OK) {
tempFloat = fGenuineCutoffRatio;
if (fGenuineCutoffRatioTextBoxPntr != NULL)
tempFloat = atof (fGenuineCutoffRatioTextBoxPntr->Text());
errorCode = into->AddFloat ("GenuineCutoffRatio", tempFloat);
if (status == B_OK) {
status = into->AddBool("AutoTraining",
fAutoTrainingCheckBox->Value() == B_CONTROL_ON);
}
if (status == B_OK) {
status = into->AddBool("NoWordsMeansSpam",
fNoWordsMeansSpamCheckBox->Value() == B_CONTROL_ON);
}
if (status == B_OK) {
status = into->AddFloat("GenuineCutoffRatio",
atof(fGenuineCutoffRatioTextControl->Text()));
}
if (status == B_OK) {
status = into->AddFloat("SpamCutoffRatio",
atof(fSpamCutoffRatioTextControl->Text()));
}
if (errorCode == B_OK) {
tempFloat = fSpamCutoffRatio;
if (fSpamCutoffRatioTextBoxPntr != NULL)
tempFloat = atof (fSpamCutoffRatioTextBoxPntr->Text());
errorCode = into->AddFloat ("SpamCutoffRatio", tempFloat);
}
return errorCode;
return status;
}
void
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;
}
// #pragma mark -
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 2011, Clemens Zeidler <haiku@clemens-zeidler.de>
*
@@ -9,10 +9,11 @@
#include <Button.h>
#include <Catalog.h>
#include <GridLayout.h>
#include <Path.h>
#include <TextControl.h>
#include <MailAddon.h>
#include <Path.h>
#include <MailFilter.h>
#include <FileConfigView.h>
#include <ProtocolConfigView.h>
@@ -25,31 +26,32 @@
#define B_TRANSLATION_CONTEXT "imap_config"
using namespace BPrivate;
const uint32 kMsgOpenIMAPFolder = '&OIF';
class ConfigView : public BMailProtocolConfigView {
class ConfigView : public MailProtocolConfigView {
public:
ConfigView(MailAddonSettings& settings,
BMailAccountSettings& accountSettings);
ConfigView(BMailAccountSettings& settings);
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 AttachedToWindow();
private:
BMailFileConfigView* fFileView;
BButton* fIMAPFolderButton;
MailAddonSettings& fAddonSettings;
MailFileConfigView* fFileView;
BButton* fFolderButton;
BMailProtocolSettings& fSettings;
};
ConfigView::ConfigView(MailAddonSettings& settings,
BMailAccountSettings& accountSettings)
ConfigView::ConfigView(BMailAccountSettings& settings)
:
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_CAN_LEAVE_MAIL_ON_SERVER
| B_MAIL_PROTOCOL_PARTIAL_DOWNLOAD
@@ -57,39 +59,31 @@ ConfigView::ConfigView(MailAddonSettings& settings,
| B_MAIL_PROTOCOL_HAS_FLAVORS
#endif
),
fAddonSettings(settings)
fSettings(settings.InboundSettings())
{
#ifdef USE_SSL
AddFlavor(B_TRANSLATE("No encryption"));
AddFlavor(B_TRANSLATE("SSL"));
#endif
SetTo(settings);
SetTo(settings.InboundSettings());
((BControl*)(FindView("leave_mail_on_server")))->SetValue(B_CONTROL_ON);
((BControl*)(FindView("leave_mail_on_server")))->Hide();
BRect frame = FindView("delete_remote_when_local")->Frame();
((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(
fFolderButton = new BButton("IMAP Folders", B_TRANSLATE(
"IMAP Folders"), new BMessage(kMsgOpenIMAPFolder));
AddChild(fIMAPFolderButton);
frame.right -= 10;
Layout()->AddView(fFolderButton, 0, Layout()->CountRows(), 2);
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());
fFileView->SetTo(&settings.Settings(), NULL);
AddChild(fFileView);
fFileView->MoveBy(0, frame.bottom + 5);
fFileView->SetTo(&settings.InboundSettings(), NULL);
ResizeToPreferred();
Layout()->AddView(fFileView, 0, Layout()->CountRows(),
Layout()->CountColumns());
}
@@ -99,18 +93,10 @@ ConfigView::~ConfigView()
status_t
ConfigView::Archive(BMessage *into, bool deep) const
ConfigView::Archive(BMessage* into, bool deep) const
{
fFileView->Archive(into, deep);
return BMailProtocolConfigView::Archive(into, deep);
}
void
ConfigView::GetPreferredSize(float *width, float *height)
{
BMailProtocolConfigView::GetPreferredSize(width,height);
*height -= 20;
return MailProtocolConfigView::Archive(into, deep);
}
@@ -129,7 +115,7 @@ ConfigView::MessageReceived(BMessage* message)
}
default:
BMailProtocolConfigView::MessageReceived(message);
MailProtocolConfigView::MessageReceived(message);
}
}
@@ -137,7 +123,7 @@ ConfigView::MessageReceived(BMessage* message)
void
ConfigView::AttachedToWindow()
{
fIMAPFolderButton->SetTarget(this);
fFolderButton->SetTarget(this);
}
@@ -145,8 +131,7 @@ ConfigView::AttachedToWindow()
BView*
instantiate_config_panel(MailAddonSettings& settings,
BMailAccountSettings& accountSettings)
instantiate_protocol_config_panel(BMailAccountSettings& settings)
{
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 2011, Clemens Zeidler <haiku@clemens-zeidler.de>
*
@@ -8,8 +8,10 @@
#include <Catalog.h>
#include <GridLayout.h>
#include <MailFilter.h>
#include <FileConfigView.h>
#include <MailAddon.h>
#include <MailPrivate.h>
#include <ProtocolConfigView.h>
@@ -18,21 +20,22 @@
#define B_TRANSLATION_CONTEXT "ConfigView"
class POP3ConfigView : public BMailProtocolConfigView {
using namespace BPrivate;
class POP3ConfigView : public MailProtocolConfigView {
public:
POP3ConfigView(MailAddonSettings& settings,
BMailAccountSettings& accountSettings);
status_t Archive(BMessage *into, bool deep = true) const;
void GetPreferredSize(float *width, float *height);
POP3ConfigView(BMailAccountSettings& settings);
status_t Archive(BMessage* into, bool deep = true) const;
private:
BMailFileConfigView* fFileView;
MailFileConfigView* fFileView;
};
POP3ConfigView::POP3ConfigView(MailAddonSettings& settings,
BMailAccountSettings& accountSettings)
POP3ConfigView::POP3ConfigView(BMailAccountSettings& settings)
:
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_HOSTNAME
| B_MAIL_PROTOCOL_CAN_LEAVE_MAIL_ON_SERVER
@@ -50,40 +53,30 @@ POP3ConfigView::POP3ConfigView(MailAddonSettings& settings,
AddFlavor(B_TRANSLATE("SSL"));
#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());
fFileView->SetTo(&settings.Settings(), NULL);
AddChild(fFileView);
float w, h;
BMailProtocolConfigView::GetPreferredSize(&w, &h);
fFileView->MoveBy(0, h - 10);
GetPreferredSize(&w, &h);
ResizeTo(w, h);
fFileView->SetTo(&settings.InboundSettings(), NULL);
Layout()->AddView(fFileView, 0, Layout()->CountRows(),
Layout()->CountColumns());
}
status_t
POP3ConfigView::Archive(BMessage *into, bool deep) const
POP3ConfigView::Archive(BMessage* into, bool deep) const
{
fFileView->Archive(into, deep);
return BMailProtocolConfigView::Archive(into, deep);
return MailProtocolConfigView::Archive(into, deep);
}
void
POP3ConfigView::GetPreferredSize(float* width, float* height)
{
BMailProtocolConfigView::GetPreferredSize(width, height);
*height += 20;
}
// #pragma mark -
BView*
instantiate_config_panel(MailAddonSettings& settings,
BMailAccountSettings& accountSettings)
instantiate_protocol_config_panel(BMailAccountSettings& settings)
{
return new POP3ConfigView(settings, accountSettings);
return new POP3ConfigView(settings);
}
@@ -65,15 +65,15 @@ NotHere(BStringList& that, BStringList& otherList, BStringList* results)
// #pragma mark -
POP3Protocol::POP3Protocol(BMailAccountSettings* settings)
POP3Protocol::POP3Protocol(const BMailAccountSettings& settings)
:
InboundProtocol(settings),
BInboundMailProtocol(settings),
fNumMessages(-1),
fMailDropSize(0),
fServerConnection(NULL)
{
printf("POP3Protocol::POP3Protocol(BMailAccountSettings* settings)\n");
fSettings = fAccountSettings.InboundSettings().Settings();
fSettings = fAccountSettings.InboundSettings();
fUseSSL = fSettings.FindInt32("flavor") == 1 ? true : false;
@@ -145,13 +145,15 @@ POP3Protocol::SyncMessages()
SetTotalItems(2);
ReportProgress(0, 1, B_TRANSLATE("Connect to server" B_UTF8_ELLIPSIS));
status_t error = Connect();
if (error < B_OK) {
if (error != B_OK) {
ResetProgress();
return error;
}
ReportProgress(0, 1, B_TRANSLATE("Getting UniqueIDs" B_UTF8_ELLIPSIS));
error = _RetrieveUniqueIDs();
if (error < B_OK) {
ResetProgress();
@@ -256,11 +258,11 @@ POP3Protocol::FetchBody(const entry_ref& ref)
SetTotalItems(1);
status_t error = Connect();
if (error < B_OK)
if (error != B_OK)
return error;
error = _RetrieveUniqueIDs();
if (error < B_OK) {
if (error != B_OK) {
Disconnect();
return error;
}
@@ -354,14 +356,10 @@ POP3Protocol::Open(const char* server, int port, int)
fLog = "";
// Prime the error message
BString error_msg, servString;
error_msg << B_TRANSLATE("Error while connecting to server %serv");
servString << server;
error_msg.ReplaceFirst("%serv", servString);
BString errorMessage(B_TRANSLATE("Error while connecting to server %serv"));
errorMessage.ReplaceFirst("%serv", server);
if (port != 110)
error_msg << ":" << port;
errorMessage << ":" << port;
uint32 hostIP = inet_addr(server);
// 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) {
error_msg << B_TRANSLATE(": Connection refused or host not found");
ShowError(error_msg.String());
errorMessage << B_TRANSLATE(": Connection refused or host not found");
ShowError(errorMessage.String());
return B_NAME_NOT_FOUND;
}
@@ -397,19 +395,19 @@ POP3Protocol::Open(const char* server, int port, int)
if (err < 0) {
fServerConnection->Disconnect();
error_msg << ": " << strerror(err);
ShowError(error_msg.String());
errorMessage << ": " << strerror(err);
ShowError(errorMessage.String());
return B_ERROR;
}
if (strncmp(line.String(), "+OK", 3) != 0) {
if (line.Length() > 0) {
error_msg << B_TRANSLATE(". The server said:\n")
errorMessage << B_TRANSLATE(". The server said:\n")
<< line.String();
} else
error_msg << B_TRANSLATE(": No reply.\n");
errorMessage << B_TRANSLATE(": No reply.\n");
ShowError(error_msg.String());
ShowError(errorMessage.String());
fServerConnection->Disconnect();
return B_ERROR;
}
@@ -877,11 +875,9 @@ POP3Protocol::_RetrieveUniqueIDs()
{
fUniqueIDs.MakeEmpty();
status_t ret = B_OK;
ret = SendCommand("UIDL" CRLF);
if (ret != B_OK)
return ret;
status_t status = SendCommand("UIDL" CRLF);
if (status != B_OK)
return status;
BString result;
int32 uidOffset;
@@ -897,20 +893,20 @@ POP3Protocol::_RetrieveUniqueIDs()
if (SendCommand("LIST" CRLF) != B_OK)
return B_ERROR;
int32 b;
while (ReceiveLine(result) > 0) {
if (result.ByteAt(0) == '.')
break;
b = result.FindLast(" ");
if (b >= 0)
b = atol(&(result.String()[b]));
int32 index = result.FindLast(" ");
int32 size;
if (index >= 0)
size = atol(&result.String()[index]);
else
b = 0;
fSizes.AddItem((void *)(addr_t)b);
size = 0;
fSizes.AddItem((void*)size);
}
return ret;
return B_OK;
}
@@ -975,15 +971,15 @@ POP3Protocol::_WriteManifest()
// #pragma mark -
InboundProtocol*
instantiate_inbound_protocol(BMailAccountSettings* settings)
BInboundMailProtocol*
instantiate_inbound_protocol(const BMailAccountSettings& settings)
{
return new POP3Protocol(settings);
}
status_t
pop3_smtp_auth(BMailAccountSettings* settings)
pop3_smtp_auth(const BMailAccountSettings& settings)
{
POP3Protocol protocol(settings);
protocol.Connect();
@@ -15,20 +15,20 @@
#include <DataIO.h>
#include <List.h>
#include <String.h>
#include <StringList.h>
#include <View.h>
#include "MailAddon.h"
#include "MailProtocol.h"
#include "MailSettings.h"
#include <StringList.h>
#include <MailProtocol.h>
#include <MailSettings.h>
class BSocket;
class POP3Protocol : public InboundProtocol {
class POP3Protocol : public BInboundMailProtocol {
public:
POP3Protocol(BMailAccountSettings* settings);
POP3Protocol(
const BMailAccountSettings& settings);
~POP3Protocol();
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 */
@@ -1,18 +1,19 @@
/*
* Copyright 2007-2011, Haiku, Inc. All rights reserved.
* Copyright 2001-2002 Dr. Zoidberg Enterprises. All rights reserved.
* Copyright 2007-2012, Haiku, Inc. All rights reserved.
* Copyright 2001-2002, Dr. Zoidberg Enterprises. All rights reserved.
* Copyright 2011, Clemens Zeidler <haiku@clemens-zeidler.de>
*
* Distributed under the terms of the MIT License.
*/
#include <Catalog.h>
#include <GridLayout.h>
#include <MailFilter.h>
#include <MenuField.h>
#include <TextControl.h>
#include <Catalog.h>
#include <FileConfigView.h>
#include <MailAddon.h>
#include <MenuField.h>
#include <MailPrivate.h>
#include <ProtocolConfigView.h>
@@ -21,21 +22,24 @@
#define B_TRANSLATION_CONTEXT "ConfigView"
class SMTPConfigView : public BMailProtocolConfigView {
using namespace BPrivate;
class SMTPConfigView : public MailProtocolConfigView {
public:
SMTPConfigView(MailAddonSettings& settings,
BMailAccountSettings& accountSettings);
status_t Archive(BMessage *into, bool deep = true) const;
void GetPreferredSize(float *width, float *height);
SMTPConfigView(BMailAccountSettings& settings);
status_t Archive(BMessage* into,
bool deep = true) const;
private:
BMailFileConfigView* fFileView;
MailFileConfigView* fFileView;
};
SMTPConfigView::SMTPConfigView(MailAddonSettings& settings,
BMailAccountSettings& accountSettings)
SMTPConfigView::SMTPConfigView(BMailAccountSettings& settings)
:
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_HOSTNAME
#ifdef USE_SSL
@@ -57,58 +61,33 @@ SMTPConfigView::SMTPConfigView(MailAddonSettings& settings,
AddAuthMethod(B_TRANSLATE("ESMTP"));
AddAuthMethod(B_TRANSLATE("POP3 before SMTP"), false);
BTextControl *control = (BTextControl *)(FindView("host"));
BTextControl* control = (BTextControl*)FindView("host");
control->SetLabel(B_TRANSLATE("SMTP server:"));
// Reset the dividers after changing one
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);
}
SetTo(settings.OutboundSettings());
BMenuField *field = (BMenuField *)(FindView("auth_method"));
field->SetDivider(widestLabel);
SetTo(settings);
fFileView = new BMailFileConfigView(B_TRANSLATE("Destination:"), "path",
fFileView = new MailFileConfigView(B_TRANSLATE("Destination:"), "path",
false, BPrivate::default_mail_out_directory().Path());
fFileView->SetTo(&settings.Settings(), NULL);
AddChild(fFileView);
float w, h;
BMailProtocolConfigView::GetPreferredSize(&w, &h);
fFileView->MoveBy(0, h - 10);
GetPreferredSize(&w, &h);
ResizeTo(w, h);
fFileView->SetTo(&settings.OutboundSettings(), NULL);
Layout()->AddView(fFileView, 0, Layout()->CountRows(),
Layout()->CountColumns());
}
status_t
SMTPConfigView::Archive(BMessage *into, bool deep) const
SMTPConfigView::Archive(BMessage* into, bool deep) const
{
fFileView->Archive(into, deep);
return BMailProtocolConfigView::Archive(into, deep);
return MailProtocolConfigView::Archive(into, deep);
}
void
SMTPConfigView::GetPreferredSize(float* width, float* height)
{
BMailProtocolConfigView::GetPreferredSize(width, height);
*width += 20;
*height += 20;
}
// #pragma mark -
BView*
instantiate_config_panel(MailAddonSettings& settings,
BMailAccountSettings& accountSettings)
instantiate_protocol_config_panel(BMailAccountSettings& settings)
{
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 2011, Clemens Zeidler <haiku@clemens-zeidler.de>
*
@@ -63,6 +63,16 @@
# define D(x) ;
#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;
/*
@@ -233,34 +243,27 @@ SplitChallengeIntoMap(BString str, map<BString,BString>& m)
}
// Authentication types recognized. Not all methods are implemented.
enum AuthType {
LOGIN = 1,
PLAIN = 1 << 2,
CRAM_MD5 = 1 << 3,
DIGEST_MD5 = 1 << 4
};
// #pragma mark -
SMTPProtocol::SMTPProtocol(BMailAccountSettings* settings)
SMTPProtocol::SMTPProtocol(BMailAccountSettings& settings)
:
OutboundProtocol(settings),
BOutboundMailProtocol(settings),
fAuthType(0)
{
fSettingsMessage = settings->OutboundSettings().Settings();
fSettingsMessage = settings.OutboundSettings();
}
SMTPProtocol::~SMTPProtocol()
{
}
status_t
SMTPProtocol::Connect()
{
BString error_msg;
BString errorMessage;
int32 authMethod = fSettingsMessage.FindInt32("auth_method");
status_t status = B_ERROR;
@@ -271,9 +274,9 @@ SMTPProtocol::Connect()
// to the SMTP server first...
status_t status = _POP3Authentication();
if (status < B_OK) {
error_msg << B_TRANSLATE("POP3 authentication failed. The server "
"said:\n") << fLog;
ShowError(error_msg.String());
errorMessage << B_TRANSLATE("POP3 authentication failed. The "
"server said:\n") << fLog;
ShowError(errorMessage.String());
return status;
}
}
@@ -281,19 +284,22 @@ SMTPProtocol::Connect()
status = Open(fSettingsMessage.FindString("server"),
fSettingsMessage.FindInt32("port"), authMethod == 1);
if (status < B_OK) {
error_msg << B_TRANSLATE("Error while opening connection to %serv");
error_msg.ReplaceFirst("%serv", fSettingsMessage.FindString("server"));
errorMessage << B_TRANSLATE("Error while opening connection to %serv");
errorMessage.ReplaceFirst("%serv",
fSettingsMessage.FindString("server"));
if (fSettingsMessage.FindInt32("port") > 0)
error_msg << ":" << fSettingsMessage.FindInt32("port");
errorMessage << ":" << fSettingsMessage.FindInt32("port");
// << strerror(err) - BNetEndpoint sucks, we can't use this;
if (fLog.Length() > 0)
error_msg << B_TRANSLATE(". The server says:\n") << fLog;
else
error_msg << B_TRANSLATE(": Connection refused or host not found.");
errorMessage << B_TRANSLATE(". The server says:\n") << fLog;
else {
errorMessage
<< B_TRANSLATE(": Connection refused or host not found.");
}
ShowError(error_msg.String());
ShowError(errorMessage.String());
return status;
}
@@ -303,13 +309,12 @@ SMTPProtocol::Connect()
delete[] password;
if (status != B_OK) {
//-----This is a really cool kind of error message. How can we make it work for POP3?
error_msg << B_TRANSLATE("Error while logging in to %serv")
errorMessage << B_TRANSLATE("Error while logging in to %serv")
<< B_TRANSLATE(". The server said:\n") << fLog;
errorMessage.ReplaceFirst("%serv",
fSettingsMessage.FindString("server"));
error_msg.ReplaceFirst("%serv", fSettingsMessage.FindString("server"));
ShowError(error_msg.String());
ShowError(errorMessage.String());
}
return B_OK;
}
@@ -549,23 +554,23 @@ SMTPProtocol::_SendMessage(const entry_ref& mail)
status_t
SMTPProtocol::_POP3Authentication()
{
const entry_ref& entry = fAccountSettings.InboundPath();
const entry_ref& entry = fAccountSettings.InboundAddOnRef();
if (strcmp(entry.name, "POP3") != 0)
return B_ERROR;
status_t (*pop3_smtp_auth)(BMailAccountSettings*);
status_t (*pop3_smtp_auth)(const BMailAccountSettings&);
BPath path(&entry);
image_id image = load_add_on(path.Path());
if (image < 0)
return B_ERROR;
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);
image = -1;
return B_ERROR;
}
status_t status = (*pop3_smtp_auth)(&fAccountSettings);
status_t status = (*pop3_smtp_auth)(fAccountSettings);
unload_add_on(image);
return status;
}
@@ -1047,8 +1052,8 @@ SMTPProtocol::SendCommand(const char *cmd)
// #pragma mark -
OutboundProtocol*
instantiate_outbound_protocol(BMailAccountSettings* settings)
BOutboundMailProtocol*
instantiate_outbound_protocol(BMailAccountSettings& 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 2011, Clemens Zeidler <haiku@clemens-zeidler.de>
*
@@ -11,20 +11,19 @@
#include <String.h>
#include <MailAddon.h>
#include <MailFilter.h>
#include <MailProtocol.h>
#include <MailSettings.h>
#ifdef USE_SSL
# include <openssl/ssl.h>
# include <openssl/rand.h>
#endif
class SMTPProtocol : public OutboundProtocol {
class SMTPProtocol : public BOutboundMailProtocol {
public:
SMTPProtocol(BMailAccountSettings* settings);
SMTPProtocol(BMailAccountSettings& settings);
~SMTPProtocol();
status_t Connect();
@@ -33,7 +32,6 @@ public:
status_t SendMessages(const std::vector<entry_ref>&
mails, size_t totalBytes);
//----Perfectly good holdovers from the old days
status_t Open(const char *server, int port, bool esmtp);
void Close();
status_t Login(const char *uid, const char *password);
@@ -53,12 +51,12 @@ private:
int32 fAuthType;
#ifdef USE_SSL
SSL_CTX *ctx;
SSL *ssl;
BIO *sbio;
SSL_CTX* ctx;
SSL* ssl;
BIO* sbio;
bool use_ssl;
bool use_STARTTLS;
bool use_ssl;
bool use_STARTTLS;
#endif
status_t fStatus;
+46 -74
View File
@@ -1,99 +1,81 @@
/* BMailFileConfigView - a file configuration view for filters
**
** Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved.
*/
/*
* Copyright 2004-2012, Haiku, Inc. 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 <Button.h>
#include <Catalog.h>
#include <GroupLayout.h>
#include <Message.h>
#include <Path.h>
#include <String.h>
#include <TextControl.h>
#include <FileConfigView.h>
class _EXPORT BFileControl;
class _EXPORT BMailFileConfigView;
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "MailKit"
const uint32 kMsgSelectButton = 'fsel';
static const uint32 kMsgSelectButton = 'fsel';
BFileControl::BFileControl(BRect rect, const char* name, const char* label,
const char *pathOfFile,uint32 flavors)
namespace BPrivate {
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));
SetLayout(new BGroupLayout(B_HORIZONTAL));
// determine font height
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);
fText = new BTextControl("file_path", label, pathOfFile, NULL);
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));
fButton->ResizeToPreferred();
fButton->MoveBy(rect.right + 6,
(rect.Height() - fButton->Frame().Height()) / 2);
AddChild(fButton);
fPanel = new BFilePanel(B_OPEN_PANEL, NULL, NULL, flavors, false);
ResizeToPreferred();
}
BFileControl::~BFileControl()
FileControl::~FileControl()
{
delete fPanel;
}
void
BFileControl::AttachedToWindow()
FileControl::AttachedToWindow()
{
fButton->SetTarget(this);
BMessenger messenger(this);
if (messenger.IsValid())
fPanel->SetTarget(messenger);
fPanel->SetTarget(this);
}
void
BFileControl::MessageReceived(BMessage* msg)
FileControl::MessageReceived(BMessage* msg)
{
switch (msg->what)
{
switch (msg->what) {
case kMsgSelectButton:
{
fPanel->Hide();
//fPanel->Window()->SetTitle(title);
BPath path(fText->Text());
if (path.InitCheck() >= B_OK)
if (path.GetParent(&path) >= B_OK)
fPanel->SetPanelDirectory(path.Path());
if (path.InitCheck() == B_OK && path.GetParent(&path) == B_OK)
fPanel->SetPanelDirectory(path.Path());
fPanel->Show();
break;
@@ -101,11 +83,9 @@ BFileControl::MessageReceived(BMessage* msg)
case B_REFS_RECEIVED:
{
entry_ref ref;
if (msg->FindRef("refs", &ref) >= B_OK)
{
if (msg->FindRef("refs", &ref) == B_OK) {
BEntry entry(&ref);
if (entry.InitCheck() >= B_OK)
{
if (entry.InitCheck() == B_OK) {
BPath path;
entry.GetPath(&path);
@@ -114,6 +94,7 @@ BFileControl::MessageReceived(BMessage* msg)
}
break;
}
default:
BView::MessageReceived(msg);
break;
@@ -122,42 +103,34 @@ BFileControl::MessageReceived(BMessage* msg)
void
BFileControl::SetText(const char* pathOfFile)
FileControl::SetText(const char* pathOfFile)
{
fText->SetText(pathOfFile);
}
const char*
BFileControl::Text() const
FileControl::Text() const
{
return fText->Text();
}
void
BFileControl::SetEnabled(bool enabled)
FileControl::SetEnabled(bool enabled)
{
fText->SetEnabled(enabled);
fButton->SetEnabled(enabled);
}
void
BFileControl::GetPreferredSize(float* width, float* height)
{
*width = fButton->Frame().right + 5;
*height = fText->Bounds().Height() + 8;
}
//--------------------------------------------------------------------------
// #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)
:
BFileControl(BRect(5, 0, 255, 10), name, label, defaultPath, flavors),
FileControl(name, label, defaultPath, flavors),
fUseMeta(useMeta),
fName(name)
{
@@ -165,24 +138,23 @@ BMailFileConfigView::BMailFileConfigView(const char* label, const char*name,
void
BMailFileConfigView::SetTo(const BMessage* archive, BMessage* meta)
MailFileConfigView::SetTo(const BMessage* archive, BMessage* meta)
{
SetText((fUseMeta ? meta : archive)->FindString(fName));
fMeta = meta;
BString path = (fUseMeta ? meta : archive)->FindString(fName);
if (path != "")
SetText(path.String());
}
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;
if (archive->ReplaceString(fName,path) != B_OK)
archive->AddString(fName,path);
if (archive->ReplaceString(fName, Text()) != B_OK)
archive->AddString(fName, Text());
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 <haiku@clemens-zeidler.de>
* Copyright 2001-2003 Dr. Zoidberg Enterprises. All rights reserved.
*
* Distributed under the terms of the MIT License.
*/
@@ -76,15 +77,23 @@ sanitize_white_space(BString& string)
// #pragma mark -
HaikuMailFormatFilter::HaikuMailFormatFilter(MailProtocol& protocol,
BMailAccountSettings* settings)
HaikuMailFormatFilter::HaikuMailFormatFilter(BMailProtocol& protocol,
const BMailAccountSettings& settings)
:
MailFilter(protocol, NULL),
fAccountID(settings->AccountID()),
fAccountName(settings->Name())
BMailFilter(protocol, NULL),
fAccountID(settings.AccountID()),
fAccountName(settings.Name())
{
const BMessage* outboundSettings = &settings->OutboundSettings().Settings();
outboundSettings->FindString("destination", &fOutboundDirectory);
const BMessage& outboundSettings = settings.OutboundSettings();
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()) {
create_directory(fOutboundDirectory, 755);
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 <haiku@clemens-zeidler.de>
* Distributed under the terms of the MIT License.
*/
@@ -7,22 +7,23 @@
#define IMAP_LISTENER_H
#include "MailProtocol.h"
#include <MailFilter.h>
#include <String.h>
class HaikuMailFormatFilter : public MailFilter {
class HaikuMailFormatFilter : public BMailFilter {
public:
HaikuMailFormatFilter(MailProtocol& protocol,
BMailAccountSettings* settings);
HaikuMailFormatFilter(BMailProtocol& protocol,
const BMailAccountSettings& settings);
virtual BString DescriptiveName() const;
void HeaderFetched(const entry_ref& ref,
BFile* file);
void BodyFetched(const entry_ref& ref, BFile* file);
void MessageSent(const entry_ref& ref,
BFile* file);
void MessageSent(const entry_ref& ref, BFile* file);
private:
status_t _SetFileName(const entry_ref& ref,
const BString& name);
+1
View File
@@ -25,6 +25,7 @@ local sources =
MailComponent.cpp
MailContainer.cpp
MailDaemon.cpp
MailFilter.cpp
MailMessage.cpp
MailProtocol.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 2007, 2010, Haiku Inc. All Rights Reserved.
*
* Distributed under the terms of the MIT License.
*/
//! The main general purpose mail message class
@@ -926,8 +927,7 @@ BEmailMessage::Send(bool sendNow)
}
BString path;
if (account->OutboundSettings().Settings().FindString("path", &path)
!= B_OK) {
if (account->OutboundSettings().FindString("path", &path) != B_OK) {
BPath defaultMailOutPath;
if (find_directory(B_USER_DIRECTORY, &defaultMailOutPath) != 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.
*/
//#include <assert.h>
#include <stdio.h>
#include <fs_attr.h>
#include <stdlib.h>
#include <assert.h>
#include <fs_attr.h>
#include <Alert.h>
#include <Directory.h>
#include <FindDirectory.h>
#include <Query.h>
#include <E-mail.h>
#include <Locker.h>
#include <Node.h>
#include <NodeInfo.h>
#include <NodeMonitor.h>
#include <Path.h>
#include <Query.h>
#include <Roster.h>
#include <String.h>
#include <StringList.h>
#include <VolumeRoster.h>
#include <mail_util.h>
#include <MailAddon.h>
#include <MailFilter.h>
#include <MailDaemon.h>
#include <MailProtocol.h>
#include <MailSettings.h>
#include <mail_util.h>
#include "HaikuMailFormatFilter.h"
@@ -48,64 +51,16 @@ const uint32 kMsgInit = '&Ini';
const uint32 kMsgSendMessage = '&SeM';
MailFilter::MailFilter(MailProtocol& protocol, AddonSettings* settings)
BMailProtocol::BMailProtocol(const BMailAccountSettings& settings)
:
fMailProtocol(protocol),
fAddonSettings(settings)
fAccountSettings(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));
}
MailProtocol::~MailProtocol()
BMailProtocol::~BMailProtocol()
{
delete fMailNotifier;
@@ -118,205 +73,118 @@ MailProtocol::~MailProtocol()
}
BMailAccountSettings&
MailProtocol::AccountSettings()
const BMailAccountSettings&
BMailProtocol::AccountSettings() const
{
return fAccountSettings;
}
void
MailProtocol::SetProtocolThread(MailProtocolThread* protocolThread)
{
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)
BMailProtocol::SetMailNotifier(BMailNotifier* mailNotifier)
{
delete fMailNotifier;
fMailNotifier = mailNotifier;
}
void
MailProtocol::ShowError(const char* error)
BMailNotifier*
BMailProtocol::MailNotifier() const
{
if (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);
return fMailNotifier;
}
bool
MailProtocol::AddFilter(MailFilter* filter)
BMailProtocol::AddFilter(BMailFilter* filter)
{
BLocker locker(this);
return fFilterList.AddItem(filter);
}
int32
MailProtocol::CountFilter()
BMailProtocol::CountFilter() const
{
BLocker locker(this);
return fFilterList.CountItems();
}
MailFilter*
MailProtocol::FilterAt(int32 index)
BMailFilter*
BMailProtocol::FilterAt(int32 index) const
{
BLocker locker(this);
return fFilterList.ItemAt(index);
}
MailFilter*
MailProtocol::RemoveFilter(int32 index)
BMailFilter*
BMailProtocol::RemoveFilter(int32 index)
{
BLocker locker(this);
return fFilterList.RemoveItemAt(index);
}
bool
MailProtocol::RemoveFilter(MailFilter* filter)
BMailProtocol::RemoveFilter(BMailFilter* filter)
{
BLocker locker(this);
return fFilterList.RemoveItem(filter);
}
void
MailProtocol::NotifyNewMessagesToFetch(int32 nMessages)
BMailProtocol::MessageReceived(BMessage* message)
{
ResetProgress();
SetTotalItems(nMessages);
}
switch (message->what) {
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
MailProtocol::NotifyHeaderFetched(const entry_ref& ref, BFile* data)
{
for (int i = 0; i < fFilterList.CountItems(); i++)
fFilterList.ItemAt(i)->HeaderFetched(ref, data);
}
case kMsgFileRenamed:
{
entry_ref from;
message->FindRef("from", &from);
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
MailProtocol::NotifyBodyFetched(const entry_ref& ref, BFile* data)
{
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);
default:
BLooper::MessageReceived(message);
}
}
status_t
MailProtocol::MoveMessage(const entry_ref& ref, BDirectory& dir)
BMailProtocol::MoveMessage(const entry_ref& ref, BDirectory& dir)
{
BEntry entry(&ref);
return entry.MoveTo(&dir);
@@ -324,7 +192,7 @@ MailProtocol::MoveMessage(const entry_ref& ref, BDirectory& dir)
status_t
MailProtocol::DeleteMessage(const entry_ref& ref)
BMailProtocol::DeleteMessage(const entry_ref& ref)
{
BEntry entry(&ref);
return entry.Remove();
@@ -332,36 +200,122 @@ MailProtocol::DeleteMessage(const entry_ref& ref)
void
MailProtocol::FileRenamed(const entry_ref& from, const entry_ref& to)
BMailProtocol::FileRenamed(const entry_ref& from, const entry_ref& to)
{
}
void
MailProtocol::FileDeleted(const node_ref& node)
BMailProtocol::FileDeleted(const node_ref& node)
{
}
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++) {
AddonSettings* filterSettings = settings.FilterSettingsAt(i);
MailFilter* filter = _LoadFilter(filterSettings);
if (!filter)
continue;
AddFilter(filter);
BMailAddOnSettings* filterSettings = settings.FilterSettingsAt(i);
BMailFilter* filter = _LoadFilter(filterSettings);
if (filter != NULL)
AddFilter(filter);
}
}
MailFilter*
MailProtocol::_LoadFilter(AddonSettings* filterSettings)
BMailFilter*
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);
image_id image;
if (it != fFilterImages.end())
@@ -374,209 +328,42 @@ MailProtocol::_LoadFilter(AddonSettings* filterSettings)
if (image < 0)
return NULL;
MailFilter* (*instantiate_mailfilter)(MailProtocol& protocol,
AddonSettings* settings);
if (get_image_symbol(image, "instantiate_mailfilter",
B_SYMBOL_TYPE_TEXT, (void **)&instantiate_mailfilter)
!= B_OK) {
BMailFilter* (*instantiate_filter)(BMailProtocol& protocol,
BMailAddOnSettings* settings);
if (get_image_symbol(image, "instantiate_filter", B_SYMBOL_TYPE_TEXT,
(void**)&instantiate_filter) != B_OK) {
unload_add_on(image);
return NULL;
}
fFilterImages[ref] = image;
return (*instantiate_mailfilter)(*this, filterSettings);
return (*instantiate_filter)(*this, filterSettings);
}
// #pragma mark -
InboundProtocol::InboundProtocol(BMailAccountSettings* settings)
BInboundMailProtocol::BInboundMailProtocol(const BMailAccountSettings& settings)
:
MailProtocol(settings)
BMailProtocol(settings)
{
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
MailProtocolThread::SetStopNow()
{
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)
BInboundMailProtocol::MessageReceived(BMessage* message)
{
switch (message->what) {
case kMsgSyncMessages:
{
status_t status = fProtocol->SyncMessages();
_NotiyMailboxSynced(status);
NotiyMailboxSynchronized(SyncMessages());
break;
}
@@ -584,7 +371,7 @@ InboundProtocolThread::MessageReceived(BMessage* message)
{
entry_ref ref;
message->FindRef("ref", &ref);
status_t status = fProtocol->FetchBody(ref);
status_t status = FetchBody(ref);
BMessenger target;
if (message->FindMessenger("target", &target) != B_OK)
@@ -602,7 +389,7 @@ InboundProtocolThread::MessageReceived(BMessage* message)
entry_ref ref;
message->FindRef("ref", &ref);
read_flags read = (read_flags)message->FindInt32("read");
fProtocol->MarkMessageAsRead(ref, read);
MarkMessageAsRead(ref, read);
break;
}
@@ -610,7 +397,7 @@ InboundProtocolThread::MessageReceived(BMessage* message)
{
entry_ref ref;
message->FindRef("ref", &ref);
fProtocol->DeleteMessage(ref);
DeleteMessage(ref);
break;
}
@@ -618,91 +405,59 @@ InboundProtocolThread::MessageReceived(BMessage* message)
{
entry_ref ref;
message->FindRef("ref", &ref);
fProtocol->AppendMessage(ref);
AppendMessage(ref);
break;
}
default:
MailProtocolThread::MessageReceived(message);
BMailProtocol::MessageReceived(message);
break;
}
}
void
InboundProtocolThread::SyncMessages()
status_t
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
InboundProtocolThread::FetchBody(const entry_ref& ref, BMessenger* listener)
BInboundMailProtocol::NotiyMailboxSynchronized(status_t status)
{
BMessage message(kMsgFetchBody);
message.AddRef("ref", &ref);
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);
for (int32 i = 0; i < CountFilter(); i++)
FilterAt(i)->MailboxSynchronized(status);
}
// #pragma mark -
OutboundProtocolThread::OutboundProtocolThread(OutboundProtocol* protocol)
BOutboundMailProtocol::BOutboundMailProtocol(
const BMailAccountSettings& settings)
:
MailProtocolThread(protocol),
fProtocol(protocol)
BMailProtocol(settings)
{
LoadFilters(fAccountSettings.OutboundSettings());
}
OutboundProtocolThread::~OutboundProtocolThread()
BOutboundMailProtocol::~BOutboundMailProtocol()
{
fProtocol->SetProtocolThread(NULL);
}
void
OutboundProtocolThread::MessageReceived(BMessage* message)
BOutboundMailProtocol::MessageReceived(BMessage* message)
{
switch (message->what) {
case kMsgSendMessage:
@@ -715,23 +470,11 @@ OutboundProtocolThread::MessageReceived(BMessage* message)
mails.push_back(ref);
}
size_t size = message->FindInt32("size");
fProtocol->SendMessages(mails, size);
SendMessages(mails, size);
break;
}
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 2004-2011, Haiku Inc. All rights reserved.
*
* Distributed under the terms of the MIT License.
*/
@@ -419,177 +419,196 @@ BMailAccounts::AccountByName(const char* name)
// #pragma mark -
AddonSettings::AddonSettings()
:
fModified(false)
BMailAddOnSettings::BMailAddOnSettings()
{
}
bool
AddonSettings::Load(const BMessage& message)
BMailAddOnSettings::~BMailAddOnSettings()
{
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
AddonSettings::Save(BMessage& message)
status_t
BMailAddOnSettings::Load(const BMessage& message)
{
BPath path(&fAddonRef);
message.AddString("add-on path", path.Path());
message.AddMessage("settings", &fSettings);
fModified = false;
return true;
const char* path = NULL;
if (message.FindString("add-on path", &path) != B_OK)
return B_BAD_VALUE;
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
AddonSettings::SetAddonRef(const entry_ref& ref)
BMailAddOnSettings::SetAddOnRef(const entry_ref& ref)
{
fAddonRef = ref;
fRef = ref;
}
const entry_ref&
AddonSettings::AddonRef() const
BMailAddOnSettings::AddOnRef() const
{
return fAddonRef;
}
const BMessage&
AddonSettings::Settings() const
{
return fSettings;
}
BMessage&
AddonSettings::EditSettings()
{
fModified = true;
return fSettings;
return fRef;
}
bool
AddonSettings::HasBeenModified()
BMailAddOnSettings::HasBeenModified() const
{
return fModified;
return fRef != fOriginalRef
|| !fOriginalSettings.HasSameData(*this, true, true);
}
// #pragma mark -
bool
MailAddonSettings::Load(const BMessage& message)
BMailProtocolSettings::BMailProtocolSettings()
:
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;
int32 countFound;
message.GetInfo("filters", &typeFound, &countFound);
if (typeFound != B_MESSAGE_TYPE)
return false;
return B_BAD_VALUE;
for (int i = 0; i < countFound; i++) {
int32 index = AddFilterSettings();
AddonSettings& filterSettings = fFiltersSettings[index];
if (index < 0)
return B_NO_MEMORY;
BMailAddOnSettings* filterSettings = fFiltersSettings.ItemAt(index);
BMessage filterMessage;
message.FindMessage("filters", i, &filterMessage);
if (!filterSettings.Load(filterMessage))
if (filterSettings->Load(filterMessage) != B_OK)
RemoveFilterSettings(index);
}
return true;
return B_OK;
}
bool
MailAddonSettings::Save(BMessage& message)
status_t
BMailProtocolSettings::Save(BMessage& message)
{
if (!AddonSettings::Save(message))
return false;
status_t status = BMailAddOnSettings::Save(message);
if (status != B_OK)
return status;
for (int i = 0; i < CountFilterSettings(); i++) {
BMessage filter;
AddonSettings& filterSettings = fFiltersSettings[i];
filterSettings.Save(filter);
BMailAddOnSettings* filterSettings = fFiltersSettings.ItemAt(i);
filterSettings->Save(filter);
message.AddMessage("filters", &filter);
}
return true;
return B_OK;
}
int32
MailAddonSettings::CountFilterSettings()
BMailProtocolSettings::CountFilterSettings() const
{
return fFiltersSettings.size();
return fFiltersSettings.CountItems();
}
int32
MailAddonSettings::AddFilterSettings(const entry_ref* ref)
BMailProtocolSettings::AddFilterSettings(const entry_ref* ref)
{
AddonSettings filterSettings;
BMailAddOnSettings* filterSettings = new BMailAddOnSettings();
if (ref != NULL)
filterSettings.SetAddonRef(*ref);
fFiltersSettings.push_back(filterSettings);
return fFiltersSettings.size() - 1;
filterSettings->SetAddOnRef(*ref);
if (fFiltersSettings.AddItem(filterSettings))
return fFiltersSettings.CountItems() - 1;
delete filterSettings;
return -1;
}
void
BMailProtocolSettings::RemoveFilterSettings(int32 index)
{
fFiltersSettings.RemoveItemAt(index);
}
bool
MailAddonSettings::RemoveFilterSettings(int32 index)
BMailProtocolSettings::MoveFilterSettings(int32 from, int32 to)
{
fFiltersSettings.erase(fFiltersSettings.begin() + index);
return true;
}
bool
MailAddonSettings::MoveFilterSettings(int32 from, int32 to)
{
if (from < 0 || from >= (int32)fFiltersSettings.size() || to < 0
|| to >= (int32)fFiltersSettings.size())
if (from < 0 || from >= (int32)CountFilterSettings() || to < 0
|| to >= (int32)CountFilterSettings())
return false;
AddonSettings fromSettings = fFiltersSettings[from];
fFiltersSettings.erase(fFiltersSettings.begin() + from);
if (to == (int32)fFiltersSettings.size())
fFiltersSettings.push_back(fromSettings);
else {
std::vector<AddonSettings>::iterator it = fFiltersSettings.begin() + to;
fFiltersSettings.insert(it, fromSettings);
}
if (from == to)
return true;
BMailAddOnSettings* settings = fFiltersSettings.RemoveItemAt(from);
fFiltersSettings.AddItem(settings, to);
return true;
}
AddonSettings*
MailAddonSettings::FilterSettingsAt(int32 index)
BMailAddOnSettings*
BMailProtocolSettings::FilterSettingsAt(int32 index) const
{
if (index < 0 || index >= (int32)fFiltersSettings.size())
return NULL;
return &fFiltersSettings[index];
return fFiltersSettings.ItemAt(index);
}
bool
MailAddonSettings::HasBeenModified()
BMailProtocolSettings::HasBeenModified() const
{
if (AddonSettings::HasBeenModified())
if (BMailAddOnSettings::HasBeenModified())
return true;
for (unsigned int i = 0; i < fFiltersSettings.size(); i++) {
if (fFiltersSettings[i].HasBeenModified())
for (int32 i = 0; i < CountFilterSettings(); i++) {
if (FilterSettingsAt(i)->HasBeenModified())
return true;
}
return false;
@@ -634,7 +653,7 @@ BMailAccountSettings::SetAccountID(int32 id)
int32
BMailAccountSettings::AccountID()
BMailAccountSettings::AccountID() const
{
return fAccountID;
}
@@ -686,7 +705,7 @@ BMailAccountSettings::ReturnAddress() const
bool
BMailAccountSettings::SetInboundAddon(const char* name)
BMailAccountSettings::SetInboundAddOn(const char* name)
{
BPath path;
status_t status = find_directory(B_BEOS_ADDONS_DIRECTORY, &path);
@@ -697,15 +716,14 @@ BMailAccountSettings::SetInboundAddon(const char* name)
path.Append(name);
entry_ref ref;
get_ref_for_path(path.Path(), &ref);
fInboundSettings.SetAddonRef(ref);
fInboundSettings.SetAddOnRef(ref);
fModified = true;
return true;
}
bool
BMailAccountSettings::SetOutboundAddon(const char* name)
BMailAccountSettings::SetOutboundAddOn(const char* name)
{
BPath path;
status_t status = find_directory(B_BEOS_ADDONS_DIRECTORY, &path);
@@ -716,52 +734,65 @@ BMailAccountSettings::SetOutboundAddon(const char* name)
path.Append(name);
entry_ref ref;
get_ref_for_path(path.Path(), &ref);
fOutboundSettings.SetAddonRef(ref);
fOutboundSettings.SetAddOnRef(ref);
fModified = true;
return true;
}
const entry_ref&
BMailAccountSettings::InboundPath() const
BMailAccountSettings::InboundAddOnRef() const
{
return fInboundSettings.AddonRef();
return fInboundSettings.AddOnRef();
}
const entry_ref&
BMailAccountSettings::OutboundPath() const
BMailAccountSettings::OutboundAddOnRef() const
{
return fOutboundSettings.AddonRef();
return fOutboundSettings.AddOnRef();
}
MailAddonSettings&
BMailProtocolSettings&
BMailAccountSettings::InboundSettings()
{
return fInboundSettings;
}
MailAddonSettings&
const BMailProtocolSettings&
BMailAccountSettings::InboundSettings() const
{
return fInboundSettings;
}
BMailProtocolSettings&
BMailAccountSettings::OutboundSettings()
{
return fOutboundSettings;
}
const BMailProtocolSettings&
BMailAccountSettings::OutboundSettings() const
{
return fOutboundSettings;
}
bool
BMailAccountSettings::HasInbound()
{
return BEntry(&fInboundSettings.AddonRef()).Exists();
return BEntry(&fInboundSettings.AddOnRef()).Exists();
}
bool
BMailAccountSettings::HasOutbound()
{
return BEntry(&fOutboundSettings.AddonRef()).Exists();
return BEntry(&fOutboundSettings.AddOnRef()).Exists();
}
@@ -870,18 +901,16 @@ BMailAccountSettings::Delete()
bool
BMailAccountSettings::HasBeenModified()
BMailAccountSettings::HasBeenModified() const
{
if (fInboundSettings.HasBeenModified())
return true;
if (fOutboundSettings.HasBeenModified())
return true;
return fModified;
return fModified
|| fInboundSettings.HasBeenModified()
|| fOutboundSettings.HasBeenModified();
}
const BEntry&
BMailAccountSettings::AccountFile()
BMailAccountSettings::AccountFile() const
{
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.
* Distributed under the terms of the MIT License.
*/
@@ -15,6 +15,7 @@
#include <Catalog.h>
#include <CheckBox.h>
#include <GridLayout.h>
#include <MenuField.h>
#include <MenuItem.h>
#include <Message.h>
@@ -29,7 +30,14 @@
#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()
@@ -62,13 +70,11 @@ BodyDownloadConfig::BodyDownloadConfig()
void
BodyDownloadConfig::SetTo(MailAddonSettings& addonSettings)
BodyDownloadConfig::SetTo(BMailProtocolSettings& settings)
{
const BMessage* settings = &addonSettings.Settings();
int32 limit = 0;
if (settings->HasInt32(kPartialDownloadLimit))
limit = settings->FindInt32(kPartialDownloadLimit);
if (settings.HasInt32(kPartialDownloadLimit))
limit = settings.FindInt32(kPartialDownloadLimit);
if (limit < 0) {
fPartialBox->SetValue(B_CONTROL_OFF);
fSizeBox->SetText("0");
@@ -122,375 +128,303 @@ BodyDownloadConfig::Archive(BMessage* into, bool) const
}
namespace {
//--------------------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 "";
}
// #pragma mark -
BTextControl *
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)
MailProtocolConfigView::MailProtocolConfigView(uint32 optionsMask)
:
BView (BRect(0,0,100,20), "protocol_config_view", B_FOLLOW_LEFT
| B_FOLLOW_TOP, B_WILL_DRAW),
BView("protocol_config_view", B_WILL_DRAW),
fHostControl(NULL),
fUserControl(NULL),
fPasswordControl(NULL),
fLeaveOnServerCheckBox(NULL),
fRemoveFromServerCheckBox(NULL),
fBodyDownloadConfig(NULL)
{
BRect rect(5,5,245,25);
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
// determine font height
font_height fontHeight;
GetFontHeight(&fontHeight);
sItemHeight = (int32)(fontHeight.ascent + fontHeight.descent + fontHeight.leading) + 13;
rect.bottom = rect.top - 2 + sItemHeight;
BGridLayout* layout = new BGridLayout();
SetLayout(layout);
if (options_mask & B_MAIL_PROTOCOL_HAS_HOSTNAME)
AddChild(AddTextField(rect, "host", B_TRANSLATE("Mail server:")));
if ((optionsMask & B_MAIL_PROTOCOL_HAS_HOSTNAME) != 0) {
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)
AddChild(AddTextField(rect, "user", B_TRANSLATE("Username:")));
if (options_mask & B_MAIL_PROTOCOL_HAS_PASSWORD) {
BTextControl *control = AddTextField(rect, "pass",
if ((optionsMask & B_MAIL_PROTOCOL_HAS_PASSWORD) != 0) {
fPasswordControl = _AddTextControl(layout, "pass",
B_TRANSLATE("Password:"));
control->TextView()->HideTyping(true);
AddChild(control);
fPasswordControl->TextView()->HideTyping(true);
}
if (options_mask & B_MAIL_PROTOCOL_HAS_FLAVORS)
AddChild(AddMenuField(rect, "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 ((optionsMask & B_MAIL_PROTOCOL_HAS_FLAVORS) != 0) {
fFlavorField = _AddMenuField(layout, "flavor",
B_TRANSLATE("Connection type:"));
}
if (options_mask & B_MAIL_PROTOCOL_CAN_LEAVE_MAIL_ON_SERVER) {
AddChild(AddCheckBox(rect, "leave_mail_on_server",
B_TRANSLATE("Leave mail on server"), new BMessage('lmos')));
BCheckBox* box = AddCheckBox(rect, "delete_remote_when_local",
B_TRANSLATE("Remove mail from server when deleted"));
box->SetEnabled(false);
AddChild(box);
if ((optionsMask & B_MAIL_PROTOCOL_HAS_AUTH_METHODS) != 0) {
fAuthenticationField = _AddMenuField(layout, "auth_method",
B_TRANSLATE("Login type:"));
}
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->MoveBy(0, rect.bottom + 5);
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());
layout->AddView(fBodyDownloadConfig, 0, layout->CountRows(), 2);
}
}
BMailProtocolConfigView::~BMailProtocolConfigView()
MailProtocolConfigView::~MailProtocolConfigView()
{
}
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 (archive->HasInt32("port"))
host << ':' << archive->FindInt32("port");
if (fHostControl != NULL)
fHostControl->SetText(host.String());
if (fUserControl != NULL)
fUserControl->SetText(settings.FindString("username"));
SetTextControl(this,"host", host.String());
SetTextControl(this,"user", archive->FindString("username"));
if (fPasswordControl != NULL) {
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 (password) {
SetTextControl(this,"pass", password);
delete[] password;
} else
SetTextControl(this,"pass", archive->FindString("password"));
if (settings.HasInt32("flavor") && fFlavorField != NULL) {
if (BMenuItem* item = fFlavorField->Menu()->ItemAt(
settings.FindInt32("flavor")))
item->SetMarked(true);
}
if (archive->HasInt32("flavor")) {
BMenuField *menu = (BMenuField *)(FindView("flavor"));
if (menu != NULL) {
if (BMenuItem *item = menu->Menu()->ItemAt(archive->FindInt32("flavor")))
item->SetMarked(true);
if (settings.HasInt32("auth_method") && fAuthenticationField != NULL) {
if (BMenuItem* item = fAuthenticationField->Menu()->ItemAt(
settings.FindInt32("auth_method"))) {
item->SetMarked(true);
_SetCredentialsEnabled(item->Command() != kMsgNoPassword);
}
}
if (archive->HasInt32("auth_method")) {
BMenuField *menu = (BMenuField *)(FindView("auth_method"));
if (menu != NULL) {
if (BMenuItem *item = menu->Menu()->ItemAt(archive->FindInt32("auth_method"))) {
item->SetMarked(true);
if (item->Command() != 'none') {
enable_control("user");
enable_control("pass");
}
}
}
if (fLeaveOnServerCheckBox != NULL) {
fLeaveOnServerCheckBox->SetValue(settings.FindBool(
"leave_mail_on_server") ? B_CONTROL_ON : B_CONTROL_OFF);
}
BCheckBox *box = (BCheckBox *)(FindView("leave_mail_on_server"));
if (box != NULL)
box->SetValue(archive->FindBool("leave_mail_on_server") ? B_CONTROL_ON : B_CONTROL_OFF);
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 (fRemoveFromServerCheckBox != NULL) {
fRemoveFromServerCheckBox->SetValue(settings.FindBool(
"delete_remote_when_local") ? B_CONTROL_ON : B_CONTROL_OFF);
fRemoveFromServerCheckBox->SetEnabled(
settings.FindBool("leave_mail_on_server"));
}
if (fBodyDownloadConfig)
if (fBodyDownloadConfig != NULL)
fBodyDownloadConfig->SetTo(settings);
}
void
BMailProtocolConfigView::AddFlavor(const char *label)
MailProtocolConfigView::AddFlavor(const char* label)
{
BMenuField *menu = (BMenuField *)(FindView("flavor"));
if (menu != NULL) {
menu->Menu()->AddItem(new BMenuItem(label,NULL));
if (menu->Menu()->FindMarked() == NULL)
menu->Menu()->ItemAt(0)->SetMarked(true);
if (fFlavorField != NULL) {
fFlavorField->Menu()->AddItem(new BMenuItem(label, NULL));
if (fFlavorField->Menu()->FindMarked() == NULL)
fFlavorField->Menu()->ItemAt(0)->SetMarked(true);
}
}
void
BMailProtocolConfigView::AddAuthMethod(const char *label,bool needUserPassword)
MailProtocolConfigView::AddAuthMethod(const char* label, bool needUserPassword)
{
BMenuField *menu = (BMenuField *)(FindView("auth_method"));
if (menu != NULL) {
BMenuItem *item = new BMenuItem(label,new BMessage(needUserPassword ? 'some' : 'none'));
if (fAuthenticationField != NULL) {
fAuthenticationField->Menu()->AddItem(new BMenuItem(label,
new BMessage(needUserPassword
? kMsgLeaveOnServer : kMsgNoPassword)));
menu->Menu()->AddItem(item);
if (menu->Menu()->FindMarked() == NULL) {
menu->Menu()->ItemAt(0)->SetMarked(true);
MessageReceived(menu->Menu()->ItemAt(0)->Message());
if (fAuthenticationField->Menu()->FindMarked() == NULL) {
BMenuItem* item = fAuthenticationField->Menu()->ItemAt(0);
item->SetMarked(true);
MessageReceived(item->Message());
}
}
}
void
BMailProtocolConfigView::AttachedToWindow()
BGridLayout*
MailProtocolConfigView::Layout() const
{
BMenuField *menu = (BMenuField *)(FindView("auth_method"));
if (menu != NULL)
menu->Menu()->SetTargetForItems(this);
BCheckBox *box = (BCheckBox *)(FindView("leave_mail_on_server"));
if (box != NULL)
box->SetTarget(this);
return (BGridLayout*)BView::GetLayout();
}
void
BMailProtocolConfigView::MessageReceived(BMessage *msg)
MailProtocolConfigView::AttachedToWindow()
{
switch (msg->what) {
case 'some':
enable_control("user");
enable_control("pass");
if (fAuthenticationField != NULL)
fAuthenticationField->Menu()->SetTargetForItems(this);
if (fLeaveOnServerCheckBox != NULL)
fLeaveOnServerCheckBox->SetTarget(this);
}
void
MailProtocolConfigView::MessageReceived(BMessage* message)
{
switch (message->what) {
case kMsgNeedPassword:
_SetCredentialsEnabled(true);
break;
case 'none':
disable_control("user");
disable_control("pass");
case kMsgNoPassword:
_SetCredentialsEnabled(false);
break;
case 'lmos':
if (msg->FindInt32("be:value") == 1) {
enable_control("delete_remote_when_local");
} else {
disable_control("delete_remote_when_local");
}
case kMsgLeaveOnServer:
fRemoveFromServerCheckBox->SetEnabled(
message->FindInt32("be:value") == B_CONTROL_ON);
break;
}
}
status_t
BMailProtocolConfigView::Archive(BMessage *into, bool deep) const
MailProtocolConfigView::Archive(BMessage* into, bool deep) const
{
const char *host = TextControl((BView *)this,"host");
int32 port = -1;
BString host_name = host;
if (host_name.FindFirst(':') > -1) {
port = atol(host_name.String() + host_name.FindFirst(':') + 1);
host_name.Truncate(host_name.FindFirst(':'));
if (fHostControl != NULL) {
int32 port = -1;
BString hostName = fHostControl->Text();
if (hostName.FindFirst(':') > -1) {
port = atol(hostName.String() + hostName.FindFirst(':') + 1);
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)
into->AddString("server",host_name.String());
// since there is no need for the port option, remove it here
into->RemoveName("port");
if (port != -1)
into->AddInt32("port",port);
if (into->ReplaceString("username",TextControl((BView *)this,"user")) != B_OK)
into->AddString("username",TextControl((BView *)this,"user"));
if (fUserControl != NULL) {
if (into->ReplaceString("username", fUserControl->Text()) != B_OK)
into->AddString("username", fUserControl->Text());
} else
into->RemoveName("username");
// remove old unencrypted passwords
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;
int32 index = -1;
_StoreIndexOfMarked(*into, "flavor", fFlavorField);
_StoreIndexOfMarked(*into, "auth_method", fAuthenticationField);
if ((field = (BMenuField *)(FindView("flavor"))) != NULL) {
BMenuItem *item = field->Menu()->FindMarked();
if (item != NULL)
index = field->Menu()->IndexOf(item);
}
_StoreCheckBox(*into, "leave_mail_on_server", fLeaveOnServerCheckBox);
_StoreCheckBox(*into, "delete_remote_when_local",
fRemoveFromServerCheckBox);
if (into->ReplaceInt32("flavor",index) != B_OK)
into->AddInt32("flavor",index);
if (fBodyDownloadConfig != NULL)
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;
}
void
BMailProtocolConfigView::GetPreferredSize(float *width, float *height)
BTextControl*
MailProtocolConfigView::_AddTextControl(BGridLayout* layout, const char* name,
const char* label)
{
float minWidth = 250;
if (BView *view = FindView("delete_remote_when_local")) {
float ignore;
view->GetPreferredSize(&minWidth,&ignore);
}
if (minWidth < 250)
minWidth = 250;
*width = minWidth + 10;
*height = (CountChildren() * sItemHeight) + 5;
BTextControl* control = new BTextControl(name, label, "", NULL);
int32 row = layout->CountRows();
layout->AddItem(control->CreateLabelLayoutItem(), 0, row);
layout->AddItem(control->CreateTextViewLayoutItem(), 1, row);
return control;
}
if (fBodyDownloadConfig) {
float bodyW, bodyH;
fBodyDownloadConfig->GetPreferredSize(&bodyW, &bodyH);
*height+= bodyH;
BMenuField*
MailProtocolConfigView::_AddMenuField(BGridLayout* layout, const char* name,
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);
if (err < B_OK)
return err;
if (incoming_count != NULL)
*incoming_count = BMailDaemon::CountNewMessages(true);
return B_OK;
}
@@ -74,20 +74,19 @@ get_pop_account(mail_pop_account* account, int32 index)
if (accountSettings == NULL)
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_host, settings.FindString("server"));
strcpy(account->real_name, accountSettings->RealName());
strcpy(account->reply_to, accountSettings->ReturnAddress());
const char *password, *passwd;
password = settings.FindString("password");
passwd = get_passwd(&settings, "cpasswd");
if (passwd)
password = passwd;
const char* encryptedPassword = get_passwd(&settings, "cpasswd");
const char* password = encryptedPassword;
if (password == NULL)
password = settings.FindString("password");
strcpy(account->pop_password, password);
free((char *)passwd);
delete[] encryptedPassword;
return B_OK;
}
@@ -107,14 +106,13 @@ get_smtp_host(char* buffer)
BMailSettings().DefaultOutboundAccount());
if (account == NULL)
return B_ERROR;
const BMessage& settings = account->OutboundSettings().Settings();
if (settings.HasString("server"))
strcpy(buffer,settings.FindString("server"));
else
const BMessage& settings = account->OutboundSettings();
if (!settings.HasString("server"))
return B_NAME_NOT_FOUND;
strcpy(buffer, settings.FindString("server"));
return B_OK;
}
@@ -136,6 +134,6 @@ forward_mail(entry_ref *ref, const char *recipients, bool now)
BEmailMessage mail(&file);
mail.SetTo(recipients);
return mail.Send(now);
}