Major restructuring of the mail server:
Accounts are now stored in a separate file. Previously they where somehow magically assembled from the chain ids. Now its possible to remove a account temporary by removing the account file form the account folder. Each account could have an inbound protocol, an outbound protocol and some filters. Mails are now associated with an account and not with a chain. This required to replace the chain id attribute by an account attribute. Replace BMailFilter and BMailChain by a less general approach. Basically the chain had a list of filters and call the ProcessMailMessage for each filter. This made it sometime difficult to understand what is going on, e.g. sometimes a filter used information gathered by another filters. The new MailProtocol and MailFilter classes are calling more dedicated hook functions, e.g. HeaderFetched or MessageReadyToSend. As before all MailProtocol's (plus their filters) are running in their own thread. Cleaned up the error and status window a bit. Abstracted the interface to these windows. Should be easy to write a BNotification api back-end now. Parsing of mail headers is much faster now. Fetching the headers of a large mailbox takes ~min and not ~hour now! Initial checkout time is in the same order like Opera. The problem was the massive use of fgets in parse_header (mail_util.cpp) now the complete header is read in one go. Furthermore, only interesting fields are extracted. Remove some unused files, BeOS relicts... Feel free to translate the mail server and remove the own language system (headers/private/mail/MDRLanguage.h). Sorry for the remaining old (and new) coding style issues, sometime just ignore them, to many :( git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@40397 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -524,10 +524,8 @@ AddFilesToHaikuHybridImage system add-ons locale catalogs
|
|||||||
AddFilesToHaikuImage system add-ons mail_daemon inbound_protocols : POP3 IMAP ;
|
AddFilesToHaikuImage system add-ons mail_daemon inbound_protocols : POP3 IMAP ;
|
||||||
AddFilesToHaikuImage system add-ons mail_daemon outbound_protocols : SMTP ;
|
AddFilesToHaikuImage system add-ons mail_daemon outbound_protocols : SMTP ;
|
||||||
AddFilesToHaikuImage system add-ons mail_daemon inbound_filters
|
AddFilesToHaikuImage system add-ons mail_daemon inbound_filters
|
||||||
: Match\ Header Spam\ Filter R5\ Daemon\ Filter ;
|
: MatchHeader SpamFilter NewMailNotification ;
|
||||||
AddFilesToHaikuImage system add-ons mail_daemon outbound_filters : Fortune ;
|
AddFilesToHaikuImage system add-ons mail_daemon outbound_filters : Fortune ;
|
||||||
AddFilesToHaikuImage system add-ons mail_daemon system_filters
|
|
||||||
: Inbox New\ mail\ notification Outbox Message\ Parser ;
|
|
||||||
AddFilesToHaikuImage system add-ons media : $(SYSTEM_ADD_ONS_MEDIA) ;
|
AddFilesToHaikuImage system add-ons media : $(SYSTEM_ADD_ONS_MEDIA) ;
|
||||||
AddFilesToHaikuImage system add-ons media plugins
|
AddFilesToHaikuImage system add-ons media plugins
|
||||||
: $(SYSTEM_ADD_ONS_MEDIA_PLUGINS) ;
|
: $(SYSTEM_ADD_ONS_MEDIA_PLUGINS) ;
|
||||||
|
|||||||
@@ -1,98 +0,0 @@
|
|||||||
#ifndef ZOIDBERG_MAIL_CHAIN_RUNNER_H
|
|
||||||
#define ZOIDBERG_MAIL_CHAIN_RUNNER_H
|
|
||||||
/* ChainRunner - runs the mail inbound and outbound chains
|
|
||||||
**
|
|
||||||
** Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include <MailAddon.h>
|
|
||||||
#include <MailSettings.h>
|
|
||||||
#include <Looper.h>
|
|
||||||
|
|
||||||
class BStringList;
|
|
||||||
class BMailStatusWindow;
|
|
||||||
class BMailStatusView;
|
|
||||||
class BMailChain;
|
|
||||||
|
|
||||||
class BMailChainCallback {
|
|
||||||
public:
|
|
||||||
virtual void Callback(status_t result) = 0;
|
|
||||||
// Called by the callback routines in ChainRunner
|
|
||||||
// result is the message that ended the chain
|
|
||||||
// (MD_HANDLED, MD_DISCARD, MD_NO_MORE_MESSAGES)
|
|
||||||
// Obviously, for process callbacks, result is
|
|
||||||
// gauranteed to be MD_NO_MORE_MESSAGES.
|
|
||||||
};
|
|
||||||
|
|
||||||
class BMailChainRunner : public BLooper {
|
|
||||||
public:
|
|
||||||
BMailChainRunner(BMailChain *chain, BMailStatusWindow *status,
|
|
||||||
bool self_destruct_when_done = true, bool save_chain_when_done = false,
|
|
||||||
bool destruct_chain_when_done = false);
|
|
||||||
~BMailChainRunner();
|
|
||||||
|
|
||||||
//----Callback functions. Callback objects will be deleted for you.
|
|
||||||
|
|
||||||
void RegisterMessageCallback(BMailChainCallback *callback);
|
|
||||||
// Your callback->Callback() function will be called when
|
|
||||||
// the current message is done being processed.
|
|
||||||
|
|
||||||
void RegisterProcessCallback(BMailChainCallback *callback);
|
|
||||||
// Your callback->Callback() function will be called when
|
|
||||||
// a filter returns MD_PASS_COMPLETE and before we go back
|
|
||||||
// to waiting for new messages, or when the fetch list
|
|
||||||
// runs out.
|
|
||||||
|
|
||||||
void RegisterChainCallback(BMailChainCallback *callback);
|
|
||||||
// Your callback->Callback() function will be called when
|
|
||||||
// a filter returns MD_ALL_PASSES_DONE and before everything
|
|
||||||
// is unloaded and sent home.
|
|
||||||
|
|
||||||
void Stop(bool immediately = false);
|
|
||||||
void ReportProgress(int bytes, int messages, const char *message = NULL);
|
|
||||||
void ResetProgress(const char *message = NULL);
|
|
||||||
|
|
||||||
void GetMessages(BStringList *list, int32 bytes);
|
|
||||||
void GetSingleMessage(const char *uid, int32 length, BPath *into);
|
|
||||||
// The bytes or length field is the total size, used for updating the
|
|
||||||
// progress bar. Use -1 for unknown maximum size.
|
|
||||||
|
|
||||||
bool QuitRequested();
|
|
||||||
|
|
||||||
void ShowError(const char *error);
|
|
||||||
void ShowMessage(const char *message);
|
|
||||||
|
|
||||||
BMailChain *Chain();
|
|
||||||
|
|
||||||
//----The big, bad asynchronous RunChain() function. Pretty harmless looking, huh?
|
|
||||||
status_t RunChain(bool asynchronous = true);
|
|
||||||
|
|
||||||
void MessageReceived (BMessage *msg);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void CallCallbacksFor(BList &list, status_t code);
|
|
||||||
void get_messages(BStringList *list);
|
|
||||||
status_t Init();
|
|
||||||
#if USE_NASTY_SYNC_THREAD_HACK
|
|
||||||
static int32 thread_sync_func(void *arg);
|
|
||||||
status_t init_addons();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
BMailChain *_chain;
|
|
||||||
BList message_cb, process_cb, chain_cb;
|
|
||||||
|
|
||||||
bool destroy_self, destroy_chain, save_chain;
|
|
||||||
|
|
||||||
BMailStatusWindow *_status;
|
|
||||||
BMailStatusView *_statview;
|
|
||||||
BList addons;
|
|
||||||
|
|
||||||
bool suicide;
|
|
||||||
uint8 _other_reserved[3];
|
|
||||||
uint32 _reserved[4];
|
|
||||||
};
|
|
||||||
|
|
||||||
BMailChainRunner *GetMailChainRunner(int32 chain_id, BMailStatusWindow *status, bool selfDestruct = true);
|
|
||||||
|
|
||||||
#endif /* ZOIDBERG_MAIL_CHAIN_RUNNER_H */
|
|
||||||
@@ -1,116 +1,39 @@
|
|||||||
#ifndef ZOIDBERG_MAIL_ADDON_H
|
|
||||||
#define ZOIDBERG_MAIL_ADDON_H
|
|
||||||
/* Filter - the base class for all mail filters
|
/* Filter - the base class for all mail filters
|
||||||
**
|
**
|
||||||
** Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved.
|
** 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 BMessage;
|
|
||||||
class BView;
|
class BView;
|
||||||
class BPositionIO;
|
|
||||||
class BEntry;
|
|
||||||
class BPath;
|
|
||||||
class BView;
|
|
||||||
class BString;
|
|
||||||
class BPositionIO;
|
|
||||||
class BEntry;
|
|
||||||
|
|
||||||
enum {
|
|
||||||
B_MAIL_DISCARD = B_MAIL_ERROR_BASE + 8,
|
|
||||||
//--- This terminates the chain and removes the message being processed
|
|
||||||
// both from disk and from the server.
|
|
||||||
B_MAIL_END_FETCH,
|
|
||||||
//--- Terminates the current operation
|
|
||||||
B_MAIL_END_CHAIN
|
|
||||||
//--- This is for yikes errors, like an unreachable server.
|
|
||||||
};
|
|
||||||
|
|
||||||
class BMailStatusView;
|
|
||||||
class BMailChainRunner;
|
|
||||||
|
|
||||||
class BMailFilter
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
BMailFilter(BMessage* settings);
|
|
||||||
// How to support queueing messages until a time of the
|
|
||||||
// day/week/month/year? The settings will contain a
|
|
||||||
// persistent ChainID field, the same for all Filters
|
|
||||||
// on the same "chain".
|
|
||||||
|
|
||||||
virtual ~BMailFilter();
|
|
||||||
// This will be called when the settings for this Filter
|
|
||||||
// are changed, or there are no new messages to consume
|
|
||||||
// after settings->FindInt32("timeout") seconds.
|
|
||||||
|
|
||||||
virtual status_t InitCheck(BString* out_message = NULL) = 0;
|
|
||||||
// Returns B_OK if the Filter was constructed success-
|
|
||||||
// fully. Otherwise it returns an error code. If it is
|
|
||||||
// passed a valid BString*, it may add an error message
|
|
||||||
// to the end of that BString iff it returns an error.
|
|
||||||
// If it returns an error code then the MailFilter will
|
|
||||||
// probably be deleted and the error shown to the user.
|
|
||||||
|
|
||||||
virtual status_t ProcessMailMessage
|
|
||||||
(
|
|
||||||
BPositionIO** io_message, BEntry* io_entry,
|
|
||||||
BMessage* io_headers, BPath* io_folder, const char *io_uid
|
|
||||||
) = 0;
|
|
||||||
// Filters a message. On input and output, the arguments
|
|
||||||
// are expected to be as below; however it is allowed for
|
|
||||||
// the MailFilter to alter any of these values as nece-
|
|
||||||
// ssary, so long as the constraints are as described when
|
|
||||||
// the function returns:
|
|
||||||
//
|
|
||||||
// * io_message - a PositionIO that contains the message
|
|
||||||
// data, pointing to the first byte of the message's
|
|
||||||
// header. This can be swapped if, eg, the message
|
|
||||||
// is copied across volume boundries. When the chain
|
|
||||||
// begins this is a file in /tmp.
|
|
||||||
// * io_entry - The entry for the PositionIO above.
|
|
||||||
// * io_headers - a list of attributes that will be added
|
|
||||||
// to the message file.
|
|
||||||
// * io_folder - The message's "folder"---may be com-
|
|
||||||
// pletely unrelated to its on-disk Entry.
|
|
||||||
// * io_uid - The unique ID provided by the message's
|
|
||||||
// Protocol
|
|
||||||
//
|
|
||||||
// At most one Filter::ProcessMailMessage() for a given
|
|
||||||
// chain (and thus ChainID) will be called at a time.
|
|
||||||
|
|
||||||
private:
|
|
||||||
virtual void _ReservedFilter1();
|
|
||||||
virtual void _ReservedFilter2();
|
|
||||||
virtual void _ReservedFilter3();
|
|
||||||
virtual void _ReservedFilter4();
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// The addon interface: export instantiate_mailfilter()
|
// The addon interface: export instantiate_mailfilter()
|
||||||
// and instantiate_mailconfig() to create a Filter addon
|
// and instantiate_mailconfig() to create a Filter addon
|
||||||
//
|
//
|
||||||
|
|
||||||
extern "C" _EXPORT BView* instantiate_config_panel(BMessage *settings,BMessage *metadata);
|
extern "C" _EXPORT InboundProtocol* instantiate_inbound_protocol(
|
||||||
// return a view that configures the MailProtocol or MailFilter
|
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)
|
// returned by the functions below. BView::Archive(foo,true)
|
||||||
// produces this addon's settings, which are passed to the in-
|
// produces this addon's settings, which are passed to the in-
|
||||||
// stantiate_* functions and stored persistently. This function
|
// stantiate_* functions and stored persistently. This function
|
||||||
// should gracefully handle empty and NULL settings.
|
// should gracefully handle empty and NULL settings.
|
||||||
// A note on the metadata argument: The metadata pointer is
|
|
||||||
// guaranteed to remain valid as long as this view exists. As it is
|
|
||||||
// a pointer to the chain's metadata, your view can save any
|
|
||||||
// chain-global settings to it in its Archive() function. Note that
|
|
||||||
// you must cache this pointer yourself! You will never get it again.
|
|
||||||
// Also note that it is possible for it to be NULL.
|
|
||||||
|
|
||||||
extern "C" _EXPORT BMailFilter* instantiate_mailfilter(BMessage *settings,
|
extern "C" _EXPORT BView* instantiate_filter_config_panel(AddonSettings&);
|
||||||
BMailChainRunner *runner);
|
extern "C" _EXPORT MailFilter* instantiate_mailfilter(MailProtocol& protocol,
|
||||||
// Return a MailProtocol or MailFilter ready to do its thing,
|
AddonSettings* settings);
|
||||||
// based on settings produced by archiving your config panel.
|
|
||||||
// Note that a Mail::Protocol is a Mail::Filter, so use
|
|
||||||
// instantiate_mailfilter to start things up.
|
|
||||||
|
|
||||||
extern "C" _EXPORT status_t descriptive_name(BMessage *msg, char *buffer);
|
extern "C" _EXPORT BString descriptive_name();
|
||||||
// the config panel will show this name in the chains filter
|
// the config panel will show this name in the chains filter
|
||||||
// list if this function returns B_OK.
|
// list if this function returns B_OK.
|
||||||
// The buffer is as big as B_FILE_NAME_LENGTH.
|
// The buffer is as big as B_FILE_NAME_LENGTH.
|
||||||
|
|||||||
@@ -1,107 +1,225 @@
|
|||||||
#ifndef ZOIDBERG_MAIL_PROTOCOL_H
|
|
||||||
#define ZOIDBERG_MAIL_PROTOCOL_H
|
|
||||||
/* Protocol - the base class for protocol filters
|
/* Protocol - the base class for protocol filters
|
||||||
**
|
*
|
||||||
** Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved.
|
* Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved.
|
||||||
|
* Copyright 2011 Clemens Zeidler. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
#ifndef MAIL_PROTOCOL_H
|
||||||
|
#define MAIL_PROTOCOL_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <Handler.h>
|
||||||
|
#include <Looper.h>
|
||||||
#include <OS.h>
|
#include <OS.h>
|
||||||
|
#include <ObjectList.h>
|
||||||
|
#include <Entry.h>
|
||||||
|
#include <File.h>
|
||||||
|
|
||||||
#include <MailAddon.h>
|
#include <MailSettings.h>
|
||||||
|
|
||||||
|
|
||||||
class BHandler;
|
class MailNotifier {
|
||||||
class BStringList;
|
public:
|
||||||
class BMailChainRunner;
|
virtual ~MailNotifier() {}
|
||||||
|
|
||||||
class BMailProtocol : public BMailFilter
|
virtual MailNotifier* Clone() = 0;
|
||||||
{
|
|
||||||
public:
|
|
||||||
BMailProtocol(BMessage* settings, BMailChainRunner *runner);
|
|
||||||
// Open a connection based on 'settings'. 'settings' will
|
|
||||||
// contain a persistent uint32 ChainID field. At most one
|
|
||||||
// Protocol per ChainID will exist at a given time.
|
|
||||||
// The constructor of Mail::Protocol initializes manifest.
|
|
||||||
// It is your responsibility to fill in unique_ids, *and
|
|
||||||
// to keep it updated* in the course of whatever nefarious
|
|
||||||
// things your protocol does.
|
|
||||||
|
|
||||||
virtual ~BMailProtocol();
|
|
||||||
// Close the connection and clean up. This will be cal-
|
|
||||||
// led after FetchMessage() or FetchNewMessage() returns
|
|
||||||
// B_TIMED_OUT or B_ERROR, or when the settings for this
|
|
||||||
// Protocol are changed.
|
|
||||||
|
|
||||||
virtual status_t GetMessage(
|
|
||||||
const char* uid,
|
|
||||||
BPositionIO** out_file, BMessage* out_headers,
|
|
||||||
BPath* out_folder_location
|
|
||||||
)=0;
|
|
||||||
// Downloads the message with id uid, writing the message's
|
|
||||||
// RFC2822 contents to *out_file and storing any headers it
|
|
||||||
// wants to add other than those from the message itself into
|
|
||||||
// out_headers. It may store a path (if this type of account
|
|
||||||
// supports folders) in *out_folder_location.
|
|
||||||
//
|
|
||||||
// Returns B_OK if the message is now available in out_file,
|
|
||||||
// B_NAME_NOT_FOUND if there is no message with id 'uid' on
|
|
||||||
// the server, or another error if the connection failed.
|
|
||||||
//
|
|
||||||
// B_OK will cause the message to be stored and processed.
|
|
||||||
// B_NAME_NOT_FOUND will cause appropriate recovery to be
|
|
||||||
// taken (if such exists) but not cause the connection to
|
|
||||||
// be terminated. Any other error will cause anything writen
|
|
||||||
// to be discarded and and the connection closed.
|
|
||||||
|
|
||||||
// OBS:
|
|
||||||
// The Protocol may replace *out_file with a custom (read-
|
|
||||||
// only) BPositionIO-derived object that preserves the il-
|
|
||||||
// lusion that the message is writen to *out_file, but in
|
|
||||||
// fact only reads from the server and writes to *out_file
|
|
||||||
// on demand. This BPositionIO must guarantee that any
|
|
||||||
// data returned by Read() has also been writen to *out_-
|
|
||||||
// file. It must return a read error if reading from the
|
|
||||||
// network or writing to *out_file fails.
|
|
||||||
//
|
|
||||||
// The mail_daemon will delete *out_file before invoking
|
|
||||||
// FetchMessage() or FetchNewMessage() again.
|
|
||||||
|
|
||||||
virtual status_t DeleteMessage(const char* uid)=0;
|
|
||||||
// Removes the message from the server. After this, it's
|
|
||||||
// assumed (but not required) that GetMessage(uid,...)
|
|
||||||
// et al will fail with B_NAME_NOT_FOUND.
|
|
||||||
|
|
||||||
void CheckForDeletedMessages();
|
|
||||||
// You can call this to trigger a sweep for deleted messages.
|
|
||||||
// Automatically called at the beginning of the chain.
|
|
||||||
|
|
||||||
//------MailFilter calls
|
|
||||||
virtual status_t ProcessMailMessage
|
|
||||||
(
|
|
||||||
BPositionIO** io_message, BEntry* io_entry,
|
|
||||||
BMessage* io_headers, BPath* io_folder, const char* io_uid
|
|
||||||
);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
BStringList *manifest, *unique_ids;
|
|
||||||
BMessage *settings;
|
|
||||||
|
|
||||||
BMailChainRunner *runner;
|
|
||||||
private:
|
|
||||||
inline void error_alert(const char *process, status_t error);
|
|
||||||
virtual void _ReservedProtocol1();
|
|
||||||
virtual void _ReservedProtocol2();
|
|
||||||
virtual void _ReservedProtocol3();
|
|
||||||
virtual void _ReservedProtocol4();
|
|
||||||
virtual void _ReservedProtocol5();
|
|
||||||
|
|
||||||
friend class DeletePass;
|
virtual void ShowError(const char* error) = 0;
|
||||||
|
virtual void ShowMessage(const char* message) = 0;
|
||||||
BHandler *trash_monitor;
|
|
||||||
BStringList *uids_on_disk;
|
virtual void SetTotalItems(int32 items) = 0;
|
||||||
|
virtual void SetTotalItemsSize(int32 size) = 0;
|
||||||
uint32 _reserved[3];
|
virtual void ReportProgress(int bytes, int messages,
|
||||||
|
const char* message = NULL) = 0;
|
||||||
|
virtual void ResetProgress(const char* message = NULL) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // ZOIDBERG_MAIL_PROTOCOL_H
|
|
||||||
|
class MailProtocol;
|
||||||
|
|
||||||
|
|
||||||
|
class MailFilter {
|
||||||
|
public:
|
||||||
|
MailFilter(MailProtocol& protocol,
|
||||||
|
AddonSettings* settings);
|
||||||
|
virtual ~MailFilter();
|
||||||
|
|
||||||
|
//! Message hooks if filter is installed to a 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 a outbound protocol
|
||||||
|
virtual void MessageReadyToSend(const entry_ref& ref,
|
||||||
|
BFile* file);
|
||||||
|
virtual void MessageSent(const entry_ref& ref,
|
||||||
|
BFile* file);
|
||||||
|
protected:
|
||||||
|
MailProtocol& fMailProtocol;
|
||||||
|
AddonSettings* fAddonSettings;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class MailProtocolThread;
|
||||||
|
|
||||||
|
|
||||||
|
class MailProtocol {
|
||||||
|
public:
|
||||||
|
MailProtocol(BMailAccountSettings* settings);
|
||||||
|
virtual ~MailProtocol();
|
||||||
|
|
||||||
|
virtual void SetStopNow() {}
|
||||||
|
|
||||||
|
BMailAccountSettings& AccountSettings();
|
||||||
|
|
||||||
|
void SetProtocolThread(
|
||||||
|
MailProtocolThread* protocolThread);
|
||||||
|
virtual void AddedToLooper() {}
|
||||||
|
MailProtocolThread* Looper();
|
||||||
|
/*! Add handler to the handler list. The handler is installed /
|
||||||
|
removed to the according BLooper automatically. */
|
||||||
|
bool AddHandler(BHandler* handler);
|
||||||
|
//! Does not delete handler
|
||||||
|
bool RemoveHandler(BHandler* handler);
|
||||||
|
|
||||||
|
void SetMailNotifier(MailNotifier* mailNotifier);
|
||||||
|
|
||||||
|
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,
|
||||||
|
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 NotifyNewMessagesToFetch(int32 nMessages);
|
||||||
|
void NotifyHeaderFetched(const entry_ref& ref,
|
||||||
|
BFile* mail);
|
||||||
|
void NotifyBodyFetched(const entry_ref& ref,
|
||||||
|
BFile* mail);
|
||||||
|
void NotifyMessageReadyToSend(const entry_ref& ref,
|
||||||
|
BFile* mail);
|
||||||
|
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);
|
||||||
|
|
||||||
|
virtual void FileRenamed(const entry_ref& from,
|
||||||
|
const entry_ref& to);
|
||||||
|
virtual void FileDeleted(const node_ref& node);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void LoadFilters(MailAddonSettings& settings);
|
||||||
|
|
||||||
|
BMailAccountSettings fAccountSettings;
|
||||||
|
MailNotifier* fMailNotifier;
|
||||||
|
|
||||||
|
private:
|
||||||
|
MailFilter* _LoadFilter(AddonSettings* filterSettings);
|
||||||
|
|
||||||
|
MailProtocolThread* fProtocolThread;
|
||||||
|
BObjectList<BHandler> fHandlerList;
|
||||||
|
BObjectList<MailFilter> fFilterList;
|
||||||
|
std::map<entry_ref, image_id> fFilterImages;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class InboundProtocol : public MailProtocol {
|
||||||
|
public:
|
||||||
|
InboundProtocol(BMailAccountSettings* settings);
|
||||||
|
virtual ~InboundProtocol();
|
||||||
|
|
||||||
|
virtual status_t SyncMessages() = 0;
|
||||||
|
virtual status_t FetchBody(const entry_ref& ref) = 0;
|
||||||
|
virtual status_t MarkMessageAsRead(const entry_ref& ref,
|
||||||
|
bool read = true);
|
||||||
|
virtual status_t DeleteMessage(const entry_ref& ref) = 0;
|
||||||
|
virtual status_t AppendMessage(const entry_ref& ref);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class OutboundProtocol : public MailProtocol {
|
||||||
|
public:
|
||||||
|
OutboundProtocol(
|
||||||
|
BMailAccountSettings* settings);
|
||||||
|
virtual ~OutboundProtocol();
|
||||||
|
|
||||||
|
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,
|
||||||
|
bool launch = false);
|
||||||
|
void MarkMessageAsRead(const entry_ref& ref,
|
||||||
|
bool read = true);
|
||||||
|
void DeleteMessage(const entry_ref& ref);
|
||||||
|
void AppendMessage(const entry_ref& ref);
|
||||||
|
private:
|
||||||
|
void _NotiyMailboxSynced(status_t status);
|
||||||
|
|
||||||
|
InboundProtocol* fProtocol;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class OutboundProtocolThread : public MailProtocolThread {
|
||||||
|
public:
|
||||||
|
OutboundProtocolThread(
|
||||||
|
OutboundProtocol* protocol);
|
||||||
|
~OutboundProtocolThread();
|
||||||
|
|
||||||
|
void MessageReceived(BMessage* message);
|
||||||
|
|
||||||
|
void SendMessages(const std::vector<entry_ref>&
|
||||||
|
mails, size_t totalBytes);
|
||||||
|
|
||||||
|
private:
|
||||||
|
OutboundProtocol* fProtocol;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // MAIL_PROTOCOL_H
|
||||||
|
|||||||
@@ -1,38 +1,69 @@
|
|||||||
#ifndef ZOIDBERG_PROTOCOL_CONFIG_VIEW_H
|
|
||||||
#define ZOIDBERG_PROTOCOL_CONFIG_VIEW_H
|
|
||||||
/* ProtocolConfigView - the standard config view for all protocols
|
/* ProtocolConfigView - the standard config view for all protocols
|
||||||
**
|
**
|
||||||
** Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved.
|
** Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
#ifndef ZOIDBERG_PROTOCOL_CONFIG_VIEW_H
|
||||||
|
#define ZOIDBERG_PROTOCOL_CONFIG_VIEW_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <CheckBox.h>
|
||||||
|
#include <StringView.h>
|
||||||
|
#include <TextControl.h>
|
||||||
#include <View.h>
|
#include <View.h>
|
||||||
|
|
||||||
|
#include "MailSettings.h"
|
||||||
|
|
||||||
|
|
||||||
|
class BodyDownloadConfig : public BView {
|
||||||
|
public:
|
||||||
|
BodyDownloadConfig();
|
||||||
|
|
||||||
|
void SetTo(MailAddonSettings& settings);
|
||||||
|
|
||||||
|
void MessageReceived(BMessage *msg);
|
||||||
|
void AttachedToWindow();
|
||||||
|
void GetPreferredSize(float *width, float *height);
|
||||||
|
status_t Archive(BMessage *into, bool) const;
|
||||||
|
private:
|
||||||
|
BTextControl* fSizeBox;
|
||||||
|
BCheckBox* fPartialBox;
|
||||||
|
BStringView* fBytesLabel;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
B_MAIL_PROTOCOL_HAS_AUTH_METHODS = 1,
|
B_MAIL_PROTOCOL_HAS_AUTH_METHODS = 1,
|
||||||
B_MAIL_PROTOCOL_HAS_FLAVORS = 2,
|
B_MAIL_PROTOCOL_HAS_FLAVORS = 2,
|
||||||
B_MAIL_PROTOCOL_HAS_USERNAME = 4,
|
B_MAIL_PROTOCOL_HAS_USERNAME = 4,
|
||||||
B_MAIL_PROTOCOL_HAS_PASSWORD = 8,
|
B_MAIL_PROTOCOL_HAS_PASSWORD = 8,
|
||||||
B_MAIL_PROTOCOL_HAS_HOSTNAME = 16,
|
B_MAIL_PROTOCOL_HAS_HOSTNAME = 16,
|
||||||
B_MAIL_PROTOCOL_CAN_LEAVE_MAIL_ON_SERVER = 32
|
B_MAIL_PROTOCOL_CAN_LEAVE_MAIL_ON_SERVER = 32,
|
||||||
|
B_MAIL_PROTOCOL_PARTIAL_DOWNLOAD = 64
|
||||||
} b_mail_protocol_config_options;
|
} b_mail_protocol_config_options;
|
||||||
|
|
||||||
class BMailProtocolConfigView : 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(BMessage *archive);
|
|
||||||
|
|
||||||
void AddFlavor(const char *label);
|
|
||||||
void AddAuthMethod(const char *label,bool needUserPassword = true);
|
|
||||||
|
|
||||||
virtual status_t Archive(BMessage *into, bool deep = true) const;
|
class BMailProtocolConfigView : public BView {
|
||||||
virtual void GetPreferredSize(float *width, float *height);
|
public:
|
||||||
virtual void AttachedToWindow();
|
BMailProtocolConfigView(uint32 options_mask
|
||||||
virtual void MessageReceived(BMessage *msg);
|
= 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,
|
||||||
|
bool needUserPassword = true);
|
||||||
|
|
||||||
|
virtual status_t Archive(BMessage *into, bool deep = true) const;
|
||||||
|
virtual void GetPreferredSize(float *width, float *height);
|
||||||
|
virtual void AttachedToWindow();
|
||||||
|
virtual void MessageReceived(BMessage *msg);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint32 _reserved[5];
|
BodyDownloadConfig* fBodyDownloadConfig;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* ZOIDBERG_PROTOCOL_CONFIG_VIEW_H */
|
#endif /* ZOIDBERG_PROTOCOL_CONFIG_VIEW_H */
|
||||||
|
|||||||
@@ -1,41 +0,0 @@
|
|||||||
#ifndef ZOIDBERG_MAIL_REMOTESTORAGEPROTOCOL_H
|
|
||||||
#define ZOIDBERG_MAIL_REMOTESTORAGEPROTOCOL_H
|
|
||||||
/* RemoteStorageProtocol - the base class for protocol filters
|
|
||||||
**
|
|
||||||
** Copyright 2003 Dr. Zoidberg Enterprises. All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <MailProtocol.h>
|
|
||||||
#include <StringList.h>
|
|
||||||
|
|
||||||
class BRemoteMailStorageProtocol : public BMailProtocol {
|
|
||||||
public:
|
|
||||||
BRemoteMailStorageProtocol(BMessage *settings, BMailChainRunner *runner);
|
|
||||||
virtual ~BRemoteMailStorageProtocol();
|
|
||||||
|
|
||||||
virtual status_t GetMessage(const char *mailbox, const char *message, BPositionIO **, BMessage *headers) = 0;
|
|
||||||
virtual status_t AddMessage(const char *mailbox, BPositionIO *data, BString *id) = 0;
|
|
||||||
|
|
||||||
virtual status_t DeleteMessage(const char *mailbox, const char *message) = 0;
|
|
||||||
virtual status_t CopyMessage(const char *mailbox, const char *to_mailbox, BString *message) = 0;
|
|
||||||
|
|
||||||
virtual status_t CreateMailbox(const char *mailbox) = 0;
|
|
||||||
virtual status_t DeleteMailbox(const char *mailbox) = 0;
|
|
||||||
|
|
||||||
void SyncMailbox(const char *mailbox);
|
|
||||||
|
|
||||||
//----Mail::Protocol stuff
|
|
||||||
virtual status_t GetMessage(
|
|
||||||
const char* uid,
|
|
||||||
BPositionIO** out_file, BMessage* out_headers,
|
|
||||||
BPath* out_folder_location);
|
|
||||||
virtual status_t DeleteMessage(const char* uid);
|
|
||||||
|
|
||||||
//---Data members
|
|
||||||
BStringList mailboxes;
|
|
||||||
|
|
||||||
private:
|
|
||||||
BHandler *handler;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // ZOIDBERG_MAIL_REMOTESTORAGEPROTOCOL_H
|
|
||||||
@@ -92,27 +92,6 @@ typedef struct {
|
|||||||
} mail_notification;
|
} mail_notification;
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - global functions
|
|
||||||
|
|
||||||
|
|
||||||
int32 count_pop_accounts(void);
|
|
||||||
status_t get_pop_account(mail_pop_account*, int32 index = 0);
|
|
||||||
status_t set_pop_account(mail_pop_account*, int32 index = 0,
|
|
||||||
bool save = true);
|
|
||||||
status_t get_smtp_host(char*);
|
|
||||||
status_t set_smtp_host(char*, bool save = true);
|
|
||||||
status_t get_mail_notification(mail_notification*);
|
|
||||||
status_t set_mail_notification(mail_notification*, bool save = true);
|
|
||||||
|
|
||||||
status_t check_for_mail(int32* incoming_count = NULL);
|
|
||||||
status_t send_queued_mail(void);
|
|
||||||
status_t forward_mail(entry_ref*, const char* recipients, bool now = true);
|
|
||||||
|
|
||||||
ssize_t decode_base64(char* out, char* in, off_t length,
|
|
||||||
bool replace_cr = false);
|
|
||||||
ssize_t encode_base64(char* out, char* in, off_t length);
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - BMailMessage
|
// #pragma mark - BMailMessage
|
||||||
|
|
||||||
class BMailMessage {
|
class BMailMessage {
|
||||||
|
|||||||
@@ -1,18 +1,34 @@
|
|||||||
#ifndef ZOIDBERG_MAIL_DAEMON_H
|
#ifndef MAIL_DAEMON_H
|
||||||
#define ZOIDBERG_MAIL_DAEMON_H
|
#define MAIL_DAEMON_H
|
||||||
/* Daemon - talking to the mail daemon
|
/* Daemon - talking to the mail daemon
|
||||||
**
|
*
|
||||||
** Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved.
|
* Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved.
|
||||||
|
* Copyright 2011, Clemens Zeidler <[email protected]>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class BMailDaemon {
|
|
||||||
public:
|
|
||||||
static status_t CheckMail(bool send_queued_mail = true,const char *account = NULL);
|
|
||||||
static status_t SendQueuedMail();
|
|
||||||
static int32 CountNewMessages(bool wait_for_fetch_completion = false);
|
|
||||||
|
|
||||||
static status_t Quit();
|
const uint32 kMsgCheckAndSend = 'mbth';
|
||||||
|
const uint32 kMsgCheckMessage = 'mnow';
|
||||||
|
const uint32 kMsgSendMessages = 'msnd';
|
||||||
|
const uint32 kMsgSettingsUpdated = 'mrrs';
|
||||||
|
const uint32 kMsgAccountsChanged = 'macc';
|
||||||
|
const uint32 kMsgSetStatusWindowMode = 'shst';
|
||||||
|
const uint32 kMsgCountNewMessages = 'mnum';
|
||||||
|
const uint32 kMsgMarkMessageAsRead = 'mmar';
|
||||||
|
|
||||||
|
|
||||||
|
class BMailDaemon {
|
||||||
|
public:
|
||||||
|
//! accountID = -1 means check all accounts
|
||||||
|
static status_t CheckMail(int32 accountID = -1);
|
||||||
|
static status_t CheckAndSendQueuedMail(int32 accountID = -1);
|
||||||
|
static status_t SendQueuedMail();
|
||||||
|
static int32 CountNewMessages(
|
||||||
|
bool waitForFetchCompletion = false);
|
||||||
|
static status_t MarkAsRead(int32 account, const entry_ref& ref,
|
||||||
|
bool read = true);
|
||||||
|
|
||||||
|
static status_t Quit();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* ZOIDBERG_MAIL_DAEMON_H */
|
#endif // MAIL_DAEMON_H
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,8 @@ enum mail_reply_to_mode {
|
|||||||
class BEmailMessage : public BMailContainer {
|
class BEmailMessage : public BMailContainer {
|
||||||
public:
|
public:
|
||||||
BEmailMessage(BPositionIO *mail_file = NULL, bool own = false, uint32 defaultCharSet = B_MAIL_NULL_CONVERSION);
|
BEmailMessage(BPositionIO *mail_file = NULL, bool own = false, uint32 defaultCharSet = B_MAIL_NULL_CONVERSION);
|
||||||
BEmailMessage(entry_ref *ref, uint32 defaultCharSet = B_MAIL_NULL_CONVERSION);
|
BEmailMessage(const entry_ref *ref,
|
||||||
|
uint32 defaultCharSet = B_MAIL_NULL_CONVERSION);
|
||||||
virtual ~BEmailMessage();
|
virtual ~BEmailMessage();
|
||||||
|
|
||||||
status_t InitCheck() const;
|
status_t InitCheck() const;
|
||||||
@@ -60,7 +61,7 @@ class BEmailMessage : public BMailContainer {
|
|||||||
|
|
||||||
void SendViaAccountFrom(BEmailMessage *message);
|
void SendViaAccountFrom(BEmailMessage *message);
|
||||||
void SendViaAccount(const char *account_name);
|
void SendViaAccount(const char *account_name);
|
||||||
void SendViaAccount(int32 chain_id);
|
void SendViaAccount(int32 account);
|
||||||
int32 Account() const;
|
int32 Account() const;
|
||||||
status_t GetAccountName(char *account,int32 maxLength) const;
|
status_t GetAccountName(char *account,int32 maxLength) const;
|
||||||
status_t GetAccountName(BString *account) const;
|
status_t GetAccountName(BString *account) const;
|
||||||
@@ -99,7 +100,7 @@ class BEmailMessage : public BMailContainer {
|
|||||||
BPositionIO *fData;
|
BPositionIO *fData;
|
||||||
|
|
||||||
status_t _status;
|
status_t _status;
|
||||||
int32 _chain_id;
|
int32 _account_id;
|
||||||
char *_bcc;
|
char *_bcc;
|
||||||
|
|
||||||
int32 _num_components;
|
int32 _num_components;
|
||||||
|
|||||||
+172
-119
@@ -1,17 +1,25 @@
|
|||||||
#ifndef ZOIDBERG_MAIL_SETTINGS_H
|
/*
|
||||||
#define ZOIDBERG_MAIL_SETTINGS_H
|
* Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved.
|
||||||
/* Settings - the mail daemon's settings
|
* Copyright 2011 Clemens Zeidler.
|
||||||
**
|
* Distributed under the terms of the MIT License.
|
||||||
** Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved.
|
*/
|
||||||
*/
|
#ifndef MAIL_SETTINGS_H
|
||||||
|
#define MAIL_SETTINGS_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <Archivable.h>
|
#include <Archivable.h>
|
||||||
|
#include <Entry.h>
|
||||||
#include <List.h>
|
#include <List.h>
|
||||||
#include <Message.h>
|
#include <Message.h>
|
||||||
|
#include <ObjectList.h>
|
||||||
|
#include <String.h>
|
||||||
|
|
||||||
|
|
||||||
class BPath;
|
class BPath;
|
||||||
|
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
B_MAIL_SHOW_STATUS_WINDOW_NEVER = 0,
|
B_MAIL_SHOW_STATUS_WINDOW_NEVER = 0,
|
||||||
@@ -20,6 +28,7 @@ typedef enum
|
|||||||
B_MAIL_SHOW_STATUS_WINDOW_ALWAYS = 3
|
B_MAIL_SHOW_STATUS_WINDOW_ALWAYS = 3
|
||||||
} b_mail_status_window_option;
|
} b_mail_status_window_option;
|
||||||
|
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
B_MAIL_STATUS_LOOK_TITLED = 0,
|
B_MAIL_STATUS_LOOK_TITLED = 0,
|
||||||
@@ -29,126 +38,170 @@ typedef enum
|
|||||||
B_MAIL_STATUS_LOOK_NO_BORDER = 4
|
B_MAIL_STATUS_LOOK_NO_BORDER = 4
|
||||||
} b_mail_status_window_look;
|
} b_mail_status_window_look;
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
inbound,
|
|
||||||
outbound
|
|
||||||
} b_mail_chain_direction;
|
|
||||||
|
|
||||||
class BMailStatusWindow;
|
|
||||||
class BMailChain;
|
|
||||||
|
|
||||||
BMailChain* NewMailChain();
|
|
||||||
BMailChain* GetMailChain(uint32 id);
|
|
||||||
|
|
||||||
status_t GetOutboundMailChains(BList* list);
|
|
||||||
status_t GetInboundMailChains(BList* list);
|
|
||||||
|
|
||||||
|
|
||||||
class BMailChain : public BArchivable {
|
|
||||||
public:
|
|
||||||
BMailChain(uint32 id);
|
|
||||||
BMailChain(BMessage*);
|
|
||||||
virtual ~BMailChain();
|
|
||||||
|
|
||||||
virtual status_t Archive(BMessage*, bool) const;
|
|
||||||
static BArchivable* Instantiate(BMessage*);
|
|
||||||
|
|
||||||
status_t Save(bigtime_t timeout = B_INFINITE_TIMEOUT);
|
|
||||||
status_t Delete() const;
|
|
||||||
status_t Reload();
|
|
||||||
status_t InitCheck() const;
|
|
||||||
|
|
||||||
uint32 ID() const;
|
|
||||||
|
|
||||||
b_mail_chain_direction ChainDirection() const;
|
|
||||||
void SetChainDirection(b_mail_chain_direction);
|
|
||||||
|
|
||||||
const char* Name() const;
|
|
||||||
status_t SetName(const char*);
|
|
||||||
|
|
||||||
BMessage* MetaData() const;
|
|
||||||
|
|
||||||
// "Filter" below refers to the settings message for a MailFilter
|
|
||||||
int32 CountFilters() const;
|
|
||||||
status_t GetFilter(int32 index, BMessage* out_settings, entry_ref* addon = NULL) const;
|
|
||||||
status_t SetFilter(int32 index, const BMessage&, const entry_ref&);
|
|
||||||
|
|
||||||
status_t AddFilter(const BMessage&, const entry_ref&); // at end
|
|
||||||
status_t AddFilter(int32 index, const BMessage&, const entry_ref&);
|
|
||||||
status_t RemoveFilter(int32 index);
|
|
||||||
|
|
||||||
void RunChain(BMailStatusWindow* window,
|
|
||||||
bool async = true,
|
|
||||||
bool save_when_done = true,
|
|
||||||
bool delete_when_done = false);
|
|
||||||
|
|
||||||
private:
|
|
||||||
status_t GetPath(BPath& path) const;
|
|
||||||
status_t Load(BMessage*);
|
|
||||||
|
|
||||||
int32 fId;
|
|
||||||
char fName[B_FILE_NAME_LENGTH];
|
|
||||||
BMessage* fMetaData;
|
|
||||||
|
|
||||||
status_t fStatus;
|
|
||||||
|
|
||||||
b_mail_chain_direction fDirection;
|
|
||||||
|
|
||||||
int32 fSettingsCount;
|
|
||||||
int32 fAddonsCount;
|
|
||||||
BList fFilterSettings;
|
|
||||||
BList fFilterAddons;
|
|
||||||
|
|
||||||
uint32 _reserved[5];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class BMailSettings {
|
class BMailSettings {
|
||||||
public:
|
public:
|
||||||
BMailSettings();
|
BMailSettings();
|
||||||
~BMailSettings();
|
~BMailSettings();
|
||||||
|
|
||||||
status_t Save(bigtime_t timeout = B_INFINITE_TIMEOUT);
|
|
||||||
status_t Reload();
|
|
||||||
status_t InitCheck() const;
|
|
||||||
|
|
||||||
// Global settings
|
|
||||||
int32 WindowFollowsCorner();
|
|
||||||
void SetWindowFollowsCorner(int32 which_corner);
|
|
||||||
|
|
||||||
uint32 ShowStatusWindow();
|
|
||||||
void SetShowStatusWindow(uint32 mode);
|
|
||||||
|
|
||||||
bool DaemonAutoStarts();
|
|
||||||
void SetDaemonAutoStarts(bool does_it);
|
|
||||||
|
|
||||||
void SetConfigWindowFrame(BRect frame);
|
status_t Save(bigtime_t timeout = B_INFINITE_TIMEOUT);
|
||||||
BRect ConfigWindowFrame();
|
status_t Reload();
|
||||||
|
status_t InitCheck() const;
|
||||||
|
|
||||||
void SetStatusWindowFrame(BRect frame);
|
// Global settings
|
||||||
BRect StatusWindowFrame();
|
int32 WindowFollowsCorner();
|
||||||
|
void SetWindowFollowsCorner(int32 which_corner);
|
||||||
|
|
||||||
int32 StatusWindowWorkspaces();
|
uint32 ShowStatusWindow();
|
||||||
void SetStatusWindowWorkspaces(int32 workspaces);
|
void SetShowStatusWindow(uint32 mode);
|
||||||
|
|
||||||
|
bool DaemonAutoStarts();
|
||||||
|
void SetDaemonAutoStarts(bool does_it);
|
||||||
|
|
||||||
int32 StatusWindowLook();
|
void SetConfigWindowFrame(BRect frame);
|
||||||
void SetStatusWindowLook(int32 look);
|
BRect ConfigWindowFrame();
|
||||||
|
|
||||||
bigtime_t AutoCheckInterval();
|
|
||||||
void SetAutoCheckInterval(bigtime_t);
|
|
||||||
|
|
||||||
bool CheckOnlyIfPPPUp();
|
|
||||||
void SetCheckOnlyIfPPPUp(bool yes);
|
|
||||||
|
|
||||||
bool SendOnlyIfPPPUp();
|
|
||||||
void SetSendOnlyIfPPPUp(bool yes);
|
|
||||||
|
|
||||||
uint32 DefaultOutboundChainID();
|
|
||||||
void SetDefaultOutboundChainID(uint32 to);
|
|
||||||
|
|
||||||
private:
|
void SetStatusWindowFrame(BRect frame);
|
||||||
BMessage fData;
|
BRect StatusWindowFrame();
|
||||||
uint32 _reserved[4];
|
|
||||||
|
int32 StatusWindowWorkspaces();
|
||||||
|
void SetStatusWindowWorkspaces(int32 workspaces);
|
||||||
|
|
||||||
|
int32 StatusWindowLook();
|
||||||
|
void SetStatusWindowLook(int32 look);
|
||||||
|
|
||||||
|
bigtime_t AutoCheckInterval();
|
||||||
|
void SetAutoCheckInterval(bigtime_t);
|
||||||
|
|
||||||
|
bool CheckOnlyIfPPPUp();
|
||||||
|
void SetCheckOnlyIfPPPUp(bool yes);
|
||||||
|
|
||||||
|
bool SendOnlyIfPPPUp();
|
||||||
|
void SetSendOnlyIfPPPUp(bool yes);
|
||||||
|
|
||||||
|
int32 DefaultOutboundAccount();
|
||||||
|
void SetDefaultOutboundAccount(int32 to);
|
||||||
|
|
||||||
|
private:
|
||||||
|
BMessage fData;
|
||||||
|
uint32 _reserved[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class AddonSettings
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AddonSettings();
|
||||||
|
|
||||||
|
bool Load(const BMessage& message);
|
||||||
|
bool Save(BMessage& message);
|
||||||
|
|
||||||
|
void SetAddonRef(const entry_ref& ref);
|
||||||
|
const entry_ref& AddonRef() const;
|
||||||
|
|
||||||
|
const BMessage& Settings() const;
|
||||||
|
BMessage& EditSettings();
|
||||||
|
|
||||||
|
bool HasBeenModified();
|
||||||
|
private:
|
||||||
|
BMessage fSettings;
|
||||||
|
entry_ref fAddonRef;
|
||||||
|
|
||||||
|
bool fModified;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class MailAddonSettings : public AddonSettings
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool Load(const BMessage& message);
|
||||||
|
bool Save(BMessage& message);
|
||||||
|
|
||||||
|
int32 CountFilterSettings();
|
||||||
|
int32 AddFilterSettings(const entry_ref* ref = NULL);
|
||||||
|
bool RemoveFilterSettings(int32 index);
|
||||||
|
bool MoveFilterSettings(int32 from, int32 to);
|
||||||
|
AddonSettings* FilterSettingsAt(int32 index);
|
||||||
|
|
||||||
|
bool HasBeenModified();
|
||||||
|
private:
|
||||||
|
std::vector<AddonSettings> fFiltersSettings;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class BMailAccountSettings
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BMailAccountSettings();
|
||||||
|
BMailAccountSettings(BEntry account);
|
||||||
|
~BMailAccountSettings();
|
||||||
|
|
||||||
|
status_t InitCheck() { return fStatus; }
|
||||||
|
|
||||||
|
void SetAccountID(int32 id);
|
||||||
|
int32 AccountID();
|
||||||
|
|
||||||
|
void SetName(const char* name);
|
||||||
|
const char* Name() const;
|
||||||
|
|
||||||
|
void SetRealName(const char* realName);
|
||||||
|
const char* RealName() const;
|
||||||
|
|
||||||
|
void SetReturnAddress(const char* returnAddress);
|
||||||
|
const char* ReturnAddress() const;
|
||||||
|
|
||||||
|
bool SetInboundAddon(const char* name);
|
||||||
|
bool SetOutboundAddon(const char* name);
|
||||||
|
const entry_ref& InboundPath() const;
|
||||||
|
const entry_ref& OutboundPath() const;
|
||||||
|
|
||||||
|
MailAddonSettings& InboundSettings();
|
||||||
|
MailAddonSettings& OutboundSettings();
|
||||||
|
|
||||||
|
bool HasInbound();
|
||||||
|
bool HasOutbound();
|
||||||
|
|
||||||
|
status_t Reload();
|
||||||
|
status_t Save();
|
||||||
|
status_t Delete();
|
||||||
|
|
||||||
|
bool HasBeenModified();
|
||||||
|
|
||||||
|
const BEntry& AccountFile();
|
||||||
|
private:
|
||||||
|
status_t _CreateAccountFile();
|
||||||
|
|
||||||
|
status_t fStatus;
|
||||||
|
BEntry fAccountFile;
|
||||||
|
|
||||||
|
int32 fAccountID;
|
||||||
|
|
||||||
|
BString fAccountName;
|
||||||
|
BString fRealName;
|
||||||
|
BString fReturnAdress;
|
||||||
|
|
||||||
|
MailAddonSettings fInboundSettings;
|
||||||
|
MailAddonSettings fOutboundSettings;
|
||||||
|
|
||||||
|
bool fModified;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class BMailAccounts {
|
||||||
|
public:
|
||||||
|
BMailAccounts();
|
||||||
|
~BMailAccounts();
|
||||||
|
|
||||||
|
static status_t AccountsPath(BPath& path);
|
||||||
|
|
||||||
|
int32 CountAccounts();
|
||||||
|
BMailAccountSettings* AccountAt(int32 index);
|
||||||
|
|
||||||
|
BMailAccountSettings* AccountByID(int32 id);
|
||||||
|
BMailAccountSettings* AccountByName(const char* name);
|
||||||
|
private:
|
||||||
|
BObjectList<BMailAccountSettings> fAccounts;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif /* ZOIDBERG_MAIL_SETTINGS_H */
|
#endif /* ZOIDBERG_MAIL_SETTINGS_H */
|
||||||
|
|||||||
@@ -42,8 +42,8 @@ class BMailFileConfigView : public BFileControl
|
|||||||
public:
|
public:
|
||||||
BMailFileConfigView(const char *label,const char *name,bool useMeta = false,const char *defaultPath = NULL,uint32 flavors = B_DIRECTORY_NODE);
|
BMailFileConfigView(const char *label,const char *name,bool useMeta = false,const char *defaultPath = NULL,uint32 flavors = B_DIRECTORY_NODE);
|
||||||
|
|
||||||
void SetTo(BMessage *archive,BMessage *metadata);
|
void SetTo(const BMessage *archive, BMessage *metadata);
|
||||||
virtual status_t Archive(BMessage *into,bool deep = true) const;
|
virtual status_t Archive(BMessage *into, bool deep = true) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BMessage *fMeta;
|
BMessage *fMeta;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
#define PASSWORD_LENGTH 32
|
#define PASSWORD_LENGTH 32
|
||||||
|
|
||||||
|
|
||||||
char *get_passwd(BMessage *msg,const char *name);
|
char *get_passwd(const BMessage *msg,const char *name);
|
||||||
bool set_passwd(BMessage *msg,const char *name,const char *password);
|
bool set_passwd(BMessage *msg,const char *name,const char *password);
|
||||||
|
|
||||||
void passwd_crypt(char *in,char *out,int length);
|
void passwd_crypt(char *in,char *out,int length);
|
||||||
|
|||||||
@@ -72,6 +72,8 @@ ssize_t readfoldedline(BPositionIO &in, char **buffer, size_t *buflen);
|
|||||||
// start with a buffer of size *buflen
|
// start with a buffer of size *buflen
|
||||||
|
|
||||||
status_t parse_header(BMessage &headers, BPositionIO &input);
|
status_t parse_header(BMessage &headers, BPositionIO &input);
|
||||||
|
status_t extract_from_header(const BString& header, const BString& field,
|
||||||
|
BString& target);
|
||||||
|
|
||||||
void extract_address(BString &address);
|
void extract_address(BString &address);
|
||||||
// retrieves the mail address only from an address header formatted field
|
// retrieves the mail address only from an address header formatted field
|
||||||
|
|||||||
@@ -1,610 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2001-2003 Dr. Zoidberg Enterprises. All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
//! Runs the mail inbound and outbound chains
|
|
||||||
|
|
||||||
|
|
||||||
#include <List.h>
|
|
||||||
#include <OS.h>
|
|
||||||
#include <Path.h>
|
|
||||||
#include <image.h>
|
|
||||||
#include <Entry.h>
|
|
||||||
#include <File.h>
|
|
||||||
#include <String.h>
|
|
||||||
#include <Alert.h>
|
|
||||||
#include <Directory.h>
|
|
||||||
#include <Application.h>
|
|
||||||
#include <Locker.h>
|
|
||||||
#include <MessageQueue.h>
|
|
||||||
#include <MessageFilter.h>
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include <MDRLanguage.h>
|
|
||||||
|
|
||||||
class _EXPORT BMailChainRunner;
|
|
||||||
|
|
||||||
#include <ChainRunner.h>
|
|
||||||
#include <status.h>
|
|
||||||
#include <StringList.h>
|
|
||||||
#include "ErrorLogWindow.h"
|
|
||||||
|
|
||||||
struct filter_image {
|
|
||||||
BMessage *settings;
|
|
||||||
BMailFilter *filter;
|
|
||||||
image_id id;
|
|
||||||
};
|
|
||||||
|
|
||||||
BLocker list_lock("mdr_chainrunner_lock");
|
|
||||||
BList running_chains, running_chain_pointers;
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
show_error(alert_type type, const char *message, const char *tag)
|
|
||||||
{
|
|
||||||
static ErrorLogWindow *window = NULL;
|
|
||||||
static BLocker lock("error window");
|
|
||||||
|
|
||||||
lock.Lock();
|
|
||||||
|
|
||||||
if (window == NULL) {
|
|
||||||
window = new ErrorLogWindow(BRect(200, 200, 500, 250),
|
|
||||||
"Mail daemon status log", B_TITLED_WINDOW);
|
|
||||||
}
|
|
||||||
|
|
||||||
lock.Unlock();
|
|
||||||
|
|
||||||
window->AddError(type, message, tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
|
||||||
|
|
||||||
|
|
||||||
_EXPORT BMailChainRunner *
|
|
||||||
GetMailChainRunner(int32 chain_id, BMailStatusWindow *status, bool selfDestruct)
|
|
||||||
{
|
|
||||||
list_lock.Lock();
|
|
||||||
if (running_chains.HasItem((void *)(chain_id))) {
|
|
||||||
BMailChainRunner *runner = (BMailChainRunner *)running_chain_pointers.ItemAt(running_chains.IndexOf((void *)(chain_id)));
|
|
||||||
list_lock.Unlock();
|
|
||||||
return runner;
|
|
||||||
}
|
|
||||||
list_lock.Unlock();
|
|
||||||
|
|
||||||
BMailChainRunner *runner = new BMailChainRunner(GetMailChain(chain_id), status,
|
|
||||||
selfDestruct, false, selfDestruct);
|
|
||||||
|
|
||||||
runner->RunChain();
|
|
||||||
return runner;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class DeathFilter : public BMessageFilter {
|
|
||||||
public:
|
|
||||||
DeathFilter()
|
|
||||||
: BMessageFilter(B_QUIT_REQUESTED)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual filter_result Filter(BMessage *, BHandler **)
|
|
||||||
{
|
|
||||||
be_app->MessageReceived(new BMessage('enda')); //---Stop new chains from starting
|
|
||||||
|
|
||||||
list_lock.Lock();
|
|
||||||
for (int32 i = 0; i < running_chain_pointers.CountItems(); i++)
|
|
||||||
((BMailChainRunner *)(running_chain_pointers.ItemAt(i)))->Stop();
|
|
||||||
list_lock.Unlock();
|
|
||||||
|
|
||||||
while(running_chains.CountItems() > 0)
|
|
||||||
snooze(10000); // 1/100th of a second to avoid wasting CPU.
|
|
||||||
|
|
||||||
return B_DISPATCH_MESSAGE;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
BMailChainRunner::BMailChainRunner(BMailChain *chain, BMailStatusWindow *status,
|
|
||||||
bool selfDestruct, bool saveChain, bool destructChain)
|
|
||||||
: BLooper(chain->Name()),
|
|
||||||
_chain(chain),
|
|
||||||
destroy_self(selfDestruct),
|
|
||||||
destroy_chain(destructChain),
|
|
||||||
save_chain(saveChain),
|
|
||||||
_status(status),
|
|
||||||
_statview(NULL),
|
|
||||||
suicide(false)
|
|
||||||
{
|
|
||||||
static DeathFilter *filter = NULL;
|
|
||||||
|
|
||||||
if (filter == NULL)
|
|
||||||
be_app->AddFilter(filter = new DeathFilter);
|
|
||||||
|
|
||||||
list_lock.Lock();
|
|
||||||
if (running_chains.HasItem((void *)(_chain->ID())))
|
|
||||||
suicide = true;
|
|
||||||
running_chains.AddItem((void *)(_chain->ID()));
|
|
||||||
running_chain_pointers.AddItem(this);
|
|
||||||
list_lock.Unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BMailChainRunner::~BMailChainRunner()
|
|
||||||
{
|
|
||||||
//--- Delete any remaining callbacks
|
|
||||||
for (int32 i = message_cb.CountItems();i-- > 0;)
|
|
||||||
delete (BMailChainCallback *)message_cb.ItemAt(i);
|
|
||||||
for (int32 i = process_cb.CountItems();i-- > 0;)
|
|
||||||
delete (BMailChainCallback *)process_cb.ItemAt(i);
|
|
||||||
for (int32 i = chain_cb.CountItems();i-- > 0;)
|
|
||||||
delete (BMailChainCallback *)chain_cb.ItemAt(i);
|
|
||||||
|
|
||||||
//--- Delete any filter images
|
|
||||||
for (int32 i = 0; i < addons.CountItems(); i++) {
|
|
||||||
filter_image *image = (filter_image *)(addons.ItemAt(i));
|
|
||||||
delete image->filter;
|
|
||||||
delete image->settings;
|
|
||||||
|
|
||||||
unload_add_on(image->id);
|
|
||||||
|
|
||||||
delete image;
|
|
||||||
}
|
|
||||||
|
|
||||||
//--- Remove ourselves from the window if we haven't been already
|
|
||||||
if ((_status != NULL) && (_statview != NULL)) {
|
|
||||||
_status->Lock();
|
|
||||||
if (_statview->Window())
|
|
||||||
_status->RemoveView(_statview);
|
|
||||||
|
|
||||||
delete _statview;
|
|
||||||
_status->Unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
//--- Remove ourselves from the lists
|
|
||||||
list_lock.Lock();
|
|
||||||
running_chains.RemoveItem((void *)(_chain->ID()));
|
|
||||||
running_chain_pointers.RemoveItem(this);
|
|
||||||
list_lock.Unlock();
|
|
||||||
|
|
||||||
//--- And delete our chain
|
|
||||||
if (destroy_chain)
|
|
||||||
delete _chain;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
BMailChainRunner::RegisterMessageCallback(BMailChainCallback *callback)
|
|
||||||
{
|
|
||||||
message_cb.AddItem(callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
BMailChainRunner::RegisterProcessCallback(BMailChainCallback *callback)
|
|
||||||
{
|
|
||||||
process_cb.AddItem(callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
BMailChainRunner::RegisterChainCallback(BMailChainCallback *callback)
|
|
||||||
{
|
|
||||||
chain_cb.AddItem(callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BMailChain *
|
|
||||||
BMailChainRunner::Chain()
|
|
||||||
{
|
|
||||||
return _chain;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
BMailChainRunner::RunChain(bool asynchronous)
|
|
||||||
{
|
|
||||||
if (suicide) {
|
|
||||||
Quit();
|
|
||||||
return B_NAME_IN_USE;
|
|
||||||
}
|
|
||||||
|
|
||||||
Run();
|
|
||||||
|
|
||||||
PostMessage('INIT');
|
|
||||||
|
|
||||||
if (!asynchronous) {
|
|
||||||
status_t result;
|
|
||||||
wait_for_thread(Thread(),&result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
BMailChainRunner::CallCallbacksFor(BList &list, status_t code)
|
|
||||||
{
|
|
||||||
for (int32 i = 0; i < list.CountItems(); i++) {
|
|
||||||
BMailChainCallback *callback = static_cast<BMailChainCallback *>(list.ItemAt(i));
|
|
||||||
|
|
||||||
callback->Callback(code);
|
|
||||||
delete callback;
|
|
||||||
}
|
|
||||||
list.MakeEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
BMailChainRunner::Init()
|
|
||||||
{
|
|
||||||
status_t big_err = B_OK;
|
|
||||||
BString desc;
|
|
||||||
entry_ref addon;
|
|
||||||
|
|
||||||
MDR_DIALECT_CHOICE (
|
|
||||||
desc << ((_chain->ChainDirection() == inbound) ? "Fetching" : "Sending") << " mail for " << _chain->Name(),
|
|
||||||
desc << _chain->Name() << ((_chain->ChainDirection() == inbound) ? "より受信中..." : "へ送信中...")
|
|
||||||
);
|
|
||||||
|
|
||||||
_status->Lock();
|
|
||||||
_statview = _status->NewStatusView(desc.String(), _chain->ChainDirection() == outbound);
|
|
||||||
_status->Unlock();
|
|
||||||
|
|
||||||
BMessage settings;
|
|
||||||
for (int32 i = 0; _chain->GetFilter(i, &settings, &addon) >= B_OK; i++) {
|
|
||||||
BPath path(&addon);
|
|
||||||
BMailFilter *(*instantiate)(BMessage*, BMailChainRunner*);
|
|
||||||
|
|
||||||
image_id imageId = load_add_on(path.Path());
|
|
||||||
|
|
||||||
if (imageId < B_OK) {
|
|
||||||
BString error;
|
|
||||||
MDR_DIALECT_CHOICE (
|
|
||||||
error << "Error loading the mail addon "
|
|
||||||
<< path.Path() << " from chain " << _chain->Name()
|
|
||||||
<< ": " << strerror(imageId);
|
|
||||||
ShowError(error.String());,
|
|
||||||
error << "メールアドオン " << path.Path()
|
|
||||||
<< " を " << _chain->Name()
|
|
||||||
<< "から読み込む際にエラーが発生しました: "
|
|
||||||
<< strerror(imageId);
|
|
||||||
|
|
||||||
ShowError(error.String());
|
|
||||||
)
|
|
||||||
return imageId;
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t err = get_image_symbol(imageId,
|
|
||||||
"instantiate_mailfilter", B_SYMBOL_TYPE_TEXT,
|
|
||||||
(void **)&instantiate);
|
|
||||||
if (err < B_OK) {
|
|
||||||
BString error;
|
|
||||||
MDR_DIALECT_CHOICE (
|
|
||||||
error << "Error loading the mail addon " << path.Path()
|
|
||||||
<< " from chain " << _chain->Name()
|
|
||||||
<< ": the addon does not seem to be a mail addon (missing symbol instantiate_mailfilter).";
|
|
||||||
ShowError(error.String());,
|
|
||||||
error << "メールアドオン " << path.Path() << " を "
|
|
||||||
<< _chain->Name() << "から読み込む際にエラーが発生しました"
|
|
||||||
<< ": そのアドオンはメールアドオンではないようです(instantiate_mailfilterシンボルがありません)";
|
|
||||||
ShowError(error.String());
|
|
||||||
)
|
|
||||||
|
|
||||||
err = -1;
|
|
||||||
|
|
||||||
// TODO: unload_add_on() ?
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
filter_image* image = new filter_image;
|
|
||||||
|
|
||||||
image->id = imageId;
|
|
||||||
image->settings = new BMessage(settings);
|
|
||||||
image->settings->AddInt32("chain", _chain->ID());
|
|
||||||
image->filter = (*instantiate)(image->settings, this);
|
|
||||||
|
|
||||||
addons.AddItem(image);
|
|
||||||
|
|
||||||
if ((big_err = image->filter->InitCheck()) != B_OK) {
|
|
||||||
//printf("InitCheck() failed (%s) in add-on %s\n",strerror(big_err),path.Path());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return big_err;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
BMailChainRunner::MessageReceived(BMessage *msg)
|
|
||||||
{
|
|
||||||
switch (msg->what) {
|
|
||||||
case 'INIT':
|
|
||||||
if (Init() == B_OK)
|
|
||||||
break;
|
|
||||||
case B_QUIT_REQUESTED:
|
|
||||||
{
|
|
||||||
CallCallbacksFor(chain_cb, B_OK);
|
|
||||||
// who knows what the code was?
|
|
||||||
|
|
||||||
BMessage settings;
|
|
||||||
entry_ref addon;
|
|
||||||
|
|
||||||
for (int32 i = 0; i < addons.CountItems(); i++) {
|
|
||||||
filter_image *image = (filter_image *)(addons.ItemAt(i));
|
|
||||||
delete image->filter;
|
|
||||||
|
|
||||||
if (save_chain) {
|
|
||||||
image->settings->RemoveName("chain");
|
|
||||||
_chain->GetFilter(i,&settings,&addon);
|
|
||||||
_chain->SetFilter(i,*(image->settings),addon);
|
|
||||||
}
|
|
||||||
|
|
||||||
delete image->settings;
|
|
||||||
|
|
||||||
unload_add_on(image->id);
|
|
||||||
|
|
||||||
delete image;
|
|
||||||
}
|
|
||||||
|
|
||||||
addons.MakeEmpty();
|
|
||||||
|
|
||||||
if ((_status != NULL) && (_statview != NULL)) {
|
|
||||||
_status->Lock();
|
|
||||||
if (_statview->Window())
|
|
||||||
_status->RemoveView(_statview);
|
|
||||||
else
|
|
||||||
delete _statview;
|
|
||||||
|
|
||||||
_statview = NULL;
|
|
||||||
_status->Unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*list_lock.Lock();
|
|
||||||
running_chains.RemoveItem((void *)(_chain->ID()));
|
|
||||||
running_chain_pointers.RemoveItem(this);
|
|
||||||
list_lock.Unlock();*/
|
|
||||||
|
|
||||||
if (save_chain)
|
|
||||||
_chain->Save();
|
|
||||||
|
|
||||||
if (destroy_self)
|
|
||||||
Quit();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'GETM':
|
|
||||||
{
|
|
||||||
BStringList list;
|
|
||||||
msg->FindFlat("messages",&list);
|
|
||||||
_statview->SetTotalItems(list.CountItems());
|
|
||||||
_statview->SetMaximum(msg->FindInt32("bytes"));
|
|
||||||
get_messages(&list);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'GTSM':
|
|
||||||
{
|
|
||||||
const char *uid;
|
|
||||||
status_t err = B_OK;
|
|
||||||
msg->FindString("uid",&uid);
|
|
||||||
BEntry *entry = new BEntry(msg->FindString("into"));
|
|
||||||
_statview->SetTotalItems(1);
|
|
||||||
_statview->SetMaximum(msg->FindInt32("bytes"));
|
|
||||||
BPositionIO *file = new BFile(entry, B_READ_WRITE | B_CREATE_FILE);
|
|
||||||
BPath *folder = new BPath;
|
|
||||||
BMessage *headers = new BMessage;
|
|
||||||
headers->AddBool("ENTIRE_MESSAGE",true);
|
|
||||||
|
|
||||||
for (int32 j = 0; j < addons.CountItems(); j++) {
|
|
||||||
struct filter_image *current = (struct filter_image *)(addons.ItemAt(j));
|
|
||||||
|
|
||||||
err = current->filter->ProcessMailMessage(&file,entry,headers,folder,uid);
|
|
||||||
if (err != B_OK)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
CallCallbacksFor(message_cb, err);
|
|
||||||
|
|
||||||
delete file;
|
|
||||||
delete entry;
|
|
||||||
delete headers;
|
|
||||||
delete folder;
|
|
||||||
|
|
||||||
CallCallbacksFor(process_cb, err);
|
|
||||||
|
|
||||||
if (save_chain) {
|
|
||||||
entry_ref addon;
|
|
||||||
BMessage settings;
|
|
||||||
for (int32 i = 0; i < addons.CountItems(); i++) {
|
|
||||||
filter_image *image = (filter_image *)(addons.ItemAt(i));
|
|
||||||
|
|
||||||
BMessage *temp = new BMessage(*(image->settings));
|
|
||||||
temp->RemoveName("chain");
|
|
||||||
_chain->GetFilter(i, &settings, &addon);
|
|
||||||
_chain->SetFilter(i, *temp, addon);
|
|
||||||
|
|
||||||
delete temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
_chain->Save();
|
|
||||||
}
|
|
||||||
|
|
||||||
ResetProgress();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
BMailChainRunner::QuitRequested()
|
|
||||||
{
|
|
||||||
Stop();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
BMailChainRunner::get_messages(BStringList *list)
|
|
||||||
{
|
|
||||||
const char *uid;
|
|
||||||
|
|
||||||
status_t err = B_OK;
|
|
||||||
const char *glort;
|
|
||||||
bool using_tmp = (_chain->MetaData()->FindString("path",&glort) < B_OK);
|
|
||||||
|
|
||||||
BDirectory tmp(using_tmp ? "/tmp" : glort);
|
|
||||||
|
|
||||||
for (int i = 0; i < list->CountItems(); i++) {
|
|
||||||
uid = (*list)[i];
|
|
||||||
|
|
||||||
char *path;
|
|
||||||
if (using_tmp)
|
|
||||||
path = tempnam("/tmp","mail_temp_");
|
|
||||||
else {
|
|
||||||
BPath pathy(glort);
|
|
||||||
pathy.Append("Downloading");
|
|
||||||
path = (char *)malloc(B_PATH_NAME_LENGTH);
|
|
||||||
sprintf(path,"%s (%s: %ld)...",pathy.Path(), _chain->Name(), _chain->ID());
|
|
||||||
}
|
|
||||||
|
|
||||||
BEntry *entry = new BEntry(path);
|
|
||||||
free(path);
|
|
||||||
BPositionIO *file = (_chain->ChainDirection() == inbound) ? new BFile(entry, B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE) : NULL;
|
|
||||||
BPath *folder = new BPath;
|
|
||||||
BMessage *headers = new BMessage;
|
|
||||||
|
|
||||||
for (int32 j = 0; j < addons.CountItems(); j++) {
|
|
||||||
struct filter_image *current = (struct filter_image *)(addons.ItemAt(j));
|
|
||||||
|
|
||||||
err = current->filter->ProcessMailMessage(&file,entry,headers,folder,uid);
|
|
||||||
|
|
||||||
if (err != B_OK)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
CallCallbacksFor(message_cb, err);
|
|
||||||
|
|
||||||
if (err == B_MAIL_DISCARD)
|
|
||||||
entry->Remove();
|
|
||||||
|
|
||||||
delete file;
|
|
||||||
delete entry;
|
|
||||||
delete headers;
|
|
||||||
delete folder;
|
|
||||||
|
|
||||||
if (err == B_MAIL_END_FETCH || err == B_MAIL_END_CHAIN)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
CallCallbacksFor(process_cb, err);
|
|
||||||
|
|
||||||
if (save_chain) {
|
|
||||||
|
|
||||||
entry_ref addon;
|
|
||||||
BMessage settings;
|
|
||||||
for (int32 i = 0; i < addons.CountItems(); i++) {
|
|
||||||
filter_image *image = (filter_image *)(addons.ItemAt(i));
|
|
||||||
|
|
||||||
BMessage *temp = new BMessage(*(image->settings));
|
|
||||||
temp->RemoveName("chain");
|
|
||||||
_chain->GetFilter(i,&settings,&addon);
|
|
||||||
_chain->SetFilter(i,*temp,addon);
|
|
||||||
|
|
||||||
delete temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
_chain->Save();
|
|
||||||
}
|
|
||||||
|
|
||||||
ResetProgress();
|
|
||||||
|
|
||||||
if (err == B_MAIL_END_CHAIN)
|
|
||||||
Stop();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
BMailChainRunner::Stop(bool kill)
|
|
||||||
{
|
|
||||||
if (kill) {
|
|
||||||
BMessageQueue *looper_queue = MessageQueue();
|
|
||||||
looper_queue->Lock();
|
|
||||||
BMessage *msg;
|
|
||||||
while ((msg = looper_queue->NextMessage()))
|
|
||||||
delete msg; //-- Ensure STOP makes the front of the queue
|
|
||||||
|
|
||||||
PostMessage(B_QUIT_REQUESTED);
|
|
||||||
looper_queue->Unlock();
|
|
||||||
} else {
|
|
||||||
PostMessage(B_QUIT_REQUESTED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
BMailChainRunner::GetMessages(BStringList *list, int32 bytes)
|
|
||||||
{
|
|
||||||
if (list->CountItems() < 1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
BMessage msg('GETM');
|
|
||||||
msg.AddFlat("messages",list);
|
|
||||||
msg.AddInt32("bytes",bytes);
|
|
||||||
PostMessage(&msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
BMailChainRunner::GetSingleMessage(const char *uid, int32 length, BPath *into)
|
|
||||||
{
|
|
||||||
BMessage msg('GTSM');
|
|
||||||
msg.AddString("uid",uid);
|
|
||||||
msg.AddInt32("bytes",length);
|
|
||||||
msg.AddString("into",into->Path());
|
|
||||||
PostMessage(&msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
BMailChainRunner::ReportProgress(int bytes, int messages, const char *message)
|
|
||||||
{
|
|
||||||
if (bytes != 0)
|
|
||||||
_statview->AddProgress(bytes);
|
|
||||||
|
|
||||||
for (int i = 0; i < messages; i++)
|
|
||||||
_statview->AddItem();
|
|
||||||
|
|
||||||
if (message != NULL)
|
|
||||||
_statview->SetMessage(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
BMailChainRunner::ResetProgress(const char *message)
|
|
||||||
{
|
|
||||||
_statview->Reset();
|
|
||||||
if (message != NULL)
|
|
||||||
_statview->SetMessage(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
BMailChainRunner::ShowError(const char *error)
|
|
||||||
{
|
|
||||||
BString tag = Chain()->Name();
|
|
||||||
tag << ": ";
|
|
||||||
show_error(B_WARNING_ALERT, error, tag.String());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
BMailChainRunner::ShowMessage(const char *error)
|
|
||||||
{
|
|
||||||
BString tag = Chain()->Name();
|
|
||||||
tag << ": ";
|
|
||||||
show_error(B_INFO_ALERT, error, tag.String());
|
|
||||||
}
|
|
||||||
@@ -145,7 +145,7 @@ BMailFileConfigView::BMailFileConfigView(const char *label,const char *name,bool
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void BMailFileConfigView::SetTo(BMessage *archive, BMessage *meta)
|
void BMailFileConfigView::SetTo(const BMessage *archive, BMessage *meta)
|
||||||
{
|
{
|
||||||
fMeta = meta;
|
fMeta = meta;
|
||||||
BString path = (fUseMeta ? meta : archive)->FindString(fName);
|
BString path = (fUseMeta ? meta : archive)->FindString(fName);
|
||||||
|
|||||||
@@ -0,0 +1,204 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, Haiku, Inc. All rights reserved.
|
||||||
|
* Copyright 2011, Clemens Zeidler <[email protected]>
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "HaikuMailFormatFilter.h"
|
||||||
|
|
||||||
|
#include <Directory.h>
|
||||||
|
|
||||||
|
#include <E-mail.h>
|
||||||
|
#include <NodeInfo.h>
|
||||||
|
|
||||||
|
#include <mail_util.h>
|
||||||
|
#include <NodeMessage.h>
|
||||||
|
|
||||||
|
|
||||||
|
struct mail_header_field
|
||||||
|
{
|
||||||
|
const char *rfc_name;
|
||||||
|
|
||||||
|
const char *attr_name;
|
||||||
|
type_code attr_type;
|
||||||
|
// currently either B_STRING_TYPE and B_TIME_TYPE
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static const mail_header_field gDefaultFields[] =
|
||||||
|
{
|
||||||
|
{ "To", B_MAIL_ATTR_TO, B_STRING_TYPE },
|
||||||
|
{ "From", B_MAIL_ATTR_FROM, B_STRING_TYPE },
|
||||||
|
{ "Cc", B_MAIL_ATTR_CC, B_STRING_TYPE },
|
||||||
|
{ "Date", B_MAIL_ATTR_WHEN, B_TIME_TYPE },
|
||||||
|
{ "Delivery-Date", B_MAIL_ATTR_WHEN, B_TIME_TYPE },
|
||||||
|
{ "Reply-To", B_MAIL_ATTR_REPLY, B_STRING_TYPE },
|
||||||
|
{ "Subject", B_MAIL_ATTR_SUBJECT, B_STRING_TYPE },
|
||||||
|
{ "X-Priority", B_MAIL_ATTR_PRIORITY, B_STRING_TYPE }, // Priorities with prefered
|
||||||
|
{ "Priority", B_MAIL_ATTR_PRIORITY, B_STRING_TYPE }, // one first - the numeric
|
||||||
|
{ "X-Msmail-Priority", B_MAIL_ATTR_PRIORITY, B_STRING_TYPE }, // one (has more levels).
|
||||||
|
{ "Mime-Version", B_MAIL_ATTR_MIME, B_STRING_TYPE },
|
||||||
|
{ "STATUS", B_MAIL_ATTR_STATUS, B_STRING_TYPE },
|
||||||
|
{ "THREAD", "MAIL:thread", B_STRING_TYPE }, //---Not supposed to be used for this (we add it in Parser), but why not?
|
||||||
|
{ "NAME", B_MAIL_ATTR_NAME, B_STRING_TYPE },
|
||||||
|
{ NULL, NULL, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
HaikuMailFormatFilter::HaikuMailFormatFilter(MailProtocol& protocol,
|
||||||
|
BMailAccountSettings* settings)
|
||||||
|
:
|
||||||
|
MailFilter(protocol, NULL),
|
||||||
|
|
||||||
|
fAccountId(settings->AccountID())
|
||||||
|
{
|
||||||
|
const BMessage* outboundSettings = &settings->OutboundSettings().Settings();
|
||||||
|
outboundSettings->FindString("destination", &fOutboundDirectory);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
HaikuMailFormatFilter::HeaderFetched(const entry_ref& ref, BFile* file)
|
||||||
|
{
|
||||||
|
file->Seek(0, SEEK_SET);
|
||||||
|
|
||||||
|
BMessage attributes;
|
||||||
|
// TODO attributes.AddInt32(B_MAIL_ATTR_CONTENT, length);
|
||||||
|
attributes.AddInt32("MAIL:account", fAccountId);
|
||||||
|
|
||||||
|
BString header;
|
||||||
|
off_t size;
|
||||||
|
if (file->GetSize(&size) == B_OK) {
|
||||||
|
char* buffer = header.LockBuffer(size);
|
||||||
|
file->Read(buffer, size);
|
||||||
|
header.UnlockBuffer(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; gDefaultFields[i].rfc_name; ++i) {
|
||||||
|
BString target;
|
||||||
|
status_t status = extract_from_header(header,
|
||||||
|
gDefaultFields[i].rfc_name, target);
|
||||||
|
if (status != B_OK)
|
||||||
|
continue;
|
||||||
|
switch (gDefaultFields[i].attr_type){
|
||||||
|
case B_STRING_TYPE:
|
||||||
|
attributes.AddString(gDefaultFields[i].attr_name, target);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_TIME_TYPE:
|
||||||
|
{
|
||||||
|
time_t when;
|
||||||
|
when = ParseDateWithTimeZone(target);
|
||||||
|
if (when == -1)
|
||||||
|
when = time(NULL); // Use current time if it's undecodable.
|
||||||
|
attributes.AddData(B_MAIL_ATTR_WHEN, B_TIME_TYPE, &when,
|
||||||
|
sizeof(when));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(*file) << attributes;
|
||||||
|
|
||||||
|
|
||||||
|
// Generate a file name for the incoming message. See also
|
||||||
|
// Message::RenderTo which does a similar thing for outgoing messages.
|
||||||
|
|
||||||
|
BString name = attributes.FindString("MAIL:subject");
|
||||||
|
SubjectToThread(name); // Extract the core subject words.
|
||||||
|
if (name.Length() <= 0)
|
||||||
|
name = "No Subject";
|
||||||
|
if (name[0] == '.')
|
||||||
|
name.Prepend ("_"); // Avoid hidden files, starting with a dot.
|
||||||
|
|
||||||
|
// Convert the date into a year-month-day fixed digit width format, so that
|
||||||
|
// sorting by file name will give all the messages with the same subject in
|
||||||
|
// order of date.
|
||||||
|
time_t dateAsTime = 0;
|
||||||
|
const time_t* datePntr;
|
||||||
|
ssize_t dateSize;
|
||||||
|
char numericDateString [40];
|
||||||
|
struct tm timeFields;
|
||||||
|
|
||||||
|
if (attributes.FindData(B_MAIL_ATTR_WHEN, B_TIME_TYPE,
|
||||||
|
(const void**)&datePntr, &dateSize) == B_OK)
|
||||||
|
dateAsTime = *datePntr;
|
||||||
|
localtime_r(&dateAsTime, &timeFields);
|
||||||
|
sprintf(numericDateString, "%04d%02d%02d%02d%02d%02d",
|
||||||
|
timeFields.tm_year + 1900,
|
||||||
|
timeFields.tm_mon + 1,
|
||||||
|
timeFields.tm_mday,
|
||||||
|
timeFields.tm_hour,
|
||||||
|
timeFields.tm_min,
|
||||||
|
timeFields.tm_sec);
|
||||||
|
name << " " << numericDateString;
|
||||||
|
|
||||||
|
BString worker = attributes.FindString("MAIL:from");
|
||||||
|
extract_address_name(worker);
|
||||||
|
name << " " << worker;
|
||||||
|
|
||||||
|
name.Truncate(222); // reserve space for the uniquer
|
||||||
|
|
||||||
|
// Get rid of annoying characters which are hard to use in the shell.
|
||||||
|
name.ReplaceAll('/', '_');
|
||||||
|
name.ReplaceAll('\'', '_');
|
||||||
|
name.ReplaceAll('"', '_');
|
||||||
|
name.ReplaceAll('!', '_');
|
||||||
|
name.ReplaceAll('<', '_');
|
||||||
|
name.ReplaceAll('>', '_');
|
||||||
|
while (name.FindFirst(" ") >= 0) // Remove multiple spaces.
|
||||||
|
name.Replace(" " /* Old */, " " /* New */, 1024 /* Count */);
|
||||||
|
|
||||||
|
worker = name;
|
||||||
|
int32 identicalNumber = 1;
|
||||||
|
status_t status = _SetFileName(ref, worker);
|
||||||
|
while (status == B_FILE_EXISTS) {
|
||||||
|
identicalNumber++;
|
||||||
|
|
||||||
|
worker = name;
|
||||||
|
worker << "_" << identicalNumber;
|
||||||
|
status = _SetFileName(ref, worker);
|
||||||
|
}
|
||||||
|
if (status < B_OK)
|
||||||
|
printf("FolderFilter::ProcessMailMessage: could not rename mail (%s)! "
|
||||||
|
"(should be: %s)\n",strerror(status), worker.String());
|
||||||
|
else {
|
||||||
|
entry_ref to(ref.device, ref.directory, worker);
|
||||||
|
fMailProtocol.FileRenamed(ref, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
BNodeInfo info(file);
|
||||||
|
info.SetType("text/x-partial-email");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
HaikuMailFormatFilter::BodyFetched(const entry_ref& ref, BFile* file)
|
||||||
|
{
|
||||||
|
BNodeInfo info(file);
|
||||||
|
info.SetType(B_MAIL_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
HaikuMailFormatFilter::MessageSent(const entry_ref& ref, BFile* file)
|
||||||
|
{
|
||||||
|
mail_flags flags = B_MAIL_SENT;
|
||||||
|
file->WriteAttr(B_MAIL_ATTR_FLAGS, B_INT32_TYPE, 0, &flags, sizeof(int32));
|
||||||
|
file->WriteAttr(B_MAIL_ATTR_STATUS, B_STRING_TYPE, 0, "Sent", 5);
|
||||||
|
|
||||||
|
if (fOutboundDirectory == "")
|
||||||
|
return;
|
||||||
|
create_directory(fOutboundDirectory, 755);
|
||||||
|
BDirectory dir(fOutboundDirectory);
|
||||||
|
fMailProtocol.Looper()->TriggerFileMove(ref, dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
HaikuMailFormatFilter::_SetFileName(const entry_ref& ref, const BString& name)
|
||||||
|
{
|
||||||
|
BEntry entry(&ref);
|
||||||
|
return entry.Rename(name);
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, Haiku, Inc. All rights reserved.
|
||||||
|
* Copyright 2011, Clemens Zeidler <[email protected]>
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef IMAP_LISTENER_H
|
||||||
|
#define IMAP_LISTENER_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "MailProtocol.h"
|
||||||
|
|
||||||
|
#include <String.h>
|
||||||
|
|
||||||
|
|
||||||
|
class HaikuMailFormatFilter : public MailFilter {
|
||||||
|
public:
|
||||||
|
HaikuMailFormatFilter(MailProtocol& protocol,
|
||||||
|
BMailAccountSettings* settings);
|
||||||
|
|
||||||
|
void HeaderFetched(const entry_ref& ref,
|
||||||
|
BFile* file);
|
||||||
|
void BodyFetched(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);
|
||||||
|
|
||||||
|
int32 fAccountId;
|
||||||
|
BString fOutboundDirectory;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // IMAP_LISTENER_H
|
||||||
+1
-18
@@ -1,10 +1,5 @@
|
|||||||
SubDir HAIKU_TOP src kits mail ;
|
SubDir HAIKU_TOP src kits mail ;
|
||||||
|
|
||||||
SetSubDirSupportedPlatformsBeOSCompatible ;
|
|
||||||
|
|
||||||
if $(TARGET_PLATFORM) != haiku {
|
|
||||||
UsePublicHeaders mail ;
|
|
||||||
}
|
|
||||||
UsePrivateHeaders mail shared ;
|
UsePrivateHeaders mail shared ;
|
||||||
UsePublicHeaders [ FDirName add-ons mail_daemon ] ;
|
UsePublicHeaders [ FDirName add-ons mail_daemon ] ;
|
||||||
|
|
||||||
@@ -17,19 +12,13 @@ SubDirC++Flags -D_BUILDING_mail=1 ;
|
|||||||
UsePrivateHeaders textencoding ;
|
UsePrivateHeaders textencoding ;
|
||||||
|
|
||||||
SharedLibrary libmail.so :
|
SharedLibrary libmail.so :
|
||||||
b_mail_message.cpp
|
|
||||||
c_mail_api.cpp
|
|
||||||
ChainRunner.cpp
|
|
||||||
cpp_abi_base64.c
|
|
||||||
crypt.cpp
|
crypt.cpp
|
||||||
des.c
|
des.c
|
||||||
ErrorLogWindow.cpp
|
|
||||||
FileConfigView.cpp
|
FileConfigView.cpp
|
||||||
|
HaikuMailFormatFilter.cpp
|
||||||
mail_encoding.c
|
mail_encoding.c
|
||||||
mail_util.cpp
|
mail_util.cpp
|
||||||
MailAddon.cpp
|
|
||||||
MailAttachment.cpp
|
MailAttachment.cpp
|
||||||
MailChain.cpp
|
|
||||||
MailComponent.cpp
|
MailComponent.cpp
|
||||||
MailContainer.cpp
|
MailContainer.cpp
|
||||||
MailDaemon.cpp
|
MailDaemon.cpp
|
||||||
@@ -39,8 +28,6 @@ SharedLibrary libmail.so :
|
|||||||
NodeMessage.cpp
|
NodeMessage.cpp
|
||||||
numailkit.cpp
|
numailkit.cpp
|
||||||
ProtocolConfigView.cpp
|
ProtocolConfigView.cpp
|
||||||
RemoteStorageProtocol.cpp
|
|
||||||
StatusWindow.cpp
|
|
||||||
StringList.cpp
|
StringList.cpp
|
||||||
:
|
:
|
||||||
be
|
be
|
||||||
@@ -50,7 +37,3 @@ SharedLibrary libmail.so :
|
|||||||
$(TARGET_NETWORK_LIBS)
|
$(TARGET_NETWORK_LIBS)
|
||||||
$(TARGET_SELECT_UNAME_ETC_LIB)
|
$(TARGET_SELECT_UNAME_ETC_LIB)
|
||||||
;
|
;
|
||||||
|
|
||||||
Package haiku-maildaemon-cvs :
|
|
||||||
libmail.so :
|
|
||||||
boot beos system lib ;
|
|
||||||
|
|||||||
@@ -1,27 +0,0 @@
|
|||||||
/* Filter - the base class for all mail filters
|
|
||||||
**
|
|
||||||
** Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include <String.h>
|
|
||||||
|
|
||||||
class _EXPORT BMailFilter;
|
|
||||||
|
|
||||||
#include <MailAddon.h>
|
|
||||||
|
|
||||||
BMailFilter::BMailFilter(BMessage *)
|
|
||||||
{
|
|
||||||
//----do nothing-----
|
|
||||||
}
|
|
||||||
|
|
||||||
BMailFilter::~BMailFilter()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void BMailFilter::_ReservedFilter1() {}
|
|
||||||
void BMailFilter::_ReservedFilter2() {}
|
|
||||||
void BMailFilter::_ReservedFilter3() {}
|
|
||||||
void BMailFilter::_ReservedFilter4() {}
|
|
||||||
|
|
||||||
@@ -1,512 +0,0 @@
|
|||||||
/* BMailChain - the mail account's inbound and outbound chain
|
|
||||||
**
|
|
||||||
** Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include <Message.h>
|
|
||||||
#include <FindDirectory.h>
|
|
||||||
#include <Directory.h>
|
|
||||||
#include <File.h>
|
|
||||||
#include <Entry.h>
|
|
||||||
#include <Path.h>
|
|
||||||
#include <String.h>
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
class BMailChain;
|
|
||||||
|
|
||||||
namespace MailInternal {
|
|
||||||
status_t WriteMessageFile(const BMessage& archive,
|
|
||||||
const BPath& path, const char* name);
|
|
||||||
}
|
|
||||||
|
|
||||||
#include <MailSettings.h>
|
|
||||||
#include <ChainRunner.h>
|
|
||||||
#include <status.h>
|
|
||||||
|
|
||||||
|
|
||||||
BMailChain::BMailChain(uint32 i)
|
|
||||||
:
|
|
||||||
fId(i),
|
|
||||||
fMetaData(NULL),
|
|
||||||
fStatus(B_OK),
|
|
||||||
fDirection(inbound),
|
|
||||||
fSettingsCount(0),
|
|
||||||
fAddonsCount(0)
|
|
||||||
{
|
|
||||||
fName[0] = 0;
|
|
||||||
Reload();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BMailChain::BMailChain(BMessage* settings)
|
|
||||||
:
|
|
||||||
fId(settings->FindInt32("id")),
|
|
||||||
fMetaData(NULL),
|
|
||||||
fStatus(B_OK),
|
|
||||||
fDirection(inbound),
|
|
||||||
fSettingsCount(0),
|
|
||||||
fAddonsCount(0)
|
|
||||||
{
|
|
||||||
fName[0] = 0;
|
|
||||||
Load(settings);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BMailChain::~BMailChain()
|
|
||||||
{
|
|
||||||
delete fMetaData;
|
|
||||||
|
|
||||||
for (int32 i = 0; fFilterSettings.ItemAt(i); i++)
|
|
||||||
delete (BMessage*)fFilterSettings.ItemAt(i);
|
|
||||||
|
|
||||||
for (int32 i = 0; fFilterAddons.ItemAt(i); i++)
|
|
||||||
delete (entry_ref*)fFilterAddons.ItemAt(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
BMailChain::Load(BMessage* settings)
|
|
||||||
{
|
|
||||||
delete fMetaData;
|
|
||||||
|
|
||||||
fMetaData = new BMessage;
|
|
||||||
if (settings->HasMessage("meta_data"))
|
|
||||||
settings->FindMessage("meta_data", fMetaData);
|
|
||||||
|
|
||||||
const char* n;
|
|
||||||
status_t ret = settings->FindString("name", &n);
|
|
||||||
if (ret == B_OK)
|
|
||||||
strncpy(fName, n, sizeof(fName));
|
|
||||||
else
|
|
||||||
fName[0] = '\0';
|
|
||||||
|
|
||||||
type_code t;
|
|
||||||
settings->GetInfo("filter_settings", &t, (int32*)(&fSettingsCount));
|
|
||||||
settings->GetInfo("filter_addons", &t, (int32*)(&fAddonsCount));
|
|
||||||
if (fSettingsCount != fAddonsCount)
|
|
||||||
return B_MISMATCHED_VALUES;
|
|
||||||
|
|
||||||
for (int i = 0; i < fSettingsCount; i++) {
|
|
||||||
BMessage* filter = new BMessage();
|
|
||||||
entry_ref* ref = new entry_ref();
|
|
||||||
char* addon_path;
|
|
||||||
|
|
||||||
if (settings->FindMessage("filter_settings", i, filter) < B_OK
|
|
||||||
|| ((settings->FindString("filter_addons", i, (const char**)&addon_path) < B_OK
|
|
||||||
|| get_ref_for_path(addon_path, ref) < B_OK)
|
|
||||||
&& settings->FindRef("filter_addons", i, ref) < B_OK)) {
|
|
||||||
delete filter;
|
|
||||||
delete ref;
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fFilterSettings.AddItem(filter)) {
|
|
||||||
delete filter;
|
|
||||||
delete ref;
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fFilterAddons.AddItem(ref)) {
|
|
||||||
fFilterSettings.RemoveItem(filter);
|
|
||||||
delete filter;
|
|
||||||
delete ref;
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
BMailChain::InitCheck() const
|
|
||||||
{
|
|
||||||
if (fSettingsCount != fAddonsCount)
|
|
||||||
return B_MISMATCHED_VALUES;
|
|
||||||
if (fFilterSettings.CountItems() != fSettingsCount
|
|
||||||
|| fFilterAddons.CountItems() != fAddonsCount)
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
if (fStatus < B_OK)
|
|
||||||
return fStatus;
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
BMailChain::Archive(BMessage* archive, bool deep) const
|
|
||||||
{
|
|
||||||
status_t ret = InitCheck();
|
|
||||||
|
|
||||||
if (ret != B_OK && ret != B_FILE_ERROR)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
ret = BArchivable::Archive(archive, deep);
|
|
||||||
if (ret != B_OK)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
ret = archive->AddString("class", "BMailChain");
|
|
||||||
if (ret != B_OK)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
ret = archive->AddInt32("id", fId);
|
|
||||||
if (ret != B_OK)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
ret = archive->AddString("name", fName);
|
|
||||||
if (ret != B_OK)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
ret = archive->AddMessage("meta_data", fMetaData);
|
|
||||||
if (ret != B_OK)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
if (ret == B_OK && deep) {
|
|
||||||
BMessage* settings;
|
|
||||||
entry_ref* ref;
|
|
||||||
|
|
||||||
int32 i;
|
|
||||||
for (i = 0;((settings = (BMessage*)fFilterSettings.ItemAt(i)) != NULL)
|
|
||||||
&& ((ref = (entry_ref*)fFilterAddons.ItemAt(i)) != NULL);
|
|
||||||
++i) {
|
|
||||||
ret = archive->AddMessage("filter_settings", settings);
|
|
||||||
if (ret < B_OK)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
BPath path(ref);
|
|
||||||
if ((ret = path.InitCheck()) < B_OK)
|
|
||||||
return ret;
|
|
||||||
ret = archive->AddString("filter_addons", path.Path());
|
|
||||||
if (ret < B_OK)
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
if (i != fSettingsCount)
|
|
||||||
return B_MISMATCHED_VALUES;
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BArchivable*
|
|
||||||
BMailChain::Instantiate(BMessage* archive)
|
|
||||||
{
|
|
||||||
return validate_instantiation(archive, "BMailChain") ?
|
|
||||||
new BMailChain(archive) : NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
BMailChain::GetPath(BPath& path) const
|
|
||||||
{
|
|
||||||
status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path);
|
|
||||||
if (status < B_OK) {
|
|
||||||
fprintf(stderr, "Couldn't find user settings directory: %s\n",
|
|
||||||
strerror(status));
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
path.Append("Mail/chains");
|
|
||||||
|
|
||||||
if (ChainDirection() == outbound)
|
|
||||||
path.Append("outbound");
|
|
||||||
else
|
|
||||||
path.Append("inbound");
|
|
||||||
|
|
||||||
BString leaf;
|
|
||||||
leaf << fId;
|
|
||||||
path.Append(leaf.String());
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
BMailChain::Save(bigtime_t /*timeout*/)
|
|
||||||
{
|
|
||||||
BMessage archive;
|
|
||||||
status_t ret = Archive(&archive, true);
|
|
||||||
if (ret != B_OK) {
|
|
||||||
fprintf(stderr, "Couldn't archive chain %ld: %s\n",
|
|
||||||
fId, strerror(ret));
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
BPath path;
|
|
||||||
if ((ret = GetPath(path)) < B_OK)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
BPath directory;
|
|
||||||
if ((ret = path.GetParent(&directory)) < B_OK)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
return MailInternal::WriteMessageFile(archive, directory,
|
|
||||||
path.Leaf()/*, timeout*/);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
BMailChain::Delete() const
|
|
||||||
{
|
|
||||||
status_t status;
|
|
||||||
BPath path;
|
|
||||||
if ((status = GetPath(path)) < B_OK)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
BEntry entry(path.Path());
|
|
||||||
if ((status = entry.InitCheck()) < B_OK)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
return entry.Remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
b_mail_chain_direction
|
|
||||||
BMailChain::ChainDirection() const
|
|
||||||
{
|
|
||||||
return fDirection;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
BMailChain::SetChainDirection(b_mail_chain_direction dir)
|
|
||||||
{
|
|
||||||
fDirection = dir;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
BMailChain::Reload()
|
|
||||||
{
|
|
||||||
BPath path;
|
|
||||||
status_t ret = find_directory(B_USER_SETTINGS_DIRECTORY, &path);
|
|
||||||
if (ret != B_OK) {
|
|
||||||
fprintf(stderr, "Couldn't find user settings directory: %s\n",
|
|
||||||
strerror(ret));
|
|
||||||
fStatus = ret;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
path.Append("Mail/chains");
|
|
||||||
{
|
|
||||||
//---Determine whether chain is outbound or inbound and glean full path.
|
|
||||||
BPath working = path;
|
|
||||||
working.Append("inbound");
|
|
||||||
BString leaf;
|
|
||||||
leaf << fId;
|
|
||||||
|
|
||||||
//puts(path.Path());
|
|
||||||
//puts(leaf.String());
|
|
||||||
|
|
||||||
if (BDirectory(working.Path()).Contains(leaf.String())) {
|
|
||||||
path = working;
|
|
||||||
fDirection = inbound;
|
|
||||||
} else {
|
|
||||||
working = path;
|
|
||||||
working.Append("outbound");
|
|
||||||
if (BDirectory(working.Path()).Contains(leaf.String())) {
|
|
||||||
path = working;
|
|
||||||
fDirection = outbound;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//puts(path.Path());
|
|
||||||
|
|
||||||
path.Append(leaf.String());
|
|
||||||
|
|
||||||
//puts(path.Path());
|
|
||||||
}
|
|
||||||
|
|
||||||
// open
|
|
||||||
BFile settings(path.Path(),B_READ_ONLY);
|
|
||||||
ret = settings.InitCheck();
|
|
||||||
|
|
||||||
if (ret != B_OK) {
|
|
||||||
BMessage empty;
|
|
||||||
fprintf(stderr, "Couldn't open chain settings file '%s': %s\n",
|
|
||||||
path.Path(), strerror(ret));
|
|
||||||
Load(&empty);
|
|
||||||
fStatus = B_FILE_ERROR;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
// read settings
|
|
||||||
BMessage tmp;
|
|
||||||
ret = tmp.Unflatten(&settings);
|
|
||||||
if (ret != B_OK) {
|
|
||||||
fprintf(stderr, "Couldn't read settings from '%s': %s\n",
|
|
||||||
path.Path(), strerror(ret));
|
|
||||||
Load(&tmp);
|
|
||||||
fStatus = ret;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
// clobber old settings
|
|
||||||
fStatus = ret = Load(&tmp);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
uint32
|
|
||||||
BMailChain::ID() const
|
|
||||||
{
|
|
||||||
return fId;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const char*
|
|
||||||
BMailChain::Name() const
|
|
||||||
{
|
|
||||||
return fName;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
BMailChain::SetName(const char* n)
|
|
||||||
{
|
|
||||||
if (n)
|
|
||||||
strncpy(fName, n, sizeof(fName));
|
|
||||||
else
|
|
||||||
fName[0] = '\0';
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BMessage*
|
|
||||||
BMailChain::MetaData() const
|
|
||||||
{
|
|
||||||
return fMetaData;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int32
|
|
||||||
BMailChain::CountFilters() const
|
|
||||||
{
|
|
||||||
return fFilterSettings.CountItems();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
BMailChain::GetFilter(int32 index, BMessage* out_settings,
|
|
||||||
entry_ref* addon) const
|
|
||||||
{
|
|
||||||
if (index >= fFilterSettings.CountItems())
|
|
||||||
return B_BAD_INDEX;
|
|
||||||
|
|
||||||
BMessage* settings = (BMessage*)fFilterSettings.ItemAt(index);
|
|
||||||
if (settings)
|
|
||||||
*out_settings = *settings;
|
|
||||||
else
|
|
||||||
return B_BAD_INDEX;
|
|
||||||
|
|
||||||
if (addon) {
|
|
||||||
entry_ref* ref = (entry_ref*)fFilterAddons.ItemAt(index);
|
|
||||||
if (ref)
|
|
||||||
*addon = *ref;
|
|
||||||
else
|
|
||||||
return B_BAD_INDEX;
|
|
||||||
}
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
BMailChain::SetFilter(int32 index, const BMessage& s,
|
|
||||||
const entry_ref& addon)
|
|
||||||
{
|
|
||||||
BMessage* settings = (BMessage*)fFilterSettings.ItemAt(index);
|
|
||||||
if (settings)
|
|
||||||
*settings = s;
|
|
||||||
else
|
|
||||||
return B_BAD_INDEX;
|
|
||||||
|
|
||||||
entry_ref* ref = (entry_ref*)fFilterAddons.ItemAt(index);
|
|
||||||
if (ref)
|
|
||||||
*ref = addon;
|
|
||||||
else
|
|
||||||
return B_BAD_INDEX;
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
BMailChain::AddFilter(const BMessage& settings, const entry_ref& addon)
|
|
||||||
{
|
|
||||||
BMessage* s = new BMessage(settings);
|
|
||||||
entry_ref* a = new entry_ref(addon);
|
|
||||||
|
|
||||||
if (!fFilterSettings.AddItem(s)) {
|
|
||||||
delete s;
|
|
||||||
delete a;
|
|
||||||
return B_BAD_INDEX;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fFilterAddons.AddItem(a)) {
|
|
||||||
fFilterSettings.RemoveItem(fSettingsCount);
|
|
||||||
delete s;
|
|
||||||
delete a;
|
|
||||||
return B_BAD_INDEX;
|
|
||||||
}
|
|
||||||
// else
|
|
||||||
|
|
||||||
++fSettingsCount;
|
|
||||||
++fAddonsCount;
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
BMailChain::AddFilter(int32 index, const BMessage& settings,
|
|
||||||
const entry_ref& addon)
|
|
||||||
{
|
|
||||||
BMessage* s = new BMessage(settings);
|
|
||||||
entry_ref* a = new entry_ref(addon);
|
|
||||||
|
|
||||||
if (!fFilterSettings.AddItem(s, index)) {
|
|
||||||
delete s;
|
|
||||||
delete a;
|
|
||||||
return B_BAD_INDEX;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fFilterAddons.AddItem(a, index)) {
|
|
||||||
fFilterSettings.RemoveItem(index);
|
|
||||||
delete s;
|
|
||||||
delete a;
|
|
||||||
return B_BAD_INDEX;
|
|
||||||
}
|
|
||||||
++fSettingsCount;
|
|
||||||
++fAddonsCount;
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
BMailChain::RemoveFilter(int32 index)
|
|
||||||
{
|
|
||||||
BMessage* s = (BMessage*)fFilterSettings.RemoveItem(index);
|
|
||||||
delete s;
|
|
||||||
|
|
||||||
entry_ref* a = (entry_ref*)fFilterAddons.RemoveItem(index);
|
|
||||||
delete a;
|
|
||||||
|
|
||||||
--fSettingsCount;
|
|
||||||
--fAddonsCount;
|
|
||||||
|
|
||||||
return s || a ? B_OK : B_BAD_INDEX;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
BMailChain::RunChain(BMailStatusWindow *window, bool async,
|
|
||||||
bool save_when_done, bool delete_when_done)
|
|
||||||
{
|
|
||||||
(new BMailChainRunner(this, window, true, save_when_done,
|
|
||||||
delete_when_done))->RunChain(async);
|
|
||||||
}
|
|
||||||
@@ -13,79 +13,85 @@
|
|||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
_EXPORT status_t
|
|
||||||
BMailDaemon::CheckMail(bool send_queued_mail,const char *account)
|
status_t
|
||||||
|
BMailDaemon::CheckMail(int32 accountID)
|
||||||
{
|
{
|
||||||
BMessenger daemon("application/x-vnd.Be-POST");
|
BMessenger daemon("application/x-vnd.Be-POST");
|
||||||
if (!daemon.IsValid())
|
if (!daemon.IsValid())
|
||||||
return B_MAIL_NO_DAEMON;
|
return B_MAIL_NO_DAEMON;
|
||||||
|
|
||||||
BMessage message(send_queued_mail ? 'mbth' : 'mnow');
|
BMessage message(kMsgCheckMessage);
|
||||||
if (account != NULL) {
|
message.AddInt32("account", accountID);
|
||||||
BList list;
|
return daemon.SendMessage(&message);
|
||||||
|
|
||||||
GetInboundMailChains(&list);
|
|
||||||
for (int32 i = list.CountItems();i-- > 0;) {
|
|
||||||
BMailChain *chain = (BMailChain *)list.ItemAt(i);
|
|
||||||
|
|
||||||
if (!strcmp(chain->Name(),account))
|
|
||||||
message.AddInt32("chain",chain->ID());
|
|
||||||
|
|
||||||
delete chain;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (send_queued_mail) {
|
|
||||||
list.MakeEmpty();
|
|
||||||
GetOutboundMailChains(&list);
|
|
||||||
for (int32 i = list.CountItems();i-- > 0;) {
|
|
||||||
BMailChain *chain = (BMailChain *)list.ItemAt(i);
|
|
||||||
|
|
||||||
if (!strcmp(chain->Name(),account))
|
|
||||||
message.AddInt32("chain",chain->ID());
|
|
||||||
|
|
||||||
delete chain;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
daemon.SendMessage(&message);
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
_EXPORT status_t BMailDaemon::SendQueuedMail() {
|
status_t
|
||||||
|
BMailDaemon::CheckAndSendQueuedMail(int32 accountID)
|
||||||
|
{
|
||||||
|
BMessenger daemon("application/x-vnd.Be-POST");
|
||||||
|
if (!daemon.IsValid())
|
||||||
|
return B_MAIL_NO_DAEMON;
|
||||||
|
|
||||||
|
BMessage message(kMsgCheckAndSend);
|
||||||
|
message.AddInt32("account", accountID);
|
||||||
|
return daemon.SendMessage(&message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BMailDaemon::SendQueuedMail()
|
||||||
|
{
|
||||||
BMessenger daemon("application/x-vnd.Be-POST");
|
BMessenger daemon("application/x-vnd.Be-POST");
|
||||||
if (!daemon.IsValid())
|
if (!daemon.IsValid())
|
||||||
return B_MAIL_NO_DAEMON;
|
return B_MAIL_NO_DAEMON;
|
||||||
|
|
||||||
daemon.SendMessage('msnd');
|
return daemon.SendMessage(kMsgSendMessages);
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_EXPORT int32 BMailDaemon::CountNewMessages(bool wait_for_fetch_completion) {
|
|
||||||
|
int32
|
||||||
|
BMailDaemon::CountNewMessages(bool wait_for_fetch_completion)
|
||||||
|
{
|
||||||
BMessenger daemon("application/x-vnd.Be-POST");
|
BMessenger daemon("application/x-vnd.Be-POST");
|
||||||
if (!daemon.IsValid())
|
if (!daemon.IsValid())
|
||||||
return B_MAIL_NO_DAEMON;
|
return B_MAIL_NO_DAEMON;
|
||||||
|
|
||||||
BMessage reply;
|
BMessage reply;
|
||||||
BMessage first('mnum');
|
BMessage first(kMsgCountNewMessages);
|
||||||
|
|
||||||
if (wait_for_fetch_completion)
|
if (wait_for_fetch_completion)
|
||||||
first.AddBool("wait_for_fetch_done",true);
|
first.AddBool("wait_for_fetch_done",true);
|
||||||
|
|
||||||
daemon.SendMessage(&first,&reply);
|
daemon.SendMessage(&first, &reply);
|
||||||
|
|
||||||
return reply.FindInt32("num_new_messages");
|
return reply.FindInt32("num_new_messages");
|
||||||
}
|
}
|
||||||
|
|
||||||
_EXPORT status_t BMailDaemon::Quit() {
|
|
||||||
|
status_t
|
||||||
|
BMailDaemon::MarkAsRead(int32 account, const entry_ref& ref, bool read)
|
||||||
|
{
|
||||||
|
BMessenger daemon("application/x-vnd.Be-POST");
|
||||||
|
if (!daemon.IsValid())
|
||||||
|
return B_MAIL_NO_DAEMON;
|
||||||
|
|
||||||
|
BMessage message(kMsgMarkMessageAsRead);
|
||||||
|
message.AddInt32("account", account);
|
||||||
|
message.AddRef("ref", &ref);
|
||||||
|
message.AddBool("read", read);
|
||||||
|
|
||||||
|
return daemon.SendMessage(&message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BMailDaemon::Quit()
|
||||||
|
{
|
||||||
BMessenger daemon("application/x-vnd.Be-POST");
|
BMessenger daemon("application/x-vnd.Be-POST");
|
||||||
if (!daemon.IsValid())
|
if (!daemon.IsValid())
|
||||||
return B_MAIL_NO_DAEMON;
|
return B_MAIL_NO_DAEMON;
|
||||||
|
|
||||||
daemon.SendMessage(B_QUIT_REQUESTED);
|
return daemon.SendMessage(B_QUIT_REQUESTED);
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ BEmailMessage::BEmailMessage(BPositionIO *file, bool own, uint32 defaultCharSet)
|
|||||||
_text_body(NULL)
|
_text_body(NULL)
|
||||||
{
|
{
|
||||||
BMailSettings settings;
|
BMailSettings settings;
|
||||||
_chain_id = settings.DefaultOutboundChainID();
|
_account_id = settings.DefaultOutboundAccount();
|
||||||
|
|
||||||
if (own)
|
if (own)
|
||||||
fData = file;
|
fData = file;
|
||||||
@@ -75,16 +75,16 @@ BEmailMessage::BEmailMessage(BPositionIO *file, bool own, uint32 defaultCharSet)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BEmailMessage::BEmailMessage(entry_ref *ref, uint32 defaultCharSet)
|
BEmailMessage::BEmailMessage(const entry_ref *ref, uint32 defaultCharSet)
|
||||||
:
|
:
|
||||||
BMailContainer (defaultCharSet),
|
BMailContainer(defaultCharSet),
|
||||||
_bcc(NULL),
|
_bcc(NULL),
|
||||||
_num_components(0),
|
_num_components(0),
|
||||||
_body(NULL),
|
_body(NULL),
|
||||||
_text_body(NULL)
|
_text_body(NULL)
|
||||||
{
|
{
|
||||||
BMailSettings settings;
|
BMailSettings settings;
|
||||||
_chain_id = settings.DefaultOutboundChainID();
|
_account_id = settings.DefaultOutboundAccount();
|
||||||
|
|
||||||
fData = new BFile();
|
fData = new BFile();
|
||||||
_status = static_cast<BFile *>(fData)->SetTo(ref,B_READ_ONLY);
|
_status = static_cast<BFile *>(fData)->SetTo(ref,B_READ_ONLY);
|
||||||
@@ -126,7 +126,11 @@ BEmailMessage::ReplyMessage(mail_reply_to_mode replyTo, bool accountFromMail,
|
|||||||
get_address_list(list, To(), extract_address);
|
get_address_list(list, To(), extract_address);
|
||||||
|
|
||||||
// Filter out the sender
|
// Filter out the sender
|
||||||
BString sender = BMailChain(Account()).MetaData()->FindString("reply_to");
|
BMailAccounts accounts;
|
||||||
|
BMailAccountSettings* account = accounts.AccountByID(Account());
|
||||||
|
BString sender;
|
||||||
|
if (account)
|
||||||
|
sender = account->ReturnAddress();
|
||||||
extract_address(sender);
|
extract_address(sender);
|
||||||
|
|
||||||
BString cc;
|
BString cc;
|
||||||
@@ -391,52 +395,42 @@ BEmailMessage::SendViaAccountFrom(BEmailMessage *message)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
BList chains;
|
SendViaAccount(name);
|
||||||
GetOutboundMailChains(&chains);
|
|
||||||
for (int32 i = chains.CountItems();i-- > 0;) {
|
|
||||||
BMailChain *chain = (BMailChain *)chains.ItemAt(i);
|
|
||||||
if (!strcmp(chain->Name(), name))
|
|
||||||
SendViaAccount(chain->ID());
|
|
||||||
|
|
||||||
delete chain;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BEmailMessage::SendViaAccount(const char *account_name)
|
BEmailMessage::SendViaAccount(const char *account_name)
|
||||||
{
|
{
|
||||||
BList chains;
|
BMailAccounts accounts;
|
||||||
GetOutboundMailChains(&chains);
|
BMailAccountSettings* account = accounts.AccountByName(account_name);
|
||||||
|
if (!account)
|
||||||
for (int32 i = 0; i < chains.CountItems(); i++) {
|
return;
|
||||||
if (strcmp(((BMailChain *)(chains.ItemAt(i)))->Name(),account_name) == 0) {
|
SendViaAccount(account->AccountID());
|
||||||
SendViaAccount(((BMailChain *)(chains.ItemAt(i)))->ID());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (chains.CountItems() > 0)
|
|
||||||
delete (BMailChain *)chains.RemoveItem(0L);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BEmailMessage::SendViaAccount(int32 chain_id)
|
BEmailMessage::SendViaAccount(int32 account)
|
||||||
{
|
{
|
||||||
_chain_id = chain_id;
|
_account_id = account;
|
||||||
|
|
||||||
|
BMailAccounts accounts;
|
||||||
|
BMailAccountSettings* accountSettings = accounts.AccountByID(_account_id);
|
||||||
|
|
||||||
BMailChain chain(_chain_id);
|
|
||||||
BString from;
|
BString from;
|
||||||
from << '\"' << chain.MetaData()->FindString("real_name") << "\" <" << chain.MetaData()->FindString("reply_to") << '>';
|
if (accountSettings) {
|
||||||
SetFrom(from.String());
|
from << '\"' << accountSettings->RealName() << "\" <"
|
||||||
|
<< accountSettings->ReturnAddress() << '>';
|
||||||
|
}
|
||||||
|
SetFrom(from);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int32
|
int32
|
||||||
BEmailMessage::Account() const
|
BEmailMessage::Account() const
|
||||||
{
|
{
|
||||||
return _chain_id;
|
return _account_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -650,7 +644,7 @@ status_t
|
|||||||
BEmailMessage::SetToRFC822(BPositionIO *mail_file, size_t length, bool parse_now)
|
BEmailMessage::SetToRFC822(BPositionIO *mail_file, size_t length, bool parse_now)
|
||||||
{
|
{
|
||||||
if (BFile *file = dynamic_cast<BFile *>(mail_file))
|
if (BFile *file = dynamic_cast<BFile *>(mail_file))
|
||||||
file->ReadAttr("MAIL:chain",B_INT32_TYPE,0,&_chain_id,sizeof(_chain_id));
|
file->ReadAttr("MAIL:account",B_INT32_TYPE,0,&_account_id,sizeof(_account_id));
|
||||||
|
|
||||||
mail_file->Seek(0,SEEK_END);
|
mail_file->Seek(0,SEEK_END);
|
||||||
length = mail_file->Position();
|
length = mail_file->Position();
|
||||||
@@ -711,7 +705,7 @@ BEmailMessage::RenderToRFC822(BPositionIO *file)
|
|||||||
|
|
||||||
if (From() == NULL) {
|
if (From() == NULL) {
|
||||||
// set the "From:" string
|
// set the "From:" string
|
||||||
SendViaAccount(_chain_id);
|
SendViaAccount(_account_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
BList recipientList;
|
BList recipientList;
|
||||||
@@ -807,14 +801,19 @@ BEmailMessage::RenderToRFC822(BPositionIO *file)
|
|||||||
attributed->WriteAttrString(B_MAIL_ATTR_STATUS,&attr);
|
attributed->WriteAttrString(B_MAIL_ATTR_STATUS,&attr);
|
||||||
attr = "1.0";
|
attr = "1.0";
|
||||||
attributed->WriteAttrString(B_MAIL_ATTR_MIME,&attr);
|
attributed->WriteAttrString(B_MAIL_ATTR_MIME,&attr);
|
||||||
attr = BMailChain(_chain_id).Name();
|
BMailAccounts accounts;
|
||||||
|
BMailAccountSettings* account = accounts.AccountByID(_account_id);
|
||||||
|
if (account)
|
||||||
|
attr = account->Name();
|
||||||
|
else
|
||||||
|
attr = "";
|
||||||
attributed->WriteAttrString(B_MAIL_ATTR_ACCOUNT,&attr);
|
attributed->WriteAttrString(B_MAIL_ATTR_ACCOUNT,&attr);
|
||||||
|
|
||||||
attributed->WriteAttr(B_MAIL_ATTR_WHEN,B_TIME_TYPE,0,&creationTime,sizeof(int32));
|
attributed->WriteAttr(B_MAIL_ATTR_WHEN,B_TIME_TYPE,0,&creationTime,sizeof(int32));
|
||||||
int32 flags = B_MAIL_PENDING | B_MAIL_SAVE;
|
int32 flags = B_MAIL_PENDING | B_MAIL_SAVE;
|
||||||
attributed->WriteAttr(B_MAIL_ATTR_FLAGS,B_INT32_TYPE,0,&flags,sizeof(int32));
|
attributed->WriteAttr(B_MAIL_ATTR_FLAGS,B_INT32_TYPE,0,&flags,sizeof(int32));
|
||||||
|
|
||||||
attributed->WriteAttr("MAIL:chain",B_INT32_TYPE,0,&_chain_id,sizeof(int32));
|
attributed->WriteAttr("MAIL:account",B_INT32_TYPE,0,&_account_id,sizeof(int32));
|
||||||
}
|
}
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
@@ -902,15 +901,19 @@ BEmailMessage::RenderTo(BDirectory *dir, BEntry *msg)
|
|||||||
status_t
|
status_t
|
||||||
BEmailMessage::Send(bool send_now)
|
BEmailMessage::Send(bool send_now)
|
||||||
{
|
{
|
||||||
BMailChain *via = new BMailChain(_chain_id);
|
BMailAccounts accounts;
|
||||||
if ((via->InitCheck() != B_OK) || (via->ChainDirection() != outbound)) {
|
BMailAccountSettings* account = accounts.AccountByID(_account_id);
|
||||||
delete via;
|
if (!account || !account->HasOutbound()) {
|
||||||
via = new BMailChain(BMailSettings().DefaultOutboundChainID());
|
account = accounts.AccountByID(
|
||||||
SendViaAccount(via->ID());
|
BMailSettings().DefaultOutboundAccount());
|
||||||
|
if (!account)
|
||||||
|
return B_ERROR;
|
||||||
|
SendViaAccount(account->AccountID());
|
||||||
}
|
}
|
||||||
|
|
||||||
BString path;
|
BString path;
|
||||||
if (via->MetaData()->FindString("path", &path) != B_OK) {
|
if (account->OutboundSettings().Settings().FindString("path", &path)
|
||||||
|
!= B_OK) {
|
||||||
BPath defaultMailOutPath;
|
BPath defaultMailOutPath;
|
||||||
if (find_directory(B_USER_DIRECTORY, &defaultMailOutPath) != B_OK
|
if (find_directory(B_USER_DIRECTORY, &defaultMailOutPath) != B_OK
|
||||||
|| defaultMailOutPath.Append("mail/out") != B_OK)
|
|| defaultMailOutPath.Append("mail/out") != B_OK)
|
||||||
@@ -925,7 +928,6 @@ BEmailMessage::Send(bool send_now)
|
|||||||
BEntry message;
|
BEntry message;
|
||||||
|
|
||||||
status_t status = RenderTo(&directory, &message);
|
status_t status = RenderTo(&directory, &message);
|
||||||
delete via;
|
|
||||||
if (status >= B_OK && send_now) {
|
if (status >= B_OK && send_now) {
|
||||||
BMailSettings settings_file;
|
BMailSettings settings_file;
|
||||||
if (settings_file.SendOnlyIfPPPUp()) {
|
if (settings_file.SendOnlyIfPPPUp()) {
|
||||||
@@ -955,7 +957,7 @@ BEmailMessage::Send(bool send_now)
|
|||||||
return B_MAIL_NO_DAEMON;
|
return B_MAIL_NO_DAEMON;
|
||||||
|
|
||||||
BMessage msg('msnd');
|
BMessage msg('msnd');
|
||||||
msg.AddInt32("chain",_chain_id);
|
msg.AddInt32("account",_account_id);
|
||||||
BPath path;
|
BPath path;
|
||||||
message.GetPath(&path);
|
message.GetPath(&path);
|
||||||
msg.AddString("message_path",path.Path());
|
msg.AddString("message_path",path.Path());
|
||||||
|
|||||||
+691
-427
File diff suppressed because it is too large
Load Diff
+545
-114
@@ -25,120 +25,12 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
|
||||||
class BMailSettings;
|
|
||||||
|
|
||||||
namespace MailInternal {
|
namespace MailInternal {
|
||||||
status_t WriteMessageFile(const BMessage& archive, const BPath& path,
|
status_t WriteMessageFile(const BMessage& archive, const BPath& path,
|
||||||
const char* name);
|
const char* name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - Chain methods
|
|
||||||
|
|
||||||
|
|
||||||
// TODO!
|
|
||||||
BMailChain*
|
|
||||||
NewMailChain()
|
|
||||||
{
|
|
||||||
// attempted solution: use time(NULL) and hope it's unique. Is there a better idea?
|
|
||||||
// note that two chains in two second is quite possible. how to fix this?
|
|
||||||
// maybe we could | in some bigtime_t as well. hrrm...
|
|
||||||
|
|
||||||
// This is to fix a problem with generating the correct id for chains.
|
|
||||||
// Basically if the chains dir does not exist, the first time you create
|
|
||||||
// an account both the inbound and outbound chains will be called 0.
|
|
||||||
create_directory("/boot/home/config/settings/Mail/chains",0777);
|
|
||||||
|
|
||||||
BPath path;
|
|
||||||
find_directory(B_USER_SETTINGS_DIRECTORY, &path);
|
|
||||||
path.Append("Mail/chains");
|
|
||||||
BDirectory chain_dir(path.Path());
|
|
||||||
BDirectory outbound_dir(&chain_dir,"outbound"), inbound_dir(&chain_dir,"inbound");
|
|
||||||
|
|
||||||
// TODO(bga): A better way to do all this anyway is to write the chain
|
|
||||||
// information to the settings message (a new field would be added).
|
|
||||||
|
|
||||||
// Lock Chain directory to avoid concurrent access.
|
|
||||||
chain_dir.Lock();
|
|
||||||
|
|
||||||
int32 id = -1; //-----When inc'ed, we start with 0----
|
|
||||||
chain_dir.ReadAttr("last_issued_chain_id",B_INT32_TYPE,0,&id,sizeof(id));
|
|
||||||
|
|
||||||
BString string_id;
|
|
||||||
|
|
||||||
do {
|
|
||||||
id++;
|
|
||||||
string_id = "";
|
|
||||||
string_id << id;
|
|
||||||
} while ((outbound_dir.Contains(string_id.String()))
|
|
||||||
|| (inbound_dir.Contains(string_id.String())));
|
|
||||||
|
|
||||||
chain_dir.WriteAttr("last_issued_chain_id",B_INT32_TYPE,0,&id,sizeof(id));
|
|
||||||
|
|
||||||
return new BMailChain(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BMailChain*
|
|
||||||
GetMailChain(uint32 id)
|
|
||||||
{
|
|
||||||
return new BMailChain(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
GetInboundMailChains(BList *list)
|
|
||||||
{
|
|
||||||
BPath path;
|
|
||||||
status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path);
|
|
||||||
if (status != B_OK) {
|
|
||||||
fprintf(stderr, "Couldn't find user settings directory: %s\n",
|
|
||||||
strerror(status));
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
path.Append("Mail/chains/inbound");
|
|
||||||
BDirectory chainDirectory(path.Path());
|
|
||||||
entry_ref ref;
|
|
||||||
|
|
||||||
while (chainDirectory.GetNextRef(&ref) == B_OK) {
|
|
||||||
char *end;
|
|
||||||
uint32 id = strtoul(ref.name, &end, 10);
|
|
||||||
|
|
||||||
if (!end || *end == '\0')
|
|
||||||
list->AddItem((void*)new BMailChain(id));
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
GetOutboundMailChains(BList *list)
|
|
||||||
{
|
|
||||||
BPath path;
|
|
||||||
status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path);
|
|
||||||
if (status != B_OK) {
|
|
||||||
fprintf(stderr, "Couldn't find user settings directory: %s\n",
|
|
||||||
strerror(status));
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
path.Append("Mail/chains/outbound");
|
|
||||||
BDirectory chainDirectory(path.Path());
|
|
||||||
entry_ref ref;
|
|
||||||
|
|
||||||
while (chainDirectory.GetNextRef(&ref) == B_OK) {
|
|
||||||
char *end;
|
|
||||||
uint32 id = strtoul(ref.name, &end, 10);
|
|
||||||
if (!end || *end == '\0')
|
|
||||||
list->AddItem((void*)new BMailChain(id));
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - BMailSettings
|
// #pragma mark - BMailSettings
|
||||||
|
|
||||||
|
|
||||||
@@ -398,16 +290,555 @@ BMailSettings::SetSendOnlyIfPPPUp(bool yes)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32
|
int32
|
||||||
BMailSettings::DefaultOutboundChainID()
|
BMailSettings::DefaultOutboundAccount()
|
||||||
{
|
{
|
||||||
return fData.FindInt32("DefaultOutboundChainID");
|
return fData.FindInt32("DefaultOutboundAccount");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BMailSettings::SetDefaultOutboundChainID(uint32 to)
|
BMailSettings::SetDefaultOutboundAccount(int32 to)
|
||||||
{
|
{
|
||||||
if (fData.ReplaceInt32("DefaultOutboundChainID",to))
|
if (fData.ReplaceInt32("DefaultOutboundAccount",to))
|
||||||
fData.AddInt32("DefaultOutboundChainID",to);
|
fData.AddInt32("DefaultOutboundAccount",to);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BMailAccounts::BMailAccounts()
|
||||||
|
{
|
||||||
|
BPath path;
|
||||||
|
status_t status = AccountsPath(path);
|
||||||
|
if (status != B_OK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
BDirectory dir(path.Path());
|
||||||
|
if (dir.InitCheck() != B_OK)
|
||||||
|
return;
|
||||||
|
BEntry entry;
|
||||||
|
while (dir.GetNextEntry(&entry) != B_ENTRY_NOT_FOUND) {
|
||||||
|
BMailAccountSettings* account = new BMailAccountSettings(entry);
|
||||||
|
if (account->InitCheck() != B_OK)
|
||||||
|
continue;
|
||||||
|
fAccounts.AddItem(account);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BMailAccounts::AccountsPath(BPath& path)
|
||||||
|
{
|
||||||
|
status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path);
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
return path.Append("Mail/accounts");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BMailAccounts::~BMailAccounts()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < fAccounts.CountItems(); i++)
|
||||||
|
delete fAccounts.ItemAt(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
BMailAccounts::CountAccounts()
|
||||||
|
{
|
||||||
|
return fAccounts.CountItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BMailAccountSettings*
|
||||||
|
BMailAccounts::AccountAt(int32 index)
|
||||||
|
{
|
||||||
|
return fAccounts.ItemAt(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BMailAccountSettings*
|
||||||
|
BMailAccounts::AccountByID(int32 id)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < fAccounts.CountItems(); i++) {
|
||||||
|
BMailAccountSettings* account = fAccounts.ItemAt(i);
|
||||||
|
if (account->AccountID() == id)
|
||||||
|
return account;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BMailAccountSettings*
|
||||||
|
BMailAccounts::AccountByName(const char* name)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < fAccounts.CountItems(); i++) {
|
||||||
|
BMailAccountSettings* account = fAccounts.ItemAt(i);
|
||||||
|
if (strcmp(account->Name(), name) == 0)
|
||||||
|
return account;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
using std::vector;
|
||||||
|
|
||||||
|
|
||||||
|
AddonSettings::AddonSettings()
|
||||||
|
:
|
||||||
|
fModified(false)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
AddonSettings::Load(const BMessage& message)
|
||||||
|
{
|
||||||
|
if (message.FindRef("ref", &fAddonRef) != B_OK)
|
||||||
|
return false;
|
||||||
|
if (message.FindMessage("settings", &fSettings) != B_OK)
|
||||||
|
return false;
|
||||||
|
fModified = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
AddonSettings::Save(BMessage& message)
|
||||||
|
{
|
||||||
|
message.AddRef("ref", &fAddonRef);
|
||||||
|
message.AddMessage("settings", &fSettings);
|
||||||
|
fModified = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
AddonSettings::SetAddonRef(const entry_ref& ref)
|
||||||
|
{
|
||||||
|
fAddonRef = ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const entry_ref&
|
||||||
|
AddonSettings::AddonRef() const
|
||||||
|
{
|
||||||
|
return fAddonRef;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const BMessage&
|
||||||
|
AddonSettings::Settings() const
|
||||||
|
{
|
||||||
|
return fSettings;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BMessage&
|
||||||
|
AddonSettings::EditSettings()
|
||||||
|
{
|
||||||
|
fModified = true;
|
||||||
|
return fSettings;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
AddonSettings::HasBeenModified()
|
||||||
|
{
|
||||||
|
return fModified;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
MailAddonSettings::Load(const BMessage& message)
|
||||||
|
{
|
||||||
|
if (!AddonSettings::Load(message))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
type_code typeFound;
|
||||||
|
int32 countFound;
|
||||||
|
message.GetInfo("filters", &typeFound, &countFound);
|
||||||
|
if (typeFound != B_MESSAGE_TYPE)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (int i = 0; i < countFound; i++) {
|
||||||
|
int32 index = AddFilterSettings();
|
||||||
|
AddonSettings& filterSettings = fFiltersSettings[index];
|
||||||
|
BMessage filterMessage;
|
||||||
|
message.FindMessage("filters", i, &filterMessage);
|
||||||
|
if (!filterSettings.Load(filterMessage))
|
||||||
|
RemoveFilterSettings(index);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
MailAddonSettings::Save(BMessage& message)
|
||||||
|
{
|
||||||
|
if (!AddonSettings::Save(message))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (int i = 0; i < CountFilterSettings(); i++) {
|
||||||
|
BMessage filter;
|
||||||
|
AddonSettings& filterSettings = fFiltersSettings[i];
|
||||||
|
filterSettings.Save(filter);
|
||||||
|
message.AddMessage("filters", &filter);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
MailAddonSettings::CountFilterSettings()
|
||||||
|
{
|
||||||
|
return fFiltersSettings.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
MailAddonSettings::AddFilterSettings(const entry_ref* ref)
|
||||||
|
{
|
||||||
|
AddonSettings filterSettings;
|
||||||
|
if (ref != NULL)
|
||||||
|
filterSettings.SetAddonRef(*ref);
|
||||||
|
fFiltersSettings.push_back(filterSettings);
|
||||||
|
return fFiltersSettings.size() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
MailAddonSettings::RemoveFilterSettings(int32 index)
|
||||||
|
{
|
||||||
|
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())
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
AddonSettings*
|
||||||
|
MailAddonSettings::FilterSettingsAt(int32 index)
|
||||||
|
{
|
||||||
|
if (index < 0 || index >= (int32)fFiltersSettings.size())
|
||||||
|
return NULL;
|
||||||
|
return &fFiltersSettings[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
MailAddonSettings::HasBeenModified()
|
||||||
|
{
|
||||||
|
if (AddonSettings::HasBeenModified())
|
||||||
|
return true;
|
||||||
|
for (unsigned int i = 0; i < fFiltersSettings.size(); i++) {
|
||||||
|
if (fFiltersSettings[i].HasBeenModified())
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
BMailAccountSettings::BMailAccountSettings()
|
||||||
|
:
|
||||||
|
fStatus(B_OK),
|
||||||
|
fModified(true)
|
||||||
|
{
|
||||||
|
fAccountID = real_time_clock();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BMailAccountSettings::BMailAccountSettings(BEntry account)
|
||||||
|
:
|
||||||
|
fAccountFile(account),
|
||||||
|
fModified(false)
|
||||||
|
{
|
||||||
|
fStatus = Reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BMailAccountSettings::~BMailAccountSettings()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BMailAccountSettings::SetAccountID(int32 id)
|
||||||
|
{
|
||||||
|
fModified = true;
|
||||||
|
fAccountID = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
BMailAccountSettings::AccountID()
|
||||||
|
{
|
||||||
|
return fAccountID;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BMailAccountSettings::SetName(const char* name)
|
||||||
|
{
|
||||||
|
fModified = true;
|
||||||
|
fAccountName = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char*
|
||||||
|
BMailAccountSettings::Name() const
|
||||||
|
{
|
||||||
|
return fAccountName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BMailAccountSettings::SetRealName(const char* realName)
|
||||||
|
{
|
||||||
|
fModified = true;
|
||||||
|
fRealName = realName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char*
|
||||||
|
BMailAccountSettings::RealName() const
|
||||||
|
{
|
||||||
|
return fRealName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BMailAccountSettings::SetReturnAddress(const char* returnAddress)
|
||||||
|
{
|
||||||
|
fModified = true;
|
||||||
|
fReturnAdress = returnAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char*
|
||||||
|
BMailAccountSettings::ReturnAddress() const
|
||||||
|
{
|
||||||
|
return fReturnAdress;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
BMailAccountSettings::SetInboundAddon(const char* name)
|
||||||
|
{
|
||||||
|
BPath path;
|
||||||
|
status_t status = find_directory(B_BEOS_ADDONS_DIRECTORY, &path);
|
||||||
|
if (status != B_OK)
|
||||||
|
return false;
|
||||||
|
path.Append("mail_daemon");
|
||||||
|
path.Append("inbound_protocols");
|
||||||
|
path.Append(name);
|
||||||
|
entry_ref ref;
|
||||||
|
get_ref_for_path(path.Path(), &ref);
|
||||||
|
fInboundSettings.SetAddonRef(ref);
|
||||||
|
|
||||||
|
fModified = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
BMailAccountSettings::SetOutboundAddon(const char* name)
|
||||||
|
{
|
||||||
|
BPath path;
|
||||||
|
status_t status = find_directory(B_BEOS_ADDONS_DIRECTORY, &path);
|
||||||
|
if (status != B_OK)
|
||||||
|
return false;
|
||||||
|
path.Append("mail_daemon");
|
||||||
|
path.Append("outbound_protocols");
|
||||||
|
path.Append(name);
|
||||||
|
entry_ref ref;
|
||||||
|
get_ref_for_path(path.Path(), &ref);
|
||||||
|
fOutboundSettings.SetAddonRef(ref);
|
||||||
|
|
||||||
|
fModified = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const entry_ref&
|
||||||
|
BMailAccountSettings::InboundPath() const
|
||||||
|
{
|
||||||
|
return fInboundSettings.AddonRef();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const entry_ref&
|
||||||
|
BMailAccountSettings::OutboundPath() const
|
||||||
|
{
|
||||||
|
return fOutboundSettings.AddonRef();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
MailAddonSettings&
|
||||||
|
BMailAccountSettings::InboundSettings()
|
||||||
|
{
|
||||||
|
return fInboundSettings;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
MailAddonSettings&
|
||||||
|
BMailAccountSettings::OutboundSettings()
|
||||||
|
{
|
||||||
|
return fOutboundSettings;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
BMailAccountSettings::HasInbound()
|
||||||
|
{
|
||||||
|
return BEntry(&fInboundSettings.AddonRef()).Exists();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
BMailAccountSettings::HasOutbound()
|
||||||
|
{
|
||||||
|
return BEntry(&fOutboundSettings.AddonRef()).Exists();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BMailAccountSettings::Reload()
|
||||||
|
{
|
||||||
|
BFile file(&fAccountFile, B_READ_ONLY);
|
||||||
|
status_t status = file.InitCheck();
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
BMessage settings;
|
||||||
|
settings.Unflatten(&file);
|
||||||
|
|
||||||
|
int32 id;
|
||||||
|
if (settings.FindInt32("id", &id) == B_OK)
|
||||||
|
fAccountID = id;
|
||||||
|
settings.FindString("name", &fAccountName);
|
||||||
|
settings.FindString("real_name", &fRealName);
|
||||||
|
settings.FindString("return_address", &fReturnAdress);
|
||||||
|
|
||||||
|
BMessage inboundSettings;
|
||||||
|
settings.FindMessage("inbound", &inboundSettings);
|
||||||
|
fInboundSettings.Load(inboundSettings);
|
||||||
|
BMessage outboundSettings;
|
||||||
|
settings.FindMessage("outbound", &outboundSettings);
|
||||||
|
fOutboundSettings.Load(outboundSettings);
|
||||||
|
|
||||||
|
fModified = false;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BMailAccountSettings::Save()
|
||||||
|
{
|
||||||
|
fModified = false;
|
||||||
|
|
||||||
|
BMessage settings;
|
||||||
|
settings.AddInt32("id", fAccountID);
|
||||||
|
settings.AddString("name", fAccountName);
|
||||||
|
settings.AddString("real_name", fRealName);
|
||||||
|
settings.AddString("return_address", fReturnAdress);
|
||||||
|
|
||||||
|
BMessage inboundSettings;
|
||||||
|
fInboundSettings.Save(inboundSettings);
|
||||||
|
settings.AddMessage("inbound", &inboundSettings);
|
||||||
|
BMessage outboundSettings;
|
||||||
|
fOutboundSettings.Save(outboundSettings);
|
||||||
|
settings.AddMessage("outbound", &outboundSettings);
|
||||||
|
|
||||||
|
BEntry oldEntry = fAccountFile;
|
||||||
|
status_t status = _CreateAccountFile();
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
oldEntry.Remove();
|
||||||
|
|
||||||
|
BPath path;
|
||||||
|
fAccountFile.GetPath(&path);
|
||||||
|
|
||||||
|
BFile file(&fAccountFile, B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE);
|
||||||
|
status = file.InitCheck();
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
return settings.Flatten(&file);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BMailAccountSettings::Delete()
|
||||||
|
{
|
||||||
|
return fAccountFile.Remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
BMailAccountSettings::HasBeenModified()
|
||||||
|
{
|
||||||
|
if (fInboundSettings.HasBeenModified())
|
||||||
|
return true;
|
||||||
|
if (fOutboundSettings.HasBeenModified())
|
||||||
|
return true;
|
||||||
|
return fModified;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const BEntry&
|
||||||
|
BMailAccountSettings::AccountFile()
|
||||||
|
{
|
||||||
|
return fAccountFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BMailAccountSettings::_CreateAccountFile()
|
||||||
|
{
|
||||||
|
BPath path;
|
||||||
|
status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path);
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
path.Append("Mail/accounts");
|
||||||
|
create_directory(path.Path(), 777);
|
||||||
|
|
||||||
|
BString fileName = fAccountName;
|
||||||
|
if (fileName == "")
|
||||||
|
fileName << fAccountID;
|
||||||
|
for (int i = 0; ; i++) {
|
||||||
|
BString testFileName = fileName;
|
||||||
|
if (i != 0) {
|
||||||
|
testFileName += "_";
|
||||||
|
testFileName << i;
|
||||||
|
}
|
||||||
|
BPath testPath(path);
|
||||||
|
testPath.Append(testFileName);
|
||||||
|
BEntry testEntry(testPath.Path());
|
||||||
|
if (!testEntry.Exists()) {
|
||||||
|
fileName = testFileName;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
path.Append(fileName);
|
||||||
|
return fAccountFile.SetTo(path.Path());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,89 @@ class _EXPORT BMailProtocolConfigView;
|
|||||||
#include "ProtocolConfigView.h"
|
#include "ProtocolConfigView.h"
|
||||||
|
|
||||||
|
|
||||||
|
const char* kPartialDownloadLimit = "partial_download_limit";
|
||||||
|
|
||||||
|
|
||||||
|
BodyDownloadConfig::BodyDownloadConfig()
|
||||||
|
:
|
||||||
|
BView(BRect(0,0,50,50), "body_config", B_FOLLOW_ALL_SIDES, 0)
|
||||||
|
{
|
||||||
|
const char *partial_text = MDR_DIALECT_CHOICE (
|
||||||
|
"Partially download messages larger than",
|
||||||
|
"部分ダウンロードする");
|
||||||
|
|
||||||
|
BRect r(0, 0, 280, 15);
|
||||||
|
fPartialBox = new BCheckBox(r, "size_if", partial_text,
|
||||||
|
new BMessage('SIZF'));
|
||||||
|
fPartialBox->ResizeToPreferred();
|
||||||
|
|
||||||
|
r = fPartialBox->Frame();
|
||||||
|
r.OffsetBy(17,r.Height() + 1);
|
||||||
|
r.right = r.left + be_plain_font->StringWidth("0000") + 10;
|
||||||
|
fSizeBox = new BTextControl(r, "size", "", "", NULL);
|
||||||
|
|
||||||
|
r.OffsetBy(r.Width() + 5,0);
|
||||||
|
fBytesLabel = new BStringView(r, "kb", "KB");
|
||||||
|
AddChild(fBytesLabel);
|
||||||
|
fSizeBox->SetDivider(0);
|
||||||
|
|
||||||
|
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
||||||
|
AddChild(fPartialBox);
|
||||||
|
AddChild(fSizeBox);
|
||||||
|
ResizeToPreferred();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BodyDownloadConfig::SetTo(MailAddonSettings& addonSettings)
|
||||||
|
{
|
||||||
|
const BMessage* settings = &addonSettings.Settings();
|
||||||
|
|
||||||
|
if (settings->HasInt32(kPartialDownloadLimit)) {
|
||||||
|
BString kb;
|
||||||
|
kb << int32(settings->FindInt32(kPartialDownloadLimit)/1024);
|
||||||
|
fSizeBox->SetText(kb.String());
|
||||||
|
fPartialBox->SetValue(B_CONTROL_ON);
|
||||||
|
} else
|
||||||
|
fSizeBox->SetEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BodyDownloadConfig::MessageReceived(BMessage *msg)
|
||||||
|
{
|
||||||
|
if (msg->what != 'SIZF')
|
||||||
|
return BView::MessageReceived(msg);
|
||||||
|
fSizeBox->SetEnabled(fPartialBox->Value());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BodyDownloadConfig::AttachedToWindow()
|
||||||
|
{
|
||||||
|
fPartialBox->SetTarget(this);
|
||||||
|
fPartialBox->ResizeToPreferred();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BodyDownloadConfig::GetPreferredSize(float *width, float *height)
|
||||||
|
{
|
||||||
|
*height = fSizeBox->Frame().bottom + 5;
|
||||||
|
*width = 200;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BodyDownloadConfig::Archive(BMessage* into, bool) const
|
||||||
|
{
|
||||||
|
into->RemoveName(kPartialDownloadLimit);
|
||||||
|
if (fPartialBox->Value())
|
||||||
|
into->AddInt32(kPartialDownloadLimit, atoi(fSizeBox->Text()) * 1024);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
//--------------------Support functions and #defines---------------
|
//--------------------Support functions and #defines---------------
|
||||||
@@ -48,7 +131,7 @@ TextControl(BView *parent,const char *name)
|
|||||||
|
|
||||||
|
|
||||||
BTextControl *
|
BTextControl *
|
||||||
AddTextField (BRect &rect, const char *name, const char *label)
|
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);
|
BTextControl *text_control = new BTextControl(rect,name,label,"",NULL,B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP);
|
||||||
// text_control->SetDivider(be_plain_font->StringWidth(label));
|
// text_control->SetDivider(be_plain_font->StringWidth(label));
|
||||||
@@ -104,7 +187,9 @@ FindWidestLabel(BView *view)
|
|||||||
//----------------Real code----------------------
|
//----------------Real code----------------------
|
||||||
BMailProtocolConfigView::BMailProtocolConfigView(uint32 options_mask)
|
BMailProtocolConfigView::BMailProtocolConfigView(uint32 options_mask)
|
||||||
:
|
:
|
||||||
BView (BRect(0,0,100,20), "protocol_config_view", B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW)
|
BView (BRect(0,0,100,20), "protocol_config_view", B_FOLLOW_LEFT
|
||||||
|
| B_FOLLOW_TOP, B_WILL_DRAW),
|
||||||
|
fBodyDownloadConfig(NULL)
|
||||||
{
|
{
|
||||||
BRect rect(5,5,245,25);
|
BRect rect(5,5,245,25);
|
||||||
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
||||||
@@ -147,6 +232,12 @@ BMailProtocolConfigView::BMailProtocolConfigView(uint32 options_mask)
|
|||||||
AddChild(box);
|
AddChild(box);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (options_mask & B_MAIL_PROTOCOL_PARTIAL_DOWNLOAD) {
|
||||||
|
fBodyDownloadConfig = new BodyDownloadConfig();
|
||||||
|
fBodyDownloadConfig->MoveBy(0, rect.bottom + 5);
|
||||||
|
AddChild(fBodyDownloadConfig);
|
||||||
|
}
|
||||||
|
|
||||||
// resize views
|
// resize views
|
||||||
float height;
|
float height;
|
||||||
GetPreferredSize(&width,&height);
|
GetPreferredSize(&width,&height);
|
||||||
@@ -165,21 +256,23 @@ BMailProtocolConfigView::~BMailProtocolConfigView()
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BMailProtocolConfigView::SetTo(BMessage *archive)
|
BMailProtocolConfigView::SetTo(MailAddonSettings& settings)
|
||||||
{
|
{
|
||||||
|
const BMessage* archive = &settings.Settings();
|
||||||
|
|
||||||
BString host = archive->FindString("server");
|
BString host = archive->FindString("server");
|
||||||
if (archive->HasInt32("port"))
|
if (archive->HasInt32("port"))
|
||||||
host << ':' << archive->FindInt32("port");
|
host << ':' << archive->FindInt32("port");
|
||||||
|
|
||||||
SetTextControl(this,"host",host.String());
|
SetTextControl(this,"host", host.String());
|
||||||
SetTextControl(this,"user",archive->FindString("username"));
|
SetTextControl(this,"user", archive->FindString("username"));
|
||||||
|
|
||||||
char *password = get_passwd(archive,"cpasswd");
|
char *password = get_passwd(archive, "cpasswd");
|
||||||
if (password) {
|
if (password) {
|
||||||
SetTextControl(this,"pass",password);
|
SetTextControl(this,"pass", password);
|
||||||
delete[] password;
|
delete[] password;
|
||||||
} else
|
} else
|
||||||
SetTextControl(this,"pass",archive->FindString("password"));
|
SetTextControl(this,"pass", archive->FindString("password"));
|
||||||
|
|
||||||
if (archive->HasInt32("flavor")) {
|
if (archive->HasInt32("flavor")) {
|
||||||
BMenuField *menu = (BMenuField *)(FindView("flavor"));
|
BMenuField *menu = (BMenuField *)(FindView("flavor"));
|
||||||
@@ -216,6 +309,9 @@ BMailProtocolConfigView::SetTo(BMessage *archive)
|
|||||||
else
|
else
|
||||||
box->SetEnabled(false);
|
box->SetEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fBodyDownloadConfig)
|
||||||
|
fBodyDownloadConfig->SetTo(settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -286,7 +382,7 @@ BMailProtocolConfigView::MessageReceived(BMessage *msg)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
BMailProtocolConfigView::Archive(BMessage *into, bool) const
|
BMailProtocolConfigView::Archive(BMessage *into, bool deep) const
|
||||||
{
|
{
|
||||||
const char *host = TextControl((BView *)this,"host");
|
const char *host = TextControl((BView *)this,"host");
|
||||||
int32 port = -1;
|
int32 port = -1;
|
||||||
@@ -348,7 +444,9 @@ BMailProtocolConfigView::Archive(BMessage *into, bool) const
|
|||||||
if (into->ReplaceBool("delete_remote_when_local",false) != B_OK)
|
if (into->ReplaceBool("delete_remote_when_local",false) != B_OK)
|
||||||
into->AddBool("delete_remote_when_local",false);
|
into->AddBool("delete_remote_when_local",false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fBodyDownloadConfig)
|
||||||
|
fBodyDownloadConfig->Archive(into, deep);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -365,5 +463,11 @@ BMailProtocolConfigView::GetPreferredSize(float *width, float *height)
|
|||||||
minWidth = 250;
|
minWidth = 250;
|
||||||
*width = minWidth + 10;
|
*width = minWidth + 10;
|
||||||
*height = (CountChildren() * sItemHeight) + 5;
|
*height = (CountChildren() * sItemHeight) + 5;
|
||||||
|
|
||||||
|
if (fBodyDownloadConfig) {
|
||||||
|
float bodyW, bodyH;
|
||||||
|
fBodyDownloadConfig->GetPreferredSize(&bodyW, &bodyH);
|
||||||
|
*height+= bodyH;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,438 +0,0 @@
|
|||||||
#include <NodeMonitor.h>
|
|
||||||
#include <Handler.h>
|
|
||||||
#include <Directory.h>
|
|
||||||
#include <Entry.h>
|
|
||||||
#include <Path.h>
|
|
||||||
#include <String.h>
|
|
||||||
#include <File.h>
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
class _EXPORT BRemoteMailStorageProtocol;
|
|
||||||
|
|
||||||
#include <RemoteStorageProtocol.h>
|
|
||||||
#include <ChainRunner.h>
|
|
||||||
#include <E-mail.h>
|
|
||||||
|
|
||||||
using std::map;
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
void GetSubFolders(BDirectory *of, BStringList *folders, const char *prepend = "");
|
|
||||||
|
|
||||||
class UpdateHandler : public BHandler {
|
|
||||||
public:
|
|
||||||
UpdateHandler(BRemoteMailStorageProtocol *prot, const char *dest)
|
|
||||||
: fProtocol(prot), fDestination(dest)
|
|
||||||
{
|
|
||||||
node_ref ref;
|
|
||||||
fDestination.GetNodeRef(&ref);
|
|
||||||
fDestinationNode = ref.node;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~UpdateHandler()
|
|
||||||
{
|
|
||||||
stop_watching(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MessageReceived(BMessage *msg)
|
|
||||||
{
|
|
||||||
switch (msg->what) {
|
|
||||||
case 'INIT': {
|
|
||||||
if (fProtocol->InitCheck() < B_OK)
|
|
||||||
return;
|
|
||||||
|
|
||||||
((BMailChainRunner *)(Looper()))->ReportProgress(0, 0,
|
|
||||||
"Synchronizing Mailboxes");
|
|
||||||
|
|
||||||
BStringList subdirs;
|
|
||||||
GetSubFolders(&fDestination, &subdirs);
|
|
||||||
BStringList to_delete;
|
|
||||||
BStringList to_add;
|
|
||||||
subdirs.NotThere(fProtocol->mailboxes, &to_add);
|
|
||||||
if (subdirs.CountItems() != 0) {
|
|
||||||
// If it's a virgin mailfolder, the user probably just configured
|
|
||||||
// his machine and probably *doesn't* want all his mail folders deleted :)
|
|
||||||
subdirs.NotHere(fProtocol->mailboxes, &to_delete);
|
|
||||||
}
|
|
||||||
for (int32 i = 0; i < to_add.CountItems(); i++) {
|
|
||||||
if (fProtocol->CreateMailbox(to_add[i]) != B_OK)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
fProtocol->mailboxes += to_add[i];
|
|
||||||
fProtocol->SyncMailbox(to_add[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
fProtocol->CheckForDeletedMessages();
|
|
||||||
// Refresh the manifest list, delete messages in locally deleted folders
|
|
||||||
|
|
||||||
for (int32 i = 0; i < to_delete.CountItems(); i++) {
|
|
||||||
if (to_delete[i][0] == 0)
|
|
||||||
continue;
|
|
||||||
if (fProtocol->DeleteMailbox(to_delete[i]) == B_OK)
|
|
||||||
fProtocol->mailboxes -= to_delete[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
entry_ref ref;
|
|
||||||
BEntry entry;
|
|
||||||
fDestination.GetEntry(&entry);
|
|
||||||
entry.GetRef(&ref);
|
|
||||||
BPath path(&ref), work_path(path);
|
|
||||||
BNode node(&ref);
|
|
||||||
node_ref watcher;
|
|
||||||
node.GetNodeRef(&watcher);
|
|
||||||
watch_node(&watcher,B_WATCH_DIRECTORY,this);
|
|
||||||
|
|
||||||
for (int32 i = 0; i < fProtocol->mailboxes.CountItems(); i++) {
|
|
||||||
work_path = path;
|
|
||||||
work_path.Append(fProtocol->mailboxes[i]);
|
|
||||||
node.SetTo(work_path.Path());
|
|
||||||
node.GetNodeRef(&watcher);
|
|
||||||
fNodes[watcher.node] = strdup(fProtocol->mailboxes[i]);
|
|
||||||
if (fProtocol->mailboxes[i][0] == 0) {
|
|
||||||
// We've covered this in the parent monitor
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
watch_node(&watcher, B_WATCH_DIRECTORY, this);
|
|
||||||
fProtocol->SyncMailbox(fProtocol->mailboxes[i]);
|
|
||||||
}
|
|
||||||
((BMailChainRunner *)(Looper()))->ResetProgress();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case B_NODE_MONITOR: {
|
|
||||||
int32 opcode;
|
|
||||||
if (msg->FindInt32("opcode", &opcode) < B_OK)
|
|
||||||
break;
|
|
||||||
|
|
||||||
int64 directory, node(msg->FindInt64("node"));
|
|
||||||
dev_t device(msg->FindInt32("device"));
|
|
||||||
|
|
||||||
bool is_dir;
|
|
||||||
{
|
|
||||||
node_ref item_ref;
|
|
||||||
item_ref.node = node;
|
|
||||||
item_ref.device = device;
|
|
||||||
BDirectory dir(&item_ref);
|
|
||||||
is_dir = (dir.InitCheck() == B_OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opcode == B_ENTRY_MOVED) {
|
|
||||||
ino_t from, to;
|
|
||||||
msg->FindInt64("from directory", &from);
|
|
||||||
msg->FindInt64("to directory", &to);
|
|
||||||
const char *from_mb(fNodes[from]), *to_mb(fNodes[to]);
|
|
||||||
if (to == fDestinationNode)
|
|
||||||
to_mb = "";
|
|
||||||
if (from == fDestinationNode)
|
|
||||||
from_mb = "";
|
|
||||||
if (from_mb == NULL) {
|
|
||||||
msg->AddInt64("directory", to);
|
|
||||||
opcode = B_ENTRY_CREATED;
|
|
||||||
} else if (to_mb == NULL) {
|
|
||||||
msg->AddInt64("directory", from);
|
|
||||||
if (is_dir)
|
|
||||||
opcode = B_ENTRY_REMOVED;
|
|
||||||
} else {
|
|
||||||
if (!is_dir) {
|
|
||||||
{
|
|
||||||
node_ref item_ref;
|
|
||||||
item_ref.node = to;
|
|
||||||
item_ref.device = device;
|
|
||||||
BDirectory dir(&item_ref);
|
|
||||||
BNode node(&dir,msg->FindString("name"));
|
|
||||||
// Why in HELL can't you make a BNode from a node_ref?
|
|
||||||
|
|
||||||
if (node.InitCheck() != B_OK) {
|
|
||||||
// We're late, it's already gone elsewhere. Ignore for now.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
BString id;
|
|
||||||
node.ReadAttrString("MAIL:unique_id", &id);
|
|
||||||
id.Truncate(id.FindLast('/'));
|
|
||||||
if (id == to_mb) {
|
|
||||||
// Already where it belongs, no need to do anything
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
snooze(uint64(5e5));
|
|
||||||
fProtocol->SyncMailbox(to_mb);
|
|
||||||
|
|
||||||
//node.WriteAttrString("MAIL:unique_id",&id);
|
|
||||||
|
|
||||||
fProtocol->CheckForDeletedMessages();
|
|
||||||
} else {
|
|
||||||
BString mb;
|
|
||||||
if (to_mb[0] == 0)
|
|
||||||
mb = msg->FindString("name");
|
|
||||||
else {
|
|
||||||
mb = to_mb;
|
|
||||||
mb << '/' << msg->FindString("name");
|
|
||||||
}
|
|
||||||
if (strcmp(mb.String(), fNodes[node]) == 0)
|
|
||||||
break;
|
|
||||||
if (fProtocol->CreateMailbox(mb.String()) < B_OK)
|
|
||||||
break;
|
|
||||||
fProtocol->mailboxes += mb.String();
|
|
||||||
fProtocol->SyncMailbox(mb.String());
|
|
||||||
fProtocol->CheckForDeletedMessages();
|
|
||||||
fProtocol->DeleteMailbox(fNodes[node]);
|
|
||||||
fProtocol->mailboxes -= fNodes[node];
|
|
||||||
free((void *)fNodes[node]);
|
|
||||||
fNodes[node] = strdup(mb.String());
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
msg->FindInt64("directory", &directory);
|
|
||||||
switch (opcode) {
|
|
||||||
case B_ENTRY_CREATED:
|
|
||||||
if (!is_dir) {
|
|
||||||
const char *dir = fNodes[directory];
|
|
||||||
snooze(500000);
|
|
||||||
// half a second
|
|
||||||
|
|
||||||
if (dir == NULL)
|
|
||||||
dir = "";
|
|
||||||
|
|
||||||
if (!fProtocol->mailboxes.HasItem(dir))
|
|
||||||
break;
|
|
||||||
|
|
||||||
{
|
|
||||||
node_ref nodeRef;
|
|
||||||
nodeRef.node = directory;
|
|
||||||
nodeRef.device = device;
|
|
||||||
BDirectory dir(&nodeRef);
|
|
||||||
|
|
||||||
BNode node(&dir, msg->FindString("name"));
|
|
||||||
if (node.InitCheck() != B_OK)
|
|
||||||
break; //-- We're late, it's already gone elsewhere. Ignore for now.
|
|
||||||
}
|
|
||||||
|
|
||||||
fProtocol->SyncMailbox(fNodes[directory]);
|
|
||||||
} else {
|
|
||||||
BString mb;
|
|
||||||
if (directory == fDestinationNode)
|
|
||||||
mb = msg->FindString("name");
|
|
||||||
else {
|
|
||||||
mb = fNodes[directory];
|
|
||||||
mb << '/' << msg->FindString("name");
|
|
||||||
}
|
|
||||||
if (fProtocol->CreateMailbox(mb.String()) < B_OK)
|
|
||||||
break;
|
|
||||||
|
|
||||||
fNodes[node] = strdup(mb.String());
|
|
||||||
fProtocol->mailboxes += mb.String();
|
|
||||||
fProtocol->SyncMailbox(mb.String());
|
|
||||||
node_ref ref;
|
|
||||||
ref.device = device;
|
|
||||||
ref.node = node;
|
|
||||||
watch_node(&ref, B_WATCH_DIRECTORY, this);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case B_ENTRY_REMOVED:
|
|
||||||
fProtocol->CheckForDeletedMessages();
|
|
||||||
if ((is_dir) && (fNodes[node] != NULL)) {
|
|
||||||
fProtocol->DeleteMailbox(fNodes[node]);
|
|
||||||
fProtocol->mailboxes -= fNodes[node];
|
|
||||||
free((void *)fNodes[node]);
|
|
||||||
fNodes[node] = NULL;
|
|
||||||
node_ref ref;
|
|
||||||
ref.device = device;
|
|
||||||
ref.node = node;
|
|
||||||
watch_node(&ref, B_STOP_WATCHING, this);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
BRemoteMailStorageProtocol *fProtocol;
|
|
||||||
BDirectory fDestination;
|
|
||||||
|
|
||||||
map<int64, const char *> fNodes;
|
|
||||||
ino_t fDestinationNode;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
GetSubFolders(BDirectory *of, BStringList *folders, const char *prepend)
|
|
||||||
{
|
|
||||||
of->Rewind();
|
|
||||||
|
|
||||||
BEntry entry;
|
|
||||||
while (of->GetNextEntry(&entry) == B_OK) {
|
|
||||||
if (!entry.IsDirectory())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
BDirectory subDirectory(&entry);
|
|
||||||
|
|
||||||
char buffer[B_FILE_NAME_LENGTH];
|
|
||||||
entry.GetName(buffer);
|
|
||||||
|
|
||||||
BString path = prepend;
|
|
||||||
path << buffer << '/';
|
|
||||||
GetSubFolders(&subDirectory, folders, path.String());
|
|
||||||
path = prepend;
|
|
||||||
path << buffer;
|
|
||||||
*folders += path.String();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // unnamed namspace
|
|
||||||
|
|
||||||
|
|
||||||
BRemoteMailStorageProtocol::BRemoteMailStorageProtocol(BMessage *settings,
|
|
||||||
BMailChainRunner *runner)
|
|
||||||
: BMailProtocol(settings, runner)
|
|
||||||
{
|
|
||||||
handler = new UpdateHandler(this, runner->Chain()->MetaData()->FindString("path"));
|
|
||||||
runner->AddHandler(handler);
|
|
||||||
runner->PostMessage('INIT', handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BRemoteMailStorageProtocol::~BRemoteMailStorageProtocol()
|
|
||||||
{
|
|
||||||
delete handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//----BMailProtocol stuff
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
BRemoteMailStorageProtocol::GetMessage(const char *uid,
|
|
||||||
BPositionIO **outFile, BMessage *outHeaders,
|
|
||||||
BPath *outFolderLocation)
|
|
||||||
{
|
|
||||||
BString folder(uid), id;
|
|
||||||
{
|
|
||||||
BString raw(uid);
|
|
||||||
folder.Truncate(raw.FindLast('/'));
|
|
||||||
raw.CopyInto(id, raw.FindLast('/') + 1, raw.Length());
|
|
||||||
}
|
|
||||||
|
|
||||||
*outFolderLocation = folder.String();
|
|
||||||
return GetMessage(folder.String(), id.String(), outFile, outHeaders);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
BRemoteMailStorageProtocol::DeleteMessage(const char *uid)
|
|
||||||
{
|
|
||||||
BString folder(uid), id;
|
|
||||||
{
|
|
||||||
BString raw(uid);
|
|
||||||
int32 j = raw.FindLast('/');
|
|
||||||
folder.Truncate(j);
|
|
||||||
raw.CopyInto(id, j + 1, raw.Length());
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t err;
|
|
||||||
if ((err = DeleteMessage(folder.String(), id.String())) < B_OK)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
*unique_ids -= uid;
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
BRemoteMailStorageProtocol::SyncMailbox(const char *mailbox)
|
|
||||||
{
|
|
||||||
BPath path(runner->Chain()->MetaData()->FindString("path"));
|
|
||||||
path.Append(mailbox);
|
|
||||||
|
|
||||||
BDirectory folder(path.Path());
|
|
||||||
|
|
||||||
BEntry entry;
|
|
||||||
BString string;
|
|
||||||
uint32 chain;
|
|
||||||
bool append;
|
|
||||||
|
|
||||||
if (!mailboxes.HasItem(mailbox))
|
|
||||||
return; // -- Basic Sanity Checking
|
|
||||||
|
|
||||||
while (folder.GetNextEntry(&entry) == B_OK) {
|
|
||||||
if (!entry.IsFile())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
BFile file;
|
|
||||||
while (file.SetTo(&entry, B_READ_WRITE) == B_BUSY)
|
|
||||||
snooze(100);
|
|
||||||
append = false;
|
|
||||||
|
|
||||||
while (file.Lock() != B_OK)
|
|
||||||
snooze(100);
|
|
||||||
file.Unlock();
|
|
||||||
|
|
||||||
if (file.ReadAttr("MAIL:chain", B_INT32_TYPE, 0, &chain, sizeof(chain)) < B_OK)
|
|
||||||
append = true;
|
|
||||||
|
|
||||||
if (chain != runner->Chain()->ID()) {
|
|
||||||
uint32 pendingChain(~0UL), flags(0);
|
|
||||||
file.ReadAttr("MAIL:pending_chain", B_INT32_TYPE, 0, &pendingChain, sizeof(chain));
|
|
||||||
file.ReadAttr("MAIL:flags", B_INT32_TYPE, 0, &flags, sizeof(flags));
|
|
||||||
|
|
||||||
if (pendingChain == runner->Chain()->ID()
|
|
||||||
&& BMailChain(chain).ChainDirection() == outbound
|
|
||||||
&& (flags & B_MAIL_PENDING) != 0) {
|
|
||||||
// Ignore this message, recode the chain attribute at the next SyncMailbox()
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pendingChain == runner->Chain()->ID()) {
|
|
||||||
chain = runner->Chain()->ID();
|
|
||||||
file.WriteAttr("MAIL:chain", B_INT32_TYPE, 0, &chain, sizeof(chain));
|
|
||||||
append = false;
|
|
||||||
} else
|
|
||||||
append = true;
|
|
||||||
}
|
|
||||||
if (file.ReadAttrString("MAIL:unique_id", &string) < B_OK)
|
|
||||||
append = true;
|
|
||||||
|
|
||||||
BString folder(string), id("");
|
|
||||||
int32 j = string.FindLast('/');
|
|
||||||
if (!append && j >= 0) {
|
|
||||||
folder.Truncate(j);
|
|
||||||
string.CopyInto(id, j + 1, string.Length());
|
|
||||||
if (folder == mailbox)
|
|
||||||
continue;
|
|
||||||
} else
|
|
||||||
append = true;
|
|
||||||
|
|
||||||
if (append) {
|
|
||||||
// ToDo: We should check for partial messages here
|
|
||||||
AddMessage(mailbox, &file, &id);
|
|
||||||
} else
|
|
||||||
CopyMessage(folder.String(), mailbox, &id);
|
|
||||||
|
|
||||||
string = mailbox;
|
|
||||||
string << '/' << id;
|
|
||||||
/*file.RemoveAttr("MAIL:unique_id");
|
|
||||||
file.RemoveAttr("MAIL:chain");*/
|
|
||||||
chain = runner->Chain()->ID();
|
|
||||||
|
|
||||||
int32 flags = 0;
|
|
||||||
file.ReadAttr("MAIL:flags", B_INT32_TYPE, 0, &flags, sizeof(flags));
|
|
||||||
|
|
||||||
if (flags & B_MAIL_PENDING)
|
|
||||||
file.WriteAttr("MAIL:pending_chain", B_INT32_TYPE, 0, &chain, sizeof(chain));
|
|
||||||
else
|
|
||||||
file.WriteAttr("MAIL:chain", B_INT32_TYPE, 0, &chain, sizeof(chain));
|
|
||||||
file.WriteAttrString("MAIL:unique_id", &string);
|
|
||||||
*manifest += string.String();
|
|
||||||
*unique_ids += string.String();
|
|
||||||
string = runner->Chain()->Name();
|
|
||||||
file.WriteAttrString("MAIL:account", &string);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,138 +0,0 @@
|
|||||||
/* BMailMessage - compatibility wrapper to our mail message class
|
|
||||||
**
|
|
||||||
** Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
//------This entire document is a horrible, horrible hack. I apologize.
|
|
||||||
#include <Entry.h>
|
|
||||||
|
|
||||||
class _EXPORT BMailMessage;
|
|
||||||
|
|
||||||
#include <E-mail.h>
|
|
||||||
|
|
||||||
#include <MailAttachment.h>
|
|
||||||
#include <MailMessage.h>
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
struct CharsetConversionEntry
|
|
||||||
{
|
|
||||||
const char *charset;
|
|
||||||
uint32 flavor;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern const CharsetConversionEntry mail_charsets[];
|
|
||||||
|
|
||||||
|
|
||||||
BMailMessage::BMailMessage(void)
|
|
||||||
: fFields((BList *)(new BEmailMessage()))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
BMailMessage::~BMailMessage(void)
|
|
||||||
{
|
|
||||||
delete ((BEmailMessage *)(fFields));
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t BMailMessage::AddContent(const char *text, int32 length,
|
|
||||||
uint32 encoding, bool /*clobber*/)
|
|
||||||
{
|
|
||||||
BTextMailComponent *comp = new BTextMailComponent;
|
|
||||||
BMemoryIO io(text,length);
|
|
||||||
comp->SetDecodedData(&io);
|
|
||||||
|
|
||||||
comp->SetEncoding(quoted_printable,encoding);
|
|
||||||
|
|
||||||
//if (clobber)
|
|
||||||
((BEmailMessage *)(fFields))->AddComponent(comp);
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t BMailMessage::AddContent(const char *text, int32 length,
|
|
||||||
const char *encoding, bool /*clobber*/)
|
|
||||||
{
|
|
||||||
BTextMailComponent *comp = new BTextMailComponent();
|
|
||||||
BMemoryIO io(text,length);
|
|
||||||
comp->SetDecodedData(&io);
|
|
||||||
|
|
||||||
uint32 encode = B_ISO1_CONVERSION;
|
|
||||||
//-----I'm assuming that encoding is one of the RFC charsets
|
|
||||||
//-----there are no docs. Am I right?
|
|
||||||
if (encoding != NULL) {
|
|
||||||
for (int32 i = 0; mail_charsets[i].charset != NULL; i++) {
|
|
||||||
if (strcasecmp(encoding,mail_charsets[i].charset) == 0) {
|
|
||||||
encode = mail_charsets[i].flavor;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
comp->SetEncoding(quoted_printable,encode);
|
|
||||||
|
|
||||||
//if (clobber)
|
|
||||||
((BEmailMessage *)(fFields))->AddComponent(comp);
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t BMailMessage::AddEnclosure(entry_ref *ref, bool /*clobber*/)
|
|
||||||
{
|
|
||||||
((BEmailMessage *)(fFields))->Attach(ref);
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t BMailMessage::AddEnclosure(const char *path, bool /*clobber*/)
|
|
||||||
{
|
|
||||||
BEntry entry(path);
|
|
||||||
status_t status;
|
|
||||||
if ((status = entry.InitCheck()) < B_OK)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
entry_ref ref;
|
|
||||||
if ((status = entry.GetRef(&ref)) < B_OK)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
((BEmailMessage *)(fFields))->Attach(&ref);
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t BMailMessage::AddEnclosure(const char *MIME_type, void *data, int32 len,
|
|
||||||
bool /*clobber*/)
|
|
||||||
{
|
|
||||||
BSimpleMailAttachment *attach = new BSimpleMailAttachment;
|
|
||||||
attach->SetDecodedData(data,len);
|
|
||||||
attach->SetHeaderField("Content-Type",MIME_type);
|
|
||||||
|
|
||||||
((BEmailMessage *)(fFields))->AddComponent(attach);
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t BMailMessage::AddHeaderField(uint32 /*encoding*/, const char *field_name, const char *str,
|
|
||||||
bool /*clobber*/)
|
|
||||||
{
|
|
||||||
//printf("First AddHeaderField. Args are %s%s\n",field_name,str);
|
|
||||||
|
|
||||||
BString string = field_name;
|
|
||||||
string.Truncate(string.Length() - 2); //----BMailMessage includes the ": "
|
|
||||||
((BEmailMessage *)(fFields))->SetHeaderField(string.String(),str);
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t BMailMessage::AddHeaderField(const char *field_name, const char *str,
|
|
||||||
bool /*clobber*/)
|
|
||||||
{
|
|
||||||
//printf("Second AddHeaderField. Args are %s%s\n",field_name,str);
|
|
||||||
BString string = field_name;
|
|
||||||
string.Truncate(string.Length() - 2); //----BMailMessage includes the ": "
|
|
||||||
((BEmailMessage *)(fFields))->SetHeaderField(string.String(),str);
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t BMailMessage::Send(bool send_now,
|
|
||||||
bool /*remove_when_I_have_completed_sending_this_message_to_your_preferred_SMTP_server*/)
|
|
||||||
{
|
|
||||||
return ((BEmailMessage *)(fFields))->Send(send_now);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,141 +0,0 @@
|
|||||||
/* C-mail API - compatibility function (stubs) for the old mail kit
|
|
||||||
**
|
|
||||||
** Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include <E-mail.h>
|
|
||||||
#include <FindDirectory.h>
|
|
||||||
#include <Path.h>
|
|
||||||
#include <File.h>
|
|
||||||
#include <Directory.h>
|
|
||||||
#include <List.h>
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <MailDaemon.h>
|
|
||||||
#include <MailSettings.h>
|
|
||||||
#include <MailMessage.h>
|
|
||||||
#include <crypt.h>
|
|
||||||
|
|
||||||
|
|
||||||
_EXPORT status_t 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
_EXPORT status_t send_queued_mail(void)
|
|
||||||
{
|
|
||||||
return BMailDaemon::SendQueuedMail();
|
|
||||||
}
|
|
||||||
|
|
||||||
_EXPORT int32 count_pop_accounts(void)
|
|
||||||
{
|
|
||||||
BPath path;
|
|
||||||
status_t status = find_directory(B_USER_SETTINGS_DIRECTORY,&path);
|
|
||||||
if (status < B_OK)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
path.Append("Mail/chains/inbound");
|
|
||||||
BDirectory dir(path.Path());
|
|
||||||
return dir.CountEntries();
|
|
||||||
}
|
|
||||||
|
|
||||||
_EXPORT status_t get_mail_notification(mail_notification *notification)
|
|
||||||
{
|
|
||||||
notification->alert = true;
|
|
||||||
notification->beep = false;
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
_EXPORT status_t set_mail_notification(mail_notification *, bool)
|
|
||||||
{
|
|
||||||
return B_NO_REPLY;
|
|
||||||
}
|
|
||||||
|
|
||||||
_EXPORT status_t get_pop_account(mail_pop_account* account, int32 index)
|
|
||||||
{
|
|
||||||
status_t err = B_OK;
|
|
||||||
const char *password, *passwd;
|
|
||||||
BMessage settings;
|
|
||||||
|
|
||||||
BList chains;
|
|
||||||
GetInboundMailChains(&chains);
|
|
||||||
|
|
||||||
BMailChain *chain = (BMailChain *)(chains.ItemAt(index));
|
|
||||||
if (chain == NULL) {
|
|
||||||
err = B_BAD_INDEX;
|
|
||||||
goto clean_up; //------Eek! A goto!
|
|
||||||
}
|
|
||||||
|
|
||||||
chain->GetFilter(0,&settings);
|
|
||||||
strcpy(account->pop_name,settings.FindString("username"));
|
|
||||||
strcpy(account->pop_host,settings.FindString("server"));
|
|
||||||
strcpy(account->real_name,chain->MetaData()->FindString("real_name"));
|
|
||||||
strcpy(account->reply_to,chain->MetaData()->FindString("reply_to"));
|
|
||||||
|
|
||||||
password = settings.FindString("password");
|
|
||||||
passwd = get_passwd(&settings,"cpasswd");
|
|
||||||
if (passwd)
|
|
||||||
password = passwd;
|
|
||||||
strcpy(account->pop_password,password);
|
|
||||||
|
|
||||||
//-------Note that we don't do the scheduling flags
|
|
||||||
|
|
||||||
clean_up:
|
|
||||||
for (int32 i = 0; i < chains.CountItems(); i++)
|
|
||||||
delete (BMailChain *)chains.ItemAt(i);
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
_EXPORT status_t set_pop_account(mail_pop_account *, int32, bool)
|
|
||||||
{
|
|
||||||
return B_NO_REPLY;
|
|
||||||
}
|
|
||||||
|
|
||||||
_EXPORT status_t get_smtp_host(char* buffer)
|
|
||||||
{
|
|
||||||
BMailChain chain(BMailSettings().DefaultOutboundChainID());
|
|
||||||
status_t err = chain.InitCheck();
|
|
||||||
if (err < B_OK)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
BMessage settings;
|
|
||||||
err = chain.GetFilter(chain.CountFilters() - 1,&settings);
|
|
||||||
if (err < B_OK)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
if (settings.HasString("server"))
|
|
||||||
strcpy(buffer,settings.FindString("server"));
|
|
||||||
else
|
|
||||||
return B_NAME_NOT_FOUND;
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
_EXPORT status_t set_smtp_host(char * /* host */, bool /* save */)
|
|
||||||
{
|
|
||||||
return B_NO_REPLY;
|
|
||||||
}
|
|
||||||
|
|
||||||
_EXPORT status_t forward_mail(entry_ref *ref, const char *recipients, bool now)
|
|
||||||
{
|
|
||||||
BFile file(ref, O_RDONLY);
|
|
||||||
status_t status = file.InitCheck();
|
|
||||||
if (status < B_OK)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
BEmailMessage mail(&file);
|
|
||||||
mail.SetTo(recipients);
|
|
||||||
|
|
||||||
return mail.Send(now);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
#include <mail_encoding.h>
|
|
||||||
|
|
||||||
#if __MWERKS__
|
|
||||||
#define encode_base64__local_abi encode_base64__FPcPcx
|
|
||||||
#define decode_base64__local_abi decode_base64__FPcPcxb
|
|
||||||
#define USETHISFILEATALL 1
|
|
||||||
#elif __GNUC__ <= 2
|
|
||||||
#define encode_base64__local_abi encode_base64__FPcT0x
|
|
||||||
#define decode_base64__local_abi decode_base64__FPcT0xb
|
|
||||||
#define USETHISFILEATALL 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if USETHISFILEATALL /* If we are using GCC >= 3 or something else, we clearly have given up on binary compat anyway */
|
|
||||||
|
|
||||||
ssize_t encode_base64__local_abi(char *out, char *in, off_t length);
|
|
||||||
ssize_t decode_base64__local_abi(char *out, char *in, off_t length, char);
|
|
||||||
|
|
||||||
_EXPORT ssize_t encode_base64__local_abi(char *out, char *in, off_t length) {
|
|
||||||
return encode_base64(out,in,length,0 /* headerMode */);
|
|
||||||
}
|
|
||||||
|
|
||||||
_EXPORT ssize_t decode_base64__local_abi(char *out, char *in, off_t length, char nothing) {
|
|
||||||
nothing = '\0';
|
|
||||||
return decode_base64(out,in,length);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
static const char key[PASSWORD_LENGTH + 1] = "Dr. Zoidberg Enterprises, BeMail";
|
static const char key[PASSWORD_LENGTH + 1] = "Dr. Zoidberg Enterprises, BeMail";
|
||||||
|
|
||||||
|
|
||||||
_EXPORT char *get_passwd(BMessage *msg,const char *name)
|
_EXPORT char *get_passwd(const BMessage *msg,const char *name)
|
||||||
{
|
{
|
||||||
char *encryptedPassword;
|
char *encryptedPassword;
|
||||||
ssize_t length;
|
ssize_t length;
|
||||||
|
|||||||
@@ -1376,6 +1376,56 @@ parse_header(BMessage &headers, BPositionIO &input)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
_EXPORT status_t
|
||||||
|
extract_from_header(const BString& header, const BString& field,
|
||||||
|
BString& target)
|
||||||
|
{
|
||||||
|
int32 headerLength = header.Length();
|
||||||
|
int32 fieldEndPos = 0;
|
||||||
|
while (true) {
|
||||||
|
int32 pos = header.IFindFirst(field, fieldEndPos);
|
||||||
|
if (pos < 0)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
fieldEndPos = pos + field.Length();
|
||||||
|
|
||||||
|
if (pos != 0 && header.ByteAt(pos - 1) != '\n')
|
||||||
|
continue;
|
||||||
|
if (header.ByteAt(fieldEndPos) == ':')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fieldEndPos++;
|
||||||
|
|
||||||
|
int32 crPos = fieldEndPos;
|
||||||
|
while (true) {
|
||||||
|
fieldEndPos = crPos;
|
||||||
|
crPos = header.FindFirst('\n', crPos);
|
||||||
|
if (crPos < 0)
|
||||||
|
crPos = headerLength;
|
||||||
|
BString temp;
|
||||||
|
header.CopyInto(temp, fieldEndPos, crPos - fieldEndPos);
|
||||||
|
if (header.ByteAt(crPos - 1) == '\r') {
|
||||||
|
temp.Truncate(temp.Length() - 1);
|
||||||
|
temp += " ";
|
||||||
|
}
|
||||||
|
target += temp;
|
||||||
|
crPos++;
|
||||||
|
if (crPos >= headerLength)
|
||||||
|
break;
|
||||||
|
char nextByte = header.ByteAt(crPos);
|
||||||
|
if (nextByte != ' ' && nextByte != '\t')
|
||||||
|
break;
|
||||||
|
crPos++;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t bufferSize = target.Length();
|
||||||
|
char* buffer = target.LockBuffer(bufferSize);
|
||||||
|
size_t length = rfc2047_to_utf8(&buffer, &bufferSize, bufferSize);
|
||||||
|
target.UnlockBuffer(length);
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
_EXPORT void
|
_EXPORT void
|
||||||
extract_address(BString &address)
|
extract_address(BString &address)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -222,10 +222,10 @@ DeskbarView::MessageReceived(BMessage* message)
|
|||||||
case MD_CHECK_SEND_NOW:
|
case MD_CHECK_SEND_NOW:
|
||||||
// also happens in DeskbarView::MouseUp() with
|
// also happens in DeskbarView::MouseUp() with
|
||||||
// B_TERTIARY_MOUSE_BUTTON pressed
|
// B_TERTIARY_MOUSE_BUTTON pressed
|
||||||
BMailDaemon::CheckMail(true);
|
BMailDaemon::CheckAndSendQueuedMail();
|
||||||
break;
|
break;
|
||||||
case MD_CHECK_FOR_MAILS:
|
case MD_CHECK_FOR_MAILS:
|
||||||
BMailDaemon::CheckMail(false,message->FindString("account"));
|
BMailDaemon::CheckMail(message->FindInt32("account"));
|
||||||
break;
|
break;
|
||||||
case MD_SEND_MAILS:
|
case MD_SEND_MAILS:
|
||||||
BMailDaemon::SendQueuedMail();
|
BMailDaemon::SendQueuedMail();
|
||||||
@@ -365,7 +365,7 @@ DeskbarView::MouseUp(BPoint pos)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (fLastButtons & B_TERTIARY_MOUSE_BUTTON)
|
if (fLastButtons & B_TERTIARY_MOUSE_BUTTON)
|
||||||
BMailDaemon::CheckMail(true);
|
BMailDaemon::CheckMail();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -556,32 +556,30 @@ DeskbarView::_BuildMenu()
|
|||||||
item->SetEnabled(false);
|
item->SetEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
BList list;
|
BMailAccounts accounts;
|
||||||
GetInboundMailChains(&list);
|
|
||||||
|
|
||||||
if (modifiers() & B_SHIFT_KEY) {
|
if (modifiers() & B_SHIFT_KEY) {
|
||||||
BMenu *chainMenu = new BMenu(
|
BMenu *accountMenu = new BMenu(
|
||||||
MDR_DIALECT_CHOICE ("Check for mails only","R) メール受信のみ"));
|
MDR_DIALECT_CHOICE ("Check for mails only","R) メール受信のみ"));
|
||||||
BFont font;
|
BFont font;
|
||||||
menu->GetFont(&font);
|
menu->GetFont(&font);
|
||||||
chainMenu->SetFont(&font);
|
accountMenu->SetFont(&font);
|
||||||
|
|
||||||
for (int32 i = 0; i < list.CountItems(); i++) {
|
for (int32 i = 0; i < accounts.CountAccounts(); i++) {
|
||||||
BMailChain* chain = (BMailChain*)list.ItemAt(i);
|
BMailAccountSettings* account = accounts.AccountAt(i);
|
||||||
|
|
||||||
BMessage* message = new BMessage(MD_CHECK_FOR_MAILS);
|
BMessage* message = new BMessage(MD_CHECK_FOR_MAILS);
|
||||||
message->AddString("account", chain->Name());
|
message->AddInt32("account", account->AccountID());
|
||||||
|
|
||||||
chainMenu->AddItem(new BMenuItem(chain->Name(), message));
|
accountMenu->AddItem(new BMenuItem(account->Name(), message));
|
||||||
delete chain;
|
|
||||||
}
|
}
|
||||||
if (list.IsEmpty()) {
|
if (accounts.CountAccounts() == 0) {
|
||||||
item = new BMenuItem("<no accounts>", NULL);
|
item = new BMenuItem("<no accounts>", NULL);
|
||||||
item->SetEnabled(false);
|
item->SetEnabled(false);
|
||||||
chainMenu->AddItem(item);
|
accountMenu->AddItem(item);
|
||||||
}
|
}
|
||||||
chainMenu->SetTargetForItems(this);
|
accountMenu->SetTargetForItems(this);
|
||||||
menu->AddItem(new BMenuItem(chainMenu, new BMessage(MD_CHECK_FOR_MAILS)));
|
menu->AddItem(new BMenuItem(accountMenu,
|
||||||
|
new BMessage(MD_CHECK_FOR_MAILS)));
|
||||||
|
|
||||||
// Not used:
|
// Not used:
|
||||||
// menu->AddItem(new BMenuItem(MDR_DIALECT_CHOICE (
|
// menu->AddItem(new BMenuItem(MDR_DIALECT_CHOICE (
|
||||||
@@ -593,7 +591,7 @@ DeskbarView::_BuildMenu()
|
|||||||
menu->AddItem(item = new BMenuItem(
|
menu->AddItem(item = new BMenuItem(
|
||||||
MDR_DIALECT_CHOICE ("Check for mail now", "C) メールチェック"),
|
MDR_DIALECT_CHOICE ("Check for mail now", "C) メールチェック"),
|
||||||
new BMessage(MD_CHECK_SEND_NOW)));
|
new BMessage(MD_CHECK_SEND_NOW)));
|
||||||
if (list.IsEmpty())
|
if (accounts.CountAccounts() == 0)
|
||||||
item->SetEnabled(false);
|
item->SetEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -53,14 +53,18 @@ class ErrorPanel : public BView {
|
|||||||
|
|
||||||
|
|
||||||
ErrorLogWindow::ErrorLogWindow(BRect rect, const char *name, window_type type)
|
ErrorLogWindow::ErrorLogWindow(BRect rect, const char *name, window_type type)
|
||||||
: BWindow(rect, name, type,
|
:
|
||||||
B_NO_WORKSPACE_ACTIVATION | B_NOT_MINIMIZABLE | B_ASYNCHRONOUS_CONTROLS)
|
BWindow(rect, name, type, B_NO_WORKSPACE_ACTIVATION | B_NOT_MINIMIZABLE
|
||||||
|
| B_ASYNCHRONOUS_CONTROLS),
|
||||||
|
fIsRunning(false)
|
||||||
{
|
{
|
||||||
rect = Bounds();
|
rect = Bounds();
|
||||||
rect.right -= B_V_SCROLL_BAR_WIDTH;
|
rect.right -= B_V_SCROLL_BAR_WIDTH;
|
||||||
|
|
||||||
view = new ErrorPanel(rect);
|
view = new ErrorPanel(rect);
|
||||||
AddChild(new BScrollView("ErrorScroller", view, B_FOLLOW_ALL_SIDES, 0, false, true));
|
AddChild(new BScrollView("ErrorScroller", view, B_FOLLOW_ALL_SIDES, 0, false, true));
|
||||||
|
Show();
|
||||||
|
Hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -69,6 +73,12 @@ ErrorLogWindow::AddError(alert_type type, const char *message, const char *tag,
|
|||||||
{
|
{
|
||||||
ErrorPanel *panel = (ErrorPanel *)view;
|
ErrorPanel *panel = (ErrorPanel *)view;
|
||||||
|
|
||||||
|
// first call?
|
||||||
|
if (!fIsRunning) {
|
||||||
|
fIsRunning = true;
|
||||||
|
Show();
|
||||||
|
}
|
||||||
|
|
||||||
Lock();
|
Lock();
|
||||||
|
|
||||||
Error *newError = new Error(BRect(0, panel->add_next_at, panel->Bounds().right,
|
Error *newError = new Error(BRect(0, panel->add_next_at, panel->Bounds().right,
|
||||||
@@ -101,8 +111,11 @@ ErrorLogWindow::QuitRequested()
|
|||||||
{
|
{
|
||||||
Hide();
|
Hide();
|
||||||
|
|
||||||
while (view->CountChildren() != 0)
|
while (view->CountChildren() != 0) {
|
||||||
view->RemoveChild(view->ChildAt(0));
|
BView* child = view->ChildAt(0);
|
||||||
|
view->RemoveChild(child);
|
||||||
|
delete child;
|
||||||
|
}
|
||||||
|
|
||||||
ErrorPanel *panel = (ErrorPanel *)(view);
|
ErrorPanel *panel = (ErrorPanel *)(view);
|
||||||
panel->add_next_at = 0;
|
panel->add_next_at = 0;
|
||||||
@@ -135,7 +148,13 @@ ErrorLogWindow::FrameResized(float newWidth, float newHeight)
|
|||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
Error::Error(BRect rect,alert_type atype,const char *tag,const char *message,bool timestamp,rgb_color bkg) : BView(rect,"error",B_FOLLOW_LEFT | B_FOLLOW_RIGHT | B_FOLLOW_TOP,B_NAVIGABLE | B_WILL_DRAW | B_FRAME_EVENTS), type(atype) {
|
Error::Error(BRect rect, alert_type atype, const char *tag, const char *message,
|
||||||
|
bool timestamp,rgb_color bkg)
|
||||||
|
:
|
||||||
|
BView(rect,"error",B_FOLLOW_LEFT | B_FOLLOW_RIGHT
|
||||||
|
| B_FOLLOW_TOP,B_NAVIGABLE | B_WILL_DRAW | B_FRAME_EVENTS),
|
||||||
|
type(atype)
|
||||||
|
{
|
||||||
SetViewColor(bkg);
|
SetViewColor(bkg);
|
||||||
SetLowColor(bkg);
|
SetLowColor(bkg);
|
||||||
|
|
||||||
@@ -148,16 +167,21 @@ Error::Error(BRect rect,alert_type atype,const char *tag,const char *message,boo
|
|||||||
BString msgString(message);
|
BString msgString(message);
|
||||||
msgString.RemoveAll("\r");
|
msgString.RemoveAll("\r");
|
||||||
|
|
||||||
BTextView *view = new BTextView(BRect(20,0,rect.Width(),rect.Height()),"error_display",BRect(0,3,rect.Width() - 20 - 3,LONG_MAX),B_FOLLOW_ALL_SIDES);
|
BTextView *view = new BTextView(BRect(20, 0, rect.Width(), rect.Height()),
|
||||||
|
"error_display", BRect(0,3,rect.Width() - 20 - 3, LONG_MAX),
|
||||||
|
B_FOLLOW_ALL_SIDES);
|
||||||
view->SetLowColor(bkg);
|
view->SetLowColor(bkg);
|
||||||
view->SetViewColor(bkg);
|
view->SetViewColor(bkg);
|
||||||
view->SetText(msgString.String());
|
view->SetText(msgString.String());
|
||||||
view->MakeSelectable(true);
|
view->MakeSelectable(true);
|
||||||
view->SetStylable(true);
|
view->SetStylable(true);
|
||||||
view->MakeEditable(false);
|
view->MakeEditable(false);
|
||||||
|
|
||||||
if (tag != NULL)
|
if (tag != NULL) {
|
||||||
view->Insert(0,tag,strlen(tag),&array);
|
BString tagString(tag);
|
||||||
|
tagString += " ";
|
||||||
|
view->Insert(0, tagString.String(), tagString.Length(), &array);
|
||||||
|
}
|
||||||
|
|
||||||
if (timestamp) {
|
if (timestamp) {
|
||||||
array.runs[0].color = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR),B_DARKEN_2_TINT);
|
array.runs[0].color = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR),B_DARKEN_2_TINT);
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
#include <Alert.h>
|
#include <Alert.h>
|
||||||
|
|
||||||
class ErrorLogWindow : public BWindow {
|
class ErrorLogWindow : public BWindow {
|
||||||
public:
|
public:
|
||||||
ErrorLogWindow(BRect rect, const char *name, window_type type);
|
ErrorLogWindow(BRect rect, const char *name, window_type type);
|
||||||
|
|
||||||
void AddError(alert_type type,const char *message,const char *tag = NULL,bool timestamp = true);
|
void AddError(alert_type type,const char *message,const char *tag = NULL,bool timestamp = true);
|
||||||
@@ -13,8 +13,9 @@ class ErrorLogWindow : public BWindow {
|
|||||||
bool QuitRequested();
|
bool QuitRequested();
|
||||||
void FrameResized(float new_width, float new_height);
|
void FrameResized(float new_width, float new_height);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BView *view;
|
BView *view;
|
||||||
|
bool fIsRunning;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // ZOIDBERG_MAIL_ERRORLOGWINDOW_H
|
#endif // ZOIDBERG_MAIL_ERRORLOGWINDOW_H
|
||||||
@@ -17,8 +17,12 @@ AddResources mail_daemon : mail_daemon.rdef DeskbarViewIcons.rdef ;
|
|||||||
|
|
||||||
Server mail_daemon :
|
Server mail_daemon :
|
||||||
DeskbarView.cpp
|
DeskbarView.cpp
|
||||||
|
ErrorLogWindow.cpp
|
||||||
LEDAnimation.cpp
|
LEDAnimation.cpp
|
||||||
|
MailDaemon.cpp
|
||||||
main.cpp
|
main.cpp
|
||||||
|
Notifier.cpp
|
||||||
|
StatusWindow.cpp
|
||||||
;
|
;
|
||||||
|
|
||||||
LinkAgainst mail_daemon : be libmail.so tracker $(TARGET_LIBSTDC++) $(TARGET_NETWORK_LIBS) ;
|
LinkAgainst mail_daemon : be libmail.so tracker $(TARGET_LIBSTDC++) $(TARGET_NETWORK_LIBS) ;
|
||||||
|
|||||||
@@ -0,0 +1,860 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2007-2011, 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 "MailDaemon.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <Beep.h>
|
||||||
|
#include <Deskbar.h>
|
||||||
|
#include <Directory.h>
|
||||||
|
#include <Entry.h>
|
||||||
|
#include <FindDirectory.h>
|
||||||
|
#include <fs_index.h>
|
||||||
|
#include <NodeMonitor.h>
|
||||||
|
#include <Path.h>
|
||||||
|
#include <Roster.h>
|
||||||
|
#include <StringList.h>
|
||||||
|
#include <VolumeRoster.h>
|
||||||
|
|
||||||
|
#include <E-mail.h>
|
||||||
|
#include <MailDaemon.h>
|
||||||
|
#include <MailMessage.h>
|
||||||
|
#include <MailSettings.h>
|
||||||
|
#include <MDRLanguage.h>
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
makeIndices()
|
||||||
|
{
|
||||||
|
const char* stringIndices[] = {
|
||||||
|
B_MAIL_ATTR_CC, B_MAIL_ATTR_FROM, B_MAIL_ATTR_NAME,
|
||||||
|
B_MAIL_ATTR_PRIORITY, B_MAIL_ATTR_REPLY, B_MAIL_ATTR_STATUS,
|
||||||
|
B_MAIL_ATTR_SUBJECT, B_MAIL_ATTR_TO, B_MAIL_ATTR_THREAD,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
// add mail indices for all devices capable of querying
|
||||||
|
|
||||||
|
int32 cookie = 0;
|
||||||
|
dev_t device;
|
||||||
|
while ((device = next_dev(&cookie)) >= B_OK) {
|
||||||
|
fs_info info;
|
||||||
|
if (fs_stat_dev(device, &info) < 0
|
||||||
|
|| (info.flags & B_FS_HAS_QUERY) == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (int32 i = 0; stringIndices[i]; i++)
|
||||||
|
fs_create_index(device, stringIndices[i], B_STRING_TYPE, 0);
|
||||||
|
|
||||||
|
fs_create_index(device, "MAIL:draft", B_INT32_TYPE, 0);
|
||||||
|
fs_create_index(device, B_MAIL_ATTR_WHEN, B_INT32_TYPE, 0);
|
||||||
|
fs_create_index(device, B_MAIL_ATTR_FLAGS, B_INT32_TYPE, 0);
|
||||||
|
fs_create_index(device, B_MAIL_ATTR_ACCOUNT, B_INT32_TYPE, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
addAttribute(BMessage& msg, const char* name, const char* publicName,
|
||||||
|
int32 type = B_STRING_TYPE, bool viewable = true, bool editable = false,
|
||||||
|
int32 width = 200)
|
||||||
|
{
|
||||||
|
msg.AddString("attr:name", name);
|
||||||
|
msg.AddString("attr:public_name", publicName);
|
||||||
|
msg.AddInt32("attr:type", type);
|
||||||
|
msg.AddBool("attr:viewable", viewable);
|
||||||
|
msg.AddBool("attr:editable", editable);
|
||||||
|
msg.AddInt32("attr:width", width);
|
||||||
|
msg.AddInt32("attr:alignment", B_ALIGN_LEFT);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
using std::map;
|
||||||
|
using std::vector;
|
||||||
|
|
||||||
|
|
||||||
|
MailDaemonApp::MailDaemonApp()
|
||||||
|
:
|
||||||
|
BApplication("application/x-vnd.Be-POST"),
|
||||||
|
|
||||||
|
fAutoCheckRunner(NULL)
|
||||||
|
{
|
||||||
|
fErrorLogWindow = new ErrorLogWindow(BRect(200, 200, 500, 250),
|
||||||
|
"Mail daemon status log", B_TITLED_WINDOW);
|
||||||
|
fMailStatusWindow = new MailStatusWindow(BRect(40, 400, 360, 400),
|
||||||
|
"Mail Status", fSettingsFile.ShowStatusWindow());
|
||||||
|
// install MimeTypes, attributes, indices, and the
|
||||||
|
// system beep add startup
|
||||||
|
MakeMimeTypes();
|
||||||
|
makeIndices();
|
||||||
|
add_system_beep_event("New E-mail");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
MailDaemonApp::~MailDaemonApp()
|
||||||
|
{
|
||||||
|
delete fAutoCheckRunner;
|
||||||
|
|
||||||
|
for (int32 i = 0; i < fQueries.CountItems(); i++)
|
||||||
|
delete fQueries.ItemAt(i);
|
||||||
|
|
||||||
|
delete fLEDAnimation;
|
||||||
|
|
||||||
|
AccountMap::const_iterator it = fAccounts.begin();
|
||||||
|
for (; it != fAccounts.end(); it++)
|
||||||
|
_RemoveAccount(it);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
MailDaemonApp::ReadyToRun()
|
||||||
|
{
|
||||||
|
InstallDeskbarIcon();
|
||||||
|
|
||||||
|
_InitAccounts();
|
||||||
|
_UpdateAutoCheck(fSettingsFile.AutoCheckInterval());
|
||||||
|
|
||||||
|
BVolume volume;
|
||||||
|
BVolumeRoster roster;
|
||||||
|
|
||||||
|
fNewMessages = 0;
|
||||||
|
|
||||||
|
while (roster.GetNextVolume(&volume) == B_OK) {
|
||||||
|
//{char name[255];volume.GetName(name);printf("Volume: %s\n",name);}
|
||||||
|
|
||||||
|
BQuery* query = new BQuery;
|
||||||
|
|
||||||
|
query->SetTarget(this);
|
||||||
|
query->SetVolume(&volume);
|
||||||
|
query->PushAttr(B_MAIL_ATTR_STATUS);
|
||||||
|
query->PushString("New");
|
||||||
|
query->PushOp(B_EQ);
|
||||||
|
query->PushAttr("BEOS:TYPE");
|
||||||
|
query->PushString("text/x-email");
|
||||||
|
query->PushOp(B_EQ);
|
||||||
|
query->PushAttr("BEOS:TYPE");
|
||||||
|
query->PushString("text/x-partial-email");
|
||||||
|
query->PushOp(B_EQ);
|
||||||
|
query->PushOp(B_OR);
|
||||||
|
query->PushOp(B_AND);
|
||||||
|
query->Fetch();
|
||||||
|
|
||||||
|
BEntry entry;
|
||||||
|
while (query->GetNextEntry(&entry) == B_OK)
|
||||||
|
fNewMessages++;
|
||||||
|
|
||||||
|
fQueries.AddItem(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
BString string;
|
||||||
|
MDR_DIALECT_CHOICE(
|
||||||
|
if (fNewMessages > 0)
|
||||||
|
string << fNewMessages;
|
||||||
|
else
|
||||||
|
string << "No";
|
||||||
|
if (fNewMessages != 1)
|
||||||
|
string << " new messages.";
|
||||||
|
else
|
||||||
|
string << " new message.";,
|
||||||
|
if (fNewMessages > 0)
|
||||||
|
string << fNewMessages << " 通の未読メッセージがあります ";
|
||||||
|
else
|
||||||
|
string << "未読メッセージはありません";
|
||||||
|
);
|
||||||
|
fCentralBeep = false;
|
||||||
|
fMailStatusWindow->SetDefaultMessage(string);
|
||||||
|
|
||||||
|
fLEDAnimation = new LEDAnimation;
|
||||||
|
SetPulseRate(1000000);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
MailDaemonApp::RefsReceived(BMessage* message)
|
||||||
|
{
|
||||||
|
fMailStatusWindow->Activate(true);
|
||||||
|
|
||||||
|
entry_ref ref;
|
||||||
|
for (int32 i = 0; message->FindRef("refs", i, &ref) == B_OK; i++) {
|
||||||
|
BNode node(&ref);
|
||||||
|
if (node.InitCheck() < B_OK)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int32 account;
|
||||||
|
if (node.ReadAttr("MAIL:account", B_INT32_TYPE, 0, &account,
|
||||||
|
sizeof(account)) < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
InboundProtocolThread* protocol = _FindInboundProtocol(account);
|
||||||
|
if (!protocol)
|
||||||
|
continue;
|
||||||
|
bool launch = true;
|
||||||
|
protocol->FetchBody(ref, launch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
MailDaemonApp::_InitAccounts()
|
||||||
|
{
|
||||||
|
BMailAccounts accounts;
|
||||||
|
for (int i = 0; i < accounts.CountAccounts(); i++)
|
||||||
|
_InitAccount(*accounts.AccountAt(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
MailDaemonApp::_InitAccount(BMailAccountSettings& settings)
|
||||||
|
{
|
||||||
|
account_protocols account;
|
||||||
|
account.inboundProtocol = _CreateInboundProtocol(settings,
|
||||||
|
account.inboundImage);
|
||||||
|
if (account.inboundProtocol) {
|
||||||
|
DefaultNotifier* notifier = new DefaultNotifier(settings.Name(), true,
|
||||||
|
fErrorLogWindow, fMailStatusWindow);
|
||||||
|
account.inboundProtocol->SetMailNotifier(notifier);
|
||||||
|
|
||||||
|
account.inboundThread = new InboundProtocolThread(
|
||||||
|
account.inboundProtocol);
|
||||||
|
account.inboundThread->Run();
|
||||||
|
}
|
||||||
|
|
||||||
|
account.outboundProtocol = _CreateOutboundProtocol(settings,
|
||||||
|
account.outboundImage);
|
||||||
|
if (account.outboundProtocol) {
|
||||||
|
DefaultNotifier* notifier = new DefaultNotifier(settings.Name(), false,
|
||||||
|
fErrorLogWindow, fMailStatusWindow);
|
||||||
|
account.outboundProtocol->SetMailNotifier(notifier);
|
||||||
|
|
||||||
|
account.outboundThread = new OutboundProtocolThread(
|
||||||
|
account.outboundProtocol);
|
||||||
|
account.outboundThread->Run();
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("account name %s, id %i, in %p, out %p\n", settings.Name(),
|
||||||
|
(int)settings.AccountID(), account.inboundProtocol,
|
||||||
|
account.outboundProtocol);
|
||||||
|
if (!account.inboundProtocol && !account.outboundProtocol)
|
||||||
|
return;
|
||||||
|
fAccounts[settings.AccountID()] = account;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
MailDaemonApp::_ReloadAccounts(BMessage* message)
|
||||||
|
{
|
||||||
|
type_code typeFound;
|
||||||
|
int32 countFound;
|
||||||
|
message->GetInfo("account", &typeFound, &countFound);
|
||||||
|
if (typeFound != B_INT32_TYPE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// reload accounts
|
||||||
|
BMailAccounts accounts;
|
||||||
|
|
||||||
|
for (int i = 0; i < countFound; i++) {
|
||||||
|
int32 account = message->FindInt32("account", i);
|
||||||
|
AccountMap::const_iterator it = fAccounts.find(account);
|
||||||
|
if (it != fAccounts.end())
|
||||||
|
_RemoveAccount(it);
|
||||||
|
BMailAccountSettings* settings = accounts.AccountByID(account);
|
||||||
|
if (settings)
|
||||||
|
_InitAccount(*settings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
MailDaemonApp::_RemoveAccount(AccountMap::const_iterator it)
|
||||||
|
{
|
||||||
|
BMessage reply;
|
||||||
|
if (it->second.inboundThread) {
|
||||||
|
it->second.inboundThread->SetStopNow();
|
||||||
|
BMessenger(it->second.inboundThread).SendMessage(B_QUIT_REQUESTED,
|
||||||
|
&reply);
|
||||||
|
}
|
||||||
|
if (it->second.outboundThread) {
|
||||||
|
it->second.outboundThread->SetStopNow();
|
||||||
|
BMessenger(it->second.outboundThread).SendMessage(B_QUIT_REQUESTED,
|
||||||
|
&reply);
|
||||||
|
}
|
||||||
|
delete it->second.inboundProtocol;
|
||||||
|
delete it->second.outboundProtocol;
|
||||||
|
unload_add_on(it->second.inboundImage);
|
||||||
|
unload_add_on(it->second.outboundImage);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
InboundProtocol*
|
||||||
|
MailDaemonApp::_CreateInboundProtocol(BMailAccountSettings& settings,
|
||||||
|
image_id& image)
|
||||||
|
{
|
||||||
|
const entry_ref& entry = settings.InboundPath();
|
||||||
|
|
||||||
|
InboundProtocol* (*instantiate_protocol)(BMailAccountSettings*);
|
||||||
|
|
||||||
|
BPath path(&entry);
|
||||||
|
image = load_add_on(path.Path());
|
||||||
|
if (image < 0)
|
||||||
|
return NULL;
|
||||||
|
if (get_image_symbol(image, "instantiate_inbound_protocol",
|
||||||
|
B_SYMBOL_TYPE_TEXT, (void **)&instantiate_protocol) != B_OK) {
|
||||||
|
unload_add_on(image);
|
||||||
|
image = -1;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
InboundProtocol* protocol = (*instantiate_protocol)(&settings);
|
||||||
|
return protocol;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
OutboundProtocol*
|
||||||
|
MailDaemonApp::_CreateOutboundProtocol(BMailAccountSettings& settings,
|
||||||
|
image_id& image)
|
||||||
|
{
|
||||||
|
const entry_ref& entry = settings.OutboundPath();
|
||||||
|
|
||||||
|
OutboundProtocol* (*instantiate_protocol)(BMailAccountSettings*);
|
||||||
|
|
||||||
|
BPath path(&entry);
|
||||||
|
image = load_add_on(path.Path());
|
||||||
|
if (image < 0)
|
||||||
|
return NULL;
|
||||||
|
if (get_image_symbol(image, "instantiate_outbound_protocol",
|
||||||
|
B_SYMBOL_TYPE_TEXT, (void **)&instantiate_protocol) != B_OK) {
|
||||||
|
unload_add_on(image);
|
||||||
|
image = -1;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
OutboundProtocol* protocol = (*instantiate_protocol)(&settings);
|
||||||
|
return protocol;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
InboundProtocolThread*
|
||||||
|
MailDaemonApp::_FindInboundProtocol(int32 account)
|
||||||
|
{
|
||||||
|
AccountMap::iterator it = fAccounts.find(account);
|
||||||
|
if (it == fAccounts.end())
|
||||||
|
return NULL;
|
||||||
|
return it->second.inboundThread;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
OutboundProtocolThread*
|
||||||
|
MailDaemonApp::_FindOutboundProtocol(int32 account)
|
||||||
|
{
|
||||||
|
if (account < 0)
|
||||||
|
account = BMailSettings().DefaultOutboundAccount();
|
||||||
|
|
||||||
|
AccountMap::iterator it = fAccounts.find(account);
|
||||||
|
if (it == fAccounts.end())
|
||||||
|
return NULL;
|
||||||
|
return it->second.outboundThread;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
MailDaemonApp::_UpdateAutoCheck(bigtime_t interval)
|
||||||
|
{
|
||||||
|
if (interval > 0) {
|
||||||
|
if (fAutoCheckRunner != NULL) {
|
||||||
|
fAutoCheckRunner->SetInterval(interval);
|
||||||
|
fAutoCheckRunner->SetCount(-1);
|
||||||
|
} else
|
||||||
|
fAutoCheckRunner = new BMessageRunner(be_app_messenger,
|
||||||
|
new BMessage('moto'), interval);
|
||||||
|
} else {
|
||||||
|
delete fAutoCheckRunner;
|
||||||
|
fAutoCheckRunner = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
MailDaemonApp::MessageReceived(BMessage* msg)
|
||||||
|
{
|
||||||
|
switch (msg->what) {
|
||||||
|
case 'moto':
|
||||||
|
if (fSettingsFile.CheckOnlyIfPPPUp()) {
|
||||||
|
// TODO: check whether internet is up and running!
|
||||||
|
}
|
||||||
|
// supposed to fall through
|
||||||
|
case kMsgCheckAndSend: // check & send messages
|
||||||
|
msg->what = kMsgSendMessages;
|
||||||
|
PostMessage(msg);
|
||||||
|
// supposed to fall trough
|
||||||
|
case kMsgCheckMessage: // check messages
|
||||||
|
GetNewMessages(msg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kMsgSendMessages: // send messages
|
||||||
|
SendPendingMessages(msg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kMsgSettingsUpdated:
|
||||||
|
fSettingsFile.Reload();
|
||||||
|
_UpdateAutoCheck(fSettingsFile.AutoCheckInterval());
|
||||||
|
fMailStatusWindow->SetShowCriterion(fSettingsFile.ShowStatusWindow());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kMsgAccountsChanged:
|
||||||
|
_ReloadAccounts(msg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kMsgSetStatusWindowMode: // when to show the status window
|
||||||
|
{
|
||||||
|
int32 mode;
|
||||||
|
if (msg->FindInt32("ShowStatusWindow", &mode) == B_OK)
|
||||||
|
fMailStatusWindow->SetShowCriterion(mode);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case kMsgMarkMessageAsRead:
|
||||||
|
{
|
||||||
|
int32 account = msg->FindInt32("account");
|
||||||
|
entry_ref ref;
|
||||||
|
if (msg->FindRef("ref", &ref) != B_OK)
|
||||||
|
break;
|
||||||
|
bool read = msg->FindBool("read");
|
||||||
|
AccountMap::iterator it = fAccounts.find(account);
|
||||||
|
if (it == fAccounts.end())
|
||||||
|
break;
|
||||||
|
InboundProtocol* inboundProtocol = it->second.inboundProtocol;
|
||||||
|
inboundProtocol->MarkMessageAsRead(ref, read);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'lkch': // status window look changed
|
||||||
|
case 'wsch': // workspace changed
|
||||||
|
fMailStatusWindow->PostMessage(msg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'stwg': // Status window gone
|
||||||
|
{
|
||||||
|
BMessage reply('mnuc');
|
||||||
|
reply.AddInt32("num_new_messages", fNewMessages);
|
||||||
|
|
||||||
|
while ((msg = fFetchDoneRespondents.RemoveItemAt(0))) {
|
||||||
|
msg->SendReply(&reply);
|
||||||
|
delete msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fAlertString != B_EMPTY_STRING) {
|
||||||
|
fAlertString.Truncate(fAlertString.Length() - 1);
|
||||||
|
BAlert* alert = new BAlert(MDR_DIALECT_CHOICE("New Messages",
|
||||||
|
"新着メッセージ"), fAlertString.String(), "OK", NULL, NULL,
|
||||||
|
B_WIDTH_AS_USUAL);
|
||||||
|
alert->SetFeel(B_NORMAL_WINDOW_FEEL);
|
||||||
|
alert->Go(NULL);
|
||||||
|
fAlertString = B_EMPTY_STRING;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fCentralBeep) {
|
||||||
|
system_beep("New E-mail");
|
||||||
|
fCentralBeep = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'mcbp':
|
||||||
|
if (fNewMessages > 0)
|
||||||
|
fCentralBeep = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kMsgCountNewMessages: // Number of new messages
|
||||||
|
{
|
||||||
|
BMessage reply('mnuc'); // Mail New message Count
|
||||||
|
if (msg->FindBool("wait_for_fetch_done")) {
|
||||||
|
fFetchDoneRespondents.AddItem(DetachCurrentMessage());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
reply.AddInt32("num_new_messages", fNewMessages);
|
||||||
|
msg->SendReply(&reply);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'mblk': // Mail Blink
|
||||||
|
if (fNewMessages > 0)
|
||||||
|
fLEDAnimation->Start();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'enda': // End Auto Check
|
||||||
|
delete fAutoCheckRunner;
|
||||||
|
fAutoCheckRunner = NULL;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'numg':
|
||||||
|
{
|
||||||
|
int32 numMessages = msg->FindInt32("num_messages");
|
||||||
|
MDR_DIALECT_CHOICE(
|
||||||
|
fAlertString << numMessages << " new message";
|
||||||
|
if (numMessages > 1)
|
||||||
|
fAlertString << 's';
|
||||||
|
|
||||||
|
fAlertString << " for " << msg->FindString("name")
|
||||||
|
<< '\n';,
|
||||||
|
|
||||||
|
fAlertString << msg->FindString("name") << "より\n"
|
||||||
|
<< numMessages << " 通のメッセージが届きました ";
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case B_QUERY_UPDATE:
|
||||||
|
{
|
||||||
|
int32 what;
|
||||||
|
msg->FindInt32("opcode", &what);
|
||||||
|
switch (what) {
|
||||||
|
case B_ENTRY_CREATED:
|
||||||
|
fNewMessages++;
|
||||||
|
break;
|
||||||
|
case B_ENTRY_REMOVED:
|
||||||
|
fNewMessages--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
BString string;
|
||||||
|
|
||||||
|
MDR_DIALECT_CHOICE(
|
||||||
|
if (fNewMessages > 0)
|
||||||
|
string << fNewMessages;
|
||||||
|
else
|
||||||
|
string << "No";
|
||||||
|
if (fNewMessages != 1)
|
||||||
|
string << " new messages.";
|
||||||
|
else
|
||||||
|
string << " new message.";,
|
||||||
|
|
||||||
|
if (fNewMessages > 0)
|
||||||
|
string << fNewMessages << " 通の未読メッセージがあります";
|
||||||
|
else
|
||||||
|
string << "未読メッセージはありません";
|
||||||
|
);
|
||||||
|
|
||||||
|
fMailStatusWindow->SetDefaultMessage(string.String());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
BApplication::MessageReceived(msg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
MailDaemonApp::InstallDeskbarIcon()
|
||||||
|
{
|
||||||
|
BDeskbar deskbar;
|
||||||
|
|
||||||
|
if (!deskbar.HasItem("mail_daemon")) {
|
||||||
|
BRoster roster;
|
||||||
|
entry_ref ref;
|
||||||
|
|
||||||
|
status_t status = roster.FindApp("application/x-vnd.Be-POST", &ref);
|
||||||
|
if (status < B_OK) {
|
||||||
|
fprintf(stderr, "Can't find application to tell deskbar: %s\n",
|
||||||
|
strerror(status));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = deskbar.AddItem(&ref);
|
||||||
|
if (status < B_OK) {
|
||||||
|
fprintf(stderr, "Can't add deskbar replicant: %s\n", strerror(status));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
MailDaemonApp::RemoveDeskbarIcon()
|
||||||
|
{
|
||||||
|
BDeskbar deskbar;
|
||||||
|
if (deskbar.HasItem("mail_daemon"))
|
||||||
|
deskbar.RemoveItem("mail_daemon");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
MailDaemonApp::QuitRequested()
|
||||||
|
{
|
||||||
|
RemoveDeskbarIcon();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
MailDaemonApp::GetNewMessages(BMessage* msg)
|
||||||
|
{
|
||||||
|
int32 account = -1;
|
||||||
|
if (msg->FindInt32("account", &account) == B_OK && account >= 0) {
|
||||||
|
InboundProtocolThread* protocol = _FindInboundProtocol(account);
|
||||||
|
if (!protocol)
|
||||||
|
return;
|
||||||
|
protocol->SyncMessages();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// else check all accounts
|
||||||
|
AccountMap::const_iterator it = fAccounts.begin();
|
||||||
|
for (; it != fAccounts.end(); it++) {
|
||||||
|
InboundProtocolThread* protocol = it->second.inboundThread;
|
||||||
|
if (!protocol)
|
||||||
|
continue;
|
||||||
|
protocol->SyncMessages();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
MailDaemonApp::MakeMimeTypes(bool remakeMIMETypes)
|
||||||
|
{
|
||||||
|
// Add MIME database entries for the e-mail file types we handle. Either
|
||||||
|
// do a full rebuild from nothing, or just add on the new attributes that
|
||||||
|
// we support which the regular BeOS mail daemon didn't have.
|
||||||
|
|
||||||
|
const char* types[2] = {"text/x-email", "text/x-partial-email"};
|
||||||
|
BMimeType mime;
|
||||||
|
BMessage info;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < sizeof(types) / sizeof(types[0]); i++) {
|
||||||
|
info.MakeEmpty();
|
||||||
|
mime.SetTo(types[i]);
|
||||||
|
if (mime.InitCheck() != B_OK) {
|
||||||
|
fputs("could not init mime type.\n", stderr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mime.IsInstalled() || remakeMIMETypes) {
|
||||||
|
// install the full mime type
|
||||||
|
mime.Delete ();
|
||||||
|
mime.Install();
|
||||||
|
|
||||||
|
// Set up the list of e-mail related attributes that Tracker will
|
||||||
|
// let you display in columns for e-mail messages.
|
||||||
|
addAttribute(info, B_MAIL_ATTR_NAME, "Name");
|
||||||
|
addAttribute(info, B_MAIL_ATTR_SUBJECT, "Subject");
|
||||||
|
addAttribute(info, B_MAIL_ATTR_TO, "To");
|
||||||
|
addAttribute(info, B_MAIL_ATTR_CC, "Cc");
|
||||||
|
addAttribute(info, B_MAIL_ATTR_FROM, "From");
|
||||||
|
addAttribute(info, B_MAIL_ATTR_REPLY, "Reply To");
|
||||||
|
addAttribute(info, B_MAIL_ATTR_STATUS, "Status");
|
||||||
|
addAttribute(info, B_MAIL_ATTR_PRIORITY, "Priority", B_STRING_TYPE,
|
||||||
|
true, true, 40);
|
||||||
|
addAttribute(info, B_MAIL_ATTR_WHEN, "When", B_TIME_TYPE, true,
|
||||||
|
false, 150);
|
||||||
|
addAttribute(info, B_MAIL_ATTR_THREAD, "Thread");
|
||||||
|
addAttribute(info, B_MAIL_ATTR_ACCOUNT, "Account", B_STRING_TYPE,
|
||||||
|
true, false, 100);
|
||||||
|
mime.SetAttrInfo(&info);
|
||||||
|
|
||||||
|
if (i == 0) {
|
||||||
|
mime.SetShortDescription("E-mail");
|
||||||
|
mime.SetLongDescription("Electronic Mail Message");
|
||||||
|
mime.SetPreferredApp("application/x-vnd.Be-MAIL");
|
||||||
|
} else {
|
||||||
|
mime.SetShortDescription("Partial E-mail");
|
||||||
|
mime.SetLongDescription("A Partially Downloaded E-mail");
|
||||||
|
mime.SetPreferredApp("application/x-vnd.Be-POST");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Just add the e-mail related attribute types we use to the MIME
|
||||||
|
// system.
|
||||||
|
mime.GetAttrInfo(&info);
|
||||||
|
bool hasAccount = false;
|
||||||
|
bool hasThread = false;
|
||||||
|
bool hasSize = false;
|
||||||
|
const char* result;
|
||||||
|
for (int32 index = 0; info.FindString("attr:name", index, &result)
|
||||||
|
== B_OK; index++) {
|
||||||
|
if (!strcmp(result, B_MAIL_ATTR_ACCOUNT))
|
||||||
|
hasAccount = true;
|
||||||
|
if (!strcmp(result, B_MAIL_ATTR_THREAD))
|
||||||
|
hasThread = true;
|
||||||
|
if (!strcmp(result, "MAIL:fullsize"))
|
||||||
|
hasSize = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasAccount) {
|
||||||
|
addAttribute(info, B_MAIL_ATTR_ACCOUNT, "Account",
|
||||||
|
B_STRING_TYPE, true, false, 100);
|
||||||
|
}
|
||||||
|
if (!hasThread)
|
||||||
|
addAttribute(info, B_MAIL_ATTR_THREAD, "Thread");
|
||||||
|
/*if (!hasSize)
|
||||||
|
addAttribute(info,"MAIL:fullsize","Message Size",B_SIZE_T_TYPE,true,false,100);*/
|
||||||
|
// TODO: Tracker can't display SIZT attributes. What a pain.
|
||||||
|
if (!hasAccount || !hasThread/* || !hasSize*/)
|
||||||
|
mime.SetAttrInfo(&info);
|
||||||
|
}
|
||||||
|
mime.Unset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct send_mails_info {
|
||||||
|
send_mails_info()
|
||||||
|
{
|
||||||
|
totalSize = 0;
|
||||||
|
}
|
||||||
|
vector<entry_ref> files;
|
||||||
|
off_t totalSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
MailDaemonApp::SendPendingMessages(BMessage* msg)
|
||||||
|
{
|
||||||
|
BVolumeRoster roster;
|
||||||
|
BVolume volume;
|
||||||
|
|
||||||
|
map<int32, send_mails_info> messages;
|
||||||
|
|
||||||
|
|
||||||
|
int32 account = -1;
|
||||||
|
if (msg->FindInt32("account", &account) != B_OK)
|
||||||
|
account = -1;
|
||||||
|
|
||||||
|
if (!msg->HasString("message_path")) {
|
||||||
|
while (roster.GetNextVolume(&volume) == B_OK) {
|
||||||
|
BQuery query;
|
||||||
|
query.SetVolume(&volume);
|
||||||
|
query.PushAttr(B_MAIL_ATTR_FLAGS);
|
||||||
|
query.PushInt32(B_MAIL_PENDING);
|
||||||
|
query.PushOp(B_EQ);
|
||||||
|
|
||||||
|
query.PushAttr(B_MAIL_ATTR_FLAGS);
|
||||||
|
query.PushInt32(B_MAIL_PENDING | B_MAIL_SAVE);
|
||||||
|
query.PushOp(B_EQ);
|
||||||
|
|
||||||
|
if (account >= 0) {
|
||||||
|
query.PushAttr("MAIL:account");
|
||||||
|
query.PushInt32(account);
|
||||||
|
query.PushOp(B_EQ);
|
||||||
|
query.PushOp(B_AND);
|
||||||
|
}
|
||||||
|
|
||||||
|
query.PushOp(B_OR);
|
||||||
|
query.Fetch();
|
||||||
|
BEntry entry;
|
||||||
|
while (query.GetNextEntry(&entry) == B_OK) {
|
||||||
|
if (_IsEntryInTrash(entry))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
BNode node;
|
||||||
|
while (node.SetTo(&entry) == B_BUSY)
|
||||||
|
snooze(1000);
|
||||||
|
if (!_IsPending(node))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int32 messageAccount;
|
||||||
|
if (node.ReadAttr("MAIL:account", B_INT32_TYPE, 0,
|
||||||
|
&messageAccount, sizeof(int32)) < 0)
|
||||||
|
messageAccount = -1;
|
||||||
|
|
||||||
|
off_t size = 0;
|
||||||
|
node.GetSize(&size);
|
||||||
|
entry_ref ref;
|
||||||
|
entry.GetRef(&ref);
|
||||||
|
|
||||||
|
messages[messageAccount].files.push_back(ref);
|
||||||
|
messages[messageAccount].totalSize += size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const char* path;
|
||||||
|
if (msg->FindString("message_path", &path) != B_OK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
off_t size = 0;
|
||||||
|
if (BNode(path).GetSize(&size) != B_OK)
|
||||||
|
return;
|
||||||
|
BEntry entry(path);
|
||||||
|
entry_ref ref;
|
||||||
|
entry.GetRef(&ref);
|
||||||
|
|
||||||
|
messages[account].files.push_back(ref);
|
||||||
|
messages[account].totalSize += size;
|
||||||
|
}
|
||||||
|
|
||||||
|
map<int32, send_mails_info>::iterator iter = messages.begin();
|
||||||
|
for (; iter != messages.end(); iter++) {
|
||||||
|
OutboundProtocolThread* protocolThread = _FindOutboundProtocol(
|
||||||
|
iter->first);
|
||||||
|
if (!protocolThread)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
send_mails_info& info = iter->second;
|
||||||
|
if (info.files.size() == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
MailProtocol* protocol = protocolThread->Protocol();
|
||||||
|
|
||||||
|
protocolThread->Lock();
|
||||||
|
protocol->SetTotalItems(info.files.size());
|
||||||
|
protocol->SetTotalItemsSize(info.totalSize);
|
||||||
|
protocolThread->Unlock();
|
||||||
|
|
||||||
|
protocolThread->SendMessages(iter->second.files, info.totalSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
MailDaemonApp::Pulse()
|
||||||
|
{
|
||||||
|
bigtime_t idle = idle_time();
|
||||||
|
if (fLEDAnimation->IsRunning() && idle < 100000)
|
||||||
|
fLEDAnimation->Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! Work-around for a broken index that contains out-of-date information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
bool
|
||||||
|
MailDaemonApp::_IsPending(BNode& node)
|
||||||
|
{
|
||||||
|
int32 flags;
|
||||||
|
if (node.ReadAttr(B_MAIL_ATTR_FLAGS, B_INT32_TYPE, 0, &flags, sizeof(int32))
|
||||||
|
!= (ssize_t)sizeof(int32))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return (flags & B_MAIL_PENDING) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
bool
|
||||||
|
MailDaemonApp::_IsEntryInTrash(BEntry& entry)
|
||||||
|
{
|
||||||
|
entry_ref ref;
|
||||||
|
entry.GetRef(&ref);
|
||||||
|
|
||||||
|
BVolume volume(ref.device);
|
||||||
|
BPath path;
|
||||||
|
if (volume.InitCheck() != B_OK
|
||||||
|
|| find_directory(B_TRASH_DIRECTORY, &path, false, &volume) != B_OK)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
BDirectory trash(path.Path());
|
||||||
|
return trash.Contains(&entry);
|
||||||
|
}
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2007-2011, 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.
|
||||||
|
*/
|
||||||
|
#ifndef MAIL_DAEMON_APP_H
|
||||||
|
#define MAIL_DAEMON_APP_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include <Application.h>
|
||||||
|
#include <ObjectList.h>
|
||||||
|
#include <Message.h>
|
||||||
|
#include <MessageRunner.h>
|
||||||
|
#include <Node.h>
|
||||||
|
#include <Query.h>
|
||||||
|
#include <String.h>
|
||||||
|
|
||||||
|
#include <MailProtocol.h>
|
||||||
|
|
||||||
|
#include "LEDAnimation.h"
|
||||||
|
#include "Notifier.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct account_protocols {
|
||||||
|
account_protocols() {
|
||||||
|
inboundImage = -1;
|
||||||
|
inboundThread = NULL;
|
||||||
|
inboundProtocol = NULL;
|
||||||
|
outboundImage = -1;
|
||||||
|
outboundThread = NULL;
|
||||||
|
outboundProtocol = NULL;
|
||||||
|
}
|
||||||
|
image_id inboundImage;
|
||||||
|
InboundProtocolThread* inboundThread;
|
||||||
|
InboundProtocol* inboundProtocol;
|
||||||
|
image_id outboundImage;
|
||||||
|
OutboundProtocolThread* outboundThread;
|
||||||
|
OutboundProtocol* outboundProtocol;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef std::map<int32, account_protocols> AccountMap;
|
||||||
|
|
||||||
|
|
||||||
|
class MailDaemonApp : public BApplication {
|
||||||
|
public:
|
||||||
|
MailDaemonApp();
|
||||||
|
virtual ~MailDaemonApp();
|
||||||
|
|
||||||
|
virtual void MessageReceived(BMessage* message);
|
||||||
|
virtual void RefsReceived(BMessage* message);
|
||||||
|
|
||||||
|
virtual void Pulse();
|
||||||
|
virtual bool QuitRequested();
|
||||||
|
virtual void ReadyToRun();
|
||||||
|
|
||||||
|
void InstallDeskbarIcon();
|
||||||
|
void RemoveDeskbarIcon();
|
||||||
|
|
||||||
|
void SendPendingMessages(BMessage* message);
|
||||||
|
void GetNewMessages(BMessage* message);
|
||||||
|
|
||||||
|
void MakeMimeTypes(bool remakeMIMETypes = false);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _InitAccounts();
|
||||||
|
void _InitAccount(BMailAccountSettings& settings);
|
||||||
|
void _ReloadAccounts(BMessage* message);
|
||||||
|
void _RemoveAccount(AccountMap::const_iterator it);
|
||||||
|
|
||||||
|
InboundProtocol* _CreateInboundProtocol(
|
||||||
|
BMailAccountSettings& settings,
|
||||||
|
image_id& image);
|
||||||
|
OutboundProtocol* _CreateOutboundProtocol(
|
||||||
|
BMailAccountSettings& settings,
|
||||||
|
image_id& image);
|
||||||
|
|
||||||
|
InboundProtocolThread* _FindInboundProtocol(int32 account);
|
||||||
|
OutboundProtocolThread* _FindOutboundProtocol(int32 account);
|
||||||
|
|
||||||
|
void _UpdateAutoCheck(bigtime_t interval);
|
||||||
|
static bool _IsPending(BNode& node);
|
||||||
|
static bool _IsEntryInTrash(BEntry& entry);
|
||||||
|
|
||||||
|
private:
|
||||||
|
BMessageRunner* fAutoCheckRunner;
|
||||||
|
BMailSettings fSettingsFile;
|
||||||
|
|
||||||
|
int32 fNewMessages;
|
||||||
|
bool fCentralBeep;
|
||||||
|
// TRUE to do a beep when the status window closes. This happens
|
||||||
|
// when all mail has been received, so you get one beep for
|
||||||
|
// everything rather than individual beeps for each mail
|
||||||
|
// account.
|
||||||
|
// Set to TRUE by the 'mcbp' message that the mail Notification
|
||||||
|
// filter sends us, cleared when the beep is done.
|
||||||
|
BObjectList<BMessage> fFetchDoneRespondents;
|
||||||
|
BObjectList<BQuery> fQueries;
|
||||||
|
|
||||||
|
LEDAnimation* fLEDAnimation;
|
||||||
|
|
||||||
|
BString fAlertString;
|
||||||
|
|
||||||
|
AccountMap fAccounts;
|
||||||
|
|
||||||
|
ErrorLogWindow* fErrorLogWindow;
|
||||||
|
MailStatusWindow* fMailStatusWindow;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // MAIL_DAEMON_APP_H
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, Haiku, Inc. All rights reserved.
|
||||||
|
* Copyright 2011, Clemens Zeidler <haiku@clemens-zeidler.de>
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "Notifier.h"
|
||||||
|
|
||||||
|
|
||||||
|
DefaultNotifier::DefaultNotifier(const char* accountName, bool inbound,
|
||||||
|
ErrorLogWindow* errorWindow, MailStatusWindow* statusWindow)
|
||||||
|
:
|
||||||
|
fAccountName(accountName),
|
||||||
|
fIsInbound(inbound),
|
||||||
|
fErrorWindow(errorWindow),
|
||||||
|
fStatusWindow(statusWindow)
|
||||||
|
{
|
||||||
|
BString desc;
|
||||||
|
desc += (fIsInbound == true) ? "Fetching" : "Sending";
|
||||||
|
desc += " mail for ";
|
||||||
|
desc += fAccountName;
|
||||||
|
|
||||||
|
fStatusWindow->Lock();
|
||||||
|
fStatusView = fStatusWindow->NewStatusView(desc, fIsInbound != false);
|
||||||
|
fStatusWindow->Unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DefaultNotifier::~DefaultNotifier()
|
||||||
|
{
|
||||||
|
fStatusWindow->Lock();
|
||||||
|
if (fStatusView->Window())
|
||||||
|
fStatusWindow->RemoveView(fStatusView);
|
||||||
|
delete fStatusView;
|
||||||
|
fStatusWindow->Unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
MailNotifier*
|
||||||
|
DefaultNotifier::Clone()
|
||||||
|
{
|
||||||
|
return new DefaultNotifier(fAccountName, fIsInbound, fErrorWindow,
|
||||||
|
fStatusWindow);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
DefaultNotifier::ShowError(const char* error)
|
||||||
|
{
|
||||||
|
fErrorWindow->AddError(B_WARNING_ALERT, error, fAccountName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
DefaultNotifier::ShowMessage(const char* message)
|
||||||
|
{
|
||||||
|
fErrorWindow->AddError(B_INFO_ALERT, message, fAccountName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
DefaultNotifier::SetTotalItems(int32 items)
|
||||||
|
{
|
||||||
|
fStatusView->SetTotalItems(items);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
DefaultNotifier::SetTotalItemsSize(int32 size)
|
||||||
|
{
|
||||||
|
fStatusView->SetMaximum(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
DefaultNotifier::ReportProgress(int bytes, int messages, const char* message)
|
||||||
|
{
|
||||||
|
if (bytes != 0)
|
||||||
|
fStatusView->AddProgress(bytes);
|
||||||
|
|
||||||
|
for (int i = 0; i < messages; i++)
|
||||||
|
fStatusView->AddItem();
|
||||||
|
|
||||||
|
if (message != NULL)
|
||||||
|
fStatusView->SetMessage(message);
|
||||||
|
|
||||||
|
if (fStatusView->ItemsNow() == fStatusView->CountTotalItems())
|
||||||
|
fStatusView->Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
DefaultNotifier::ResetProgress(const char* message)
|
||||||
|
{
|
||||||
|
fStatusView->Reset();
|
||||||
|
if (message != NULL)
|
||||||
|
fStatusView->SetMessage(message);
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, Haiku, Inc. All rights reserved.
|
||||||
|
* Copyright 2011, Clemens Zeidler <haiku@clemens-zeidler.de>
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef NOTIFIER_H
|
||||||
|
#define NOTIFIER_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <String.h>
|
||||||
|
|
||||||
|
#include "MailProtocol.h"
|
||||||
|
|
||||||
|
#include "ErrorLogWindow.h"
|
||||||
|
#include "StatusWindow.h"
|
||||||
|
|
||||||
|
|
||||||
|
class DefaultNotifier : public MailNotifier {
|
||||||
|
public:
|
||||||
|
DefaultNotifier(const char* accountName,
|
||||||
|
bool inbound, ErrorLogWindow* errorWindow,
|
||||||
|
MailStatusWindow* statusWindow);
|
||||||
|
~DefaultNotifier();
|
||||||
|
|
||||||
|
MailNotifier* Clone();
|
||||||
|
|
||||||
|
void ShowError(const char* error);
|
||||||
|
void ShowMessage(const char* message);
|
||||||
|
|
||||||
|
void SetTotalItems(int32 items);
|
||||||
|
void SetTotalItemsSize(int32 size);
|
||||||
|
void ReportProgress(int bytes, int messages,
|
||||||
|
const char* message = NULL);
|
||||||
|
void ResetProgress(const char* message = NULL);
|
||||||
|
|
||||||
|
private:
|
||||||
|
BString fAccountName;
|
||||||
|
bool fIsInbound;
|
||||||
|
ErrorLogWindow* fErrorWindow;
|
||||||
|
MailStatusWindow* fStatusWindow;
|
||||||
|
MailStatusView* fStatusView;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //NOTIFIER_H
|
||||||
@@ -9,7 +9,8 @@
|
|||||||
//! The status window while fetching/sending mails
|
//! The status window while fetching/sending mails
|
||||||
|
|
||||||
|
|
||||||
#include "status.h"
|
#include "StatusWindow.h"
|
||||||
|
|
||||||
#include "MailSettings.h"
|
#include "MailSettings.h"
|
||||||
|
|
||||||
#include <MDRLanguage.h>
|
#include <MDRLanguage.h>
|
||||||
@@ -36,9 +37,10 @@
|
|||||||
static BLocker sLock;
|
static BLocker sLock;
|
||||||
|
|
||||||
|
|
||||||
BMailStatusWindow::BMailStatusWindow(BRect rect, const char *name,
|
MailStatusWindow::MailStatusWindow(BRect rect, const char *name,
|
||||||
uint32 showMode)
|
uint32 showMode)
|
||||||
: BWindow(rect, name, B_MODAL_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
|
:
|
||||||
|
BWindow(rect, name, B_MODAL_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
|
||||||
B_NOT_CLOSABLE | B_NO_WORKSPACE_ACTIVATION | B_NOT_V_RESIZABLE
|
B_NOT_CLOSABLE | B_NO_WORKSPACE_ACTIVATION | B_NOT_V_RESIZABLE
|
||||||
| B_NOT_ZOOMABLE | B_NOT_MINIMIZABLE | B_AVOID_FRONT),
|
| B_NOT_ZOOMABLE | B_NOT_MINIMIZABLE | B_AVOID_FRONT),
|
||||||
fShowMode(showMode),
|
fShowMode(showMode),
|
||||||
@@ -118,10 +120,8 @@ BMailStatusWindow::BMailStatusWindow(BRect rect, const char *name,
|
|||||||
fFrame = Frame();
|
fFrame = Frame();
|
||||||
|
|
||||||
BPath path;
|
BPath path;
|
||||||
status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path);
|
status_t status = BMailAccounts::AccountsPath(path);
|
||||||
if (status == B_OK) {
|
if (status == B_OK) {
|
||||||
path.Append("Mail/chains/inbound");
|
|
||||||
create_directory(path.Path(), 0755);
|
|
||||||
BDirectory chainDirectory(path.Path());
|
BDirectory chainDirectory(path.Path());
|
||||||
if (chainDirectory.GetNodeRef(&fChainDirectory) == B_OK) {
|
if (chainDirectory.GetNodeRef(&fChainDirectory) == B_OK) {
|
||||||
// Watch this directory for changes
|
// Watch this directory for changes
|
||||||
@@ -137,10 +137,10 @@ BMailStatusWindow::BMailStatusWindow(BRect rect, const char *name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BMailStatusWindow::~BMailStatusWindow()
|
MailStatusWindow::~MailStatusWindow()
|
||||||
{
|
{
|
||||||
// remove all status_views, so we don't accidentally delete them
|
// remove all status_views, so we don't accidentally delete them
|
||||||
while (BMailStatusView *status_view = (BMailStatusView *)fStatusViews.RemoveItem(0L))
|
while (MailStatusView *status_view = (MailStatusView *)fStatusViews.RemoveItem(0L))
|
||||||
RemoveView(status_view);
|
RemoveView(status_view);
|
||||||
|
|
||||||
BMailSettings general;
|
BMailSettings general;
|
||||||
@@ -157,19 +157,23 @@ BMailStatusWindow::~BMailStatusWindow()
|
|||||||
|
|
||||||
//! Activate the "Check Now" button only if there are inbound accounts
|
//! Activate the "Check Now" button only if there are inbound accounts
|
||||||
void
|
void
|
||||||
BMailStatusWindow::_CheckChains()
|
MailStatusWindow::_CheckChains()
|
||||||
{
|
{
|
||||||
BDirectory directory(&fChainDirectory);
|
bool hasInbound = false;
|
||||||
|
BMailAccounts accounts;
|
||||||
|
for (int32 i = 0; i < accounts.CountAccounts(); i++) {
|
||||||
|
if (accounts.AccountAt(i)->HasInbound()) {
|
||||||
|
hasInbound = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
entry_ref ref;
|
fCheckNowButton->SetEnabled(hasInbound);
|
||||||
bool isEmpty = directory.GetNextRef(&ref) != B_OK;
|
|
||||||
|
|
||||||
fCheckNowButton->SetEnabled(!isEmpty);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BMailStatusWindow::FrameMoved(BPoint /*origin*/)
|
MailStatusWindow::FrameMoved(BPoint /*origin*/)
|
||||||
{
|
{
|
||||||
if (fLastWorkspace == current_workspace())
|
if (fLastWorkspace == current_workspace())
|
||||||
fFrame = Frame();
|
fFrame = Frame();
|
||||||
@@ -177,7 +181,7 @@ BMailStatusWindow::FrameMoved(BPoint /*origin*/)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BMailStatusWindow::WorkspaceActivated(int32 workspace, bool active)
|
MailStatusWindow::WorkspaceActivated(int32 workspace, bool active)
|
||||||
{
|
{
|
||||||
if (!active)
|
if (!active)
|
||||||
return;
|
return;
|
||||||
@@ -195,7 +199,7 @@ BMailStatusWindow::WorkspaceActivated(int32 workspace, bool active)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BMailStatusWindow::MessageReceived(BMessage *msg)
|
MailStatusWindow::MessageReceived(BMessage *msg)
|
||||||
{
|
{
|
||||||
switch (msg->what) {
|
switch (msg->what) {
|
||||||
case 'lkch':
|
case 'lkch':
|
||||||
@@ -232,7 +236,7 @@ BMailStatusWindow::MessageReceived(BMessage *msg)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BMailStatusWindow::SetDefaultMessage(const BString &message)
|
MailStatusWindow::SetDefaultMessage(const BString &message)
|
||||||
{
|
{
|
||||||
if (Lock()) {
|
if (Lock()) {
|
||||||
fMessageView->SetText(message.String());
|
fMessageView->SetText(message.String());
|
||||||
@@ -241,8 +245,8 @@ BMailStatusWindow::SetDefaultMessage(const BString &message)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BMailStatusView *
|
MailStatusView *
|
||||||
BMailStatusWindow::NewStatusView(const char *description, bool upstream)
|
MailStatusWindow::NewStatusView(const char *description, bool upstream)
|
||||||
{
|
{
|
||||||
if (!Lock())
|
if (!Lock())
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -250,7 +254,7 @@ BMailStatusWindow::NewStatusView(const char *description, bool upstream)
|
|||||||
BRect rect = Bounds();
|
BRect rect = Bounds();
|
||||||
rect.top = fStatusViews.CountItems() * (fMinHeight + 1);
|
rect.top = fStatusViews.CountItems() * (fMinHeight + 1);
|
||||||
rect.bottom = rect.top + fMinHeight;
|
rect.bottom = rect.top + fMinHeight;
|
||||||
BMailStatusView *status = new BMailStatusView(rect, description, upstream);
|
MailStatusView *status = new MailStatusView(rect, description, upstream);
|
||||||
status->window = this;
|
status->window = this;
|
||||||
|
|
||||||
Unlock();
|
Unlock();
|
||||||
@@ -259,7 +263,7 @@ BMailStatusWindow::NewStatusView(const char *description, bool upstream)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BMailStatusWindow::ActuallyAddStatusView(BMailStatusView *status)
|
MailStatusWindow::ActuallyAddStatusView(MailStatusView *status)
|
||||||
{
|
{
|
||||||
if (!Lock())
|
if (!Lock())
|
||||||
return;
|
return;
|
||||||
@@ -307,7 +311,7 @@ BMailStatusWindow::ActuallyAddStatusView(BMailStatusView *status)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BMailStatusWindow::RemoveView(BMailStatusView *view)
|
MailStatusWindow::RemoveView(MailStatusView *view)
|
||||||
{
|
{
|
||||||
if (!view || !Lock())
|
if (!view || !Lock())
|
||||||
return;
|
return;
|
||||||
@@ -324,7 +328,7 @@ BMailStatusWindow::RemoveView(BMailStatusView *view)
|
|||||||
|
|
||||||
fStatusViews.RemoveItem((void *)view);
|
fStatusViews.RemoveItem((void *)view);
|
||||||
if (RemoveChild(view)) {
|
if (RemoveChild(view)) {
|
||||||
while ((view = (BMailStatusView *)fStatusViews.ItemAt(i++)) != NULL)
|
while ((view = (MailStatusView *)fStatusViews.ItemAt(i++)) != NULL)
|
||||||
view->MoveBy(0, -fMinHeight - 1);
|
view->MoveBy(0, -fMinHeight - 1);
|
||||||
|
|
||||||
// the view will be deleted in the ChainRunner
|
// the view will be deleted in the ChainRunner
|
||||||
@@ -360,14 +364,14 @@ BMailStatusWindow::RemoveView(BMailStatusView *view)
|
|||||||
|
|
||||||
|
|
||||||
int32
|
int32
|
||||||
BMailStatusWindow::CountVisibleItems()
|
MailStatusWindow::CountVisibleItems()
|
||||||
{
|
{
|
||||||
if (fShowMode != B_MAIL_SHOW_STATUS_WINDOW_WHEN_SENDING)
|
if (fShowMode != B_MAIL_SHOW_STATUS_WINDOW_WHEN_SENDING)
|
||||||
return fStatusViews.CountItems();
|
return fStatusViews.CountItems();
|
||||||
|
|
||||||
int32 count = 0;
|
int32 count = 0;
|
||||||
for (int32 i = fStatusViews.CountItems(); i-- > 0;) {
|
for (int32 i = fStatusViews.CountItems(); i-- > 0;) {
|
||||||
BMailStatusView *view = (BMailStatusView *)fStatusViews.ItemAt(i);
|
MailStatusView *view = (MailStatusView *)fStatusViews.ItemAt(i);
|
||||||
if (view->is_upstream)
|
if (view->is_upstream)
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
@@ -376,14 +380,14 @@ BMailStatusWindow::CountVisibleItems()
|
|||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
BMailStatusWindow::HasItems(void)
|
MailStatusWindow::HasItems(void)
|
||||||
{
|
{
|
||||||
return CountVisibleItems() > 0;
|
return CountVisibleItems() > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BMailStatusWindow::SetShowCriterion(uint32 when)
|
MailStatusWindow::SetShowCriterion(uint32 when)
|
||||||
{
|
{
|
||||||
if (!Lock())
|
if (!Lock())
|
||||||
return;
|
return;
|
||||||
@@ -403,7 +407,7 @@ BMailStatusWindow::SetShowCriterion(uint32 when)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BMailStatusWindow::SetBorderStyle(int32 look)
|
MailStatusWindow::SetBorderStyle(int32 look)
|
||||||
{
|
{
|
||||||
switch (look) {
|
switch (look) {
|
||||||
case B_MAIL_STATUS_LOOK_TITLED:
|
case B_MAIL_STATUS_LOOK_TITLED:
|
||||||
@@ -429,12 +433,12 @@ BMailStatusWindow::SetBorderStyle(int32 look)
|
|||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
//------------------------------------------------
|
//------------------------------------------------
|
||||||
//
|
//
|
||||||
// BMailStatusView
|
// MailStatusView
|
||||||
//
|
//
|
||||||
//------------------------------------------------
|
//------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
BMailStatusView::BMailStatusView(BRect rect, const char *description,bool upstream)
|
MailStatusView::MailStatusView(BRect rect, const char *description,bool upstream)
|
||||||
: BBox(rect, description, B_FOLLOW_LEFT_RIGHT,
|
: BBox(rect, description, B_FOLLOW_LEFT_RIGHT,
|
||||||
B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE_JUMP,
|
B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE_JUMP,
|
||||||
B_PLAIN_BORDER)
|
B_PLAIN_BORDER)
|
||||||
@@ -454,16 +458,18 @@ BMailStatusView::BMailStatusView(BRect rect, const char *description,bool upstre
|
|||||||
total_items = 0;
|
total_items = 0;
|
||||||
pre_text[0] = 0;
|
pre_text[0] = 0;
|
||||||
is_upstream = upstream;
|
is_upstream = upstream;
|
||||||
|
|
||||||
|
by_bytes = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BMailStatusView::~BMailStatusView()
|
MailStatusView::~MailStatusView()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BMailStatusView::AddProgress(int32 how_much)
|
MailStatusView::AddProgress(int32 how_much)
|
||||||
{
|
{
|
||||||
AddSelfToWindow();
|
AddSelfToWindow();
|
||||||
|
|
||||||
@@ -484,7 +490,7 @@ BMailStatusView::AddProgress(int32 how_much)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BMailStatusView::SetMessage(const char *msg)
|
MailStatusView::SetMessage(const char *msg)
|
||||||
{
|
{
|
||||||
AddSelfToWindow();
|
AddSelfToWindow();
|
||||||
|
|
||||||
@@ -496,31 +502,34 @@ BMailStatusView::SetMessage(const char *msg)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BMailStatusView::Reset(bool hide)
|
MailStatusView::Reset(bool hide)
|
||||||
{
|
{
|
||||||
if (LockLooper()) {
|
if (!LockLooper())
|
||||||
char old[255];
|
return;
|
||||||
if ((pre_text[0] == 0) && !hide)
|
|
||||||
strcpy(pre_text, status->TrailingText());
|
|
||||||
if (hide)
|
|
||||||
pre_text[0] = 0;
|
|
||||||
|
|
||||||
strcpy(old,status->Label());
|
char old[255];
|
||||||
status->Reset(old);
|
if ((pre_text[0] == 0) && !hide)
|
||||||
status->SetTrailingText(pre_text);
|
strcpy(pre_text, status->TrailingText());
|
||||||
status->Draw(status->Bounds());
|
if (hide)
|
||||||
pre_text[0] = 0;
|
pre_text[0] = 0;
|
||||||
total_items = 0;
|
|
||||||
items_now = 0;
|
strcpy(old,status->Label());
|
||||||
UnlockLooper();
|
status->Reset(old);
|
||||||
}
|
status->SetTrailingText(pre_text);
|
||||||
|
status->Draw(status->Bounds());
|
||||||
|
pre_text[0] = 0;
|
||||||
|
total_items = 0;
|
||||||
|
items_now = 0;
|
||||||
|
|
||||||
|
UnlockLooper();
|
||||||
|
|
||||||
if (hide && Window())
|
if (hide && Window())
|
||||||
window->RemoveView(this);
|
window->RemoveView(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BMailStatusView::SetMaximum(int32 max_bytes)
|
MailStatusView::SetMaximum(int32 max_bytes)
|
||||||
{
|
{
|
||||||
AddSelfToWindow();
|
AddSelfToWindow();
|
||||||
|
|
||||||
@@ -538,22 +547,24 @@ BMailStatusView::SetMaximum(int32 max_bytes)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BMailStatusView::SetTotalItems(int32 items)
|
MailStatusView::SetTotalItems(int32 items)
|
||||||
{
|
{
|
||||||
AddSelfToWindow();
|
AddSelfToWindow();
|
||||||
total_items = items;
|
total_items = items;
|
||||||
|
if (!by_bytes)
|
||||||
|
SetMaximum(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int32
|
int32
|
||||||
BMailStatusView::CountTotalItems()
|
MailStatusView::CountTotalItems()
|
||||||
{
|
{
|
||||||
return total_items;
|
return total_items;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BMailStatusView::AddItem(void)
|
MailStatusView::AddItem(void)
|
||||||
{
|
{
|
||||||
AddSelfToWindow();
|
AddSelfToWindow();
|
||||||
items_now++;
|
items_now++;
|
||||||
@@ -564,7 +575,7 @@ BMailStatusView::AddItem(void)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BMailStatusView::AddSelfToWindow()
|
MailStatusView::AddSelfToWindow()
|
||||||
{
|
{
|
||||||
if (Window() != NULL)
|
if (Window() != NULL)
|
||||||
return;
|
return;
|
||||||
@@ -16,19 +16,19 @@
|
|||||||
|
|
||||||
class BStatusBar;
|
class BStatusBar;
|
||||||
class BStringView;
|
class BStringView;
|
||||||
class BMailStatusView;
|
class MailStatusView;
|
||||||
|
|
||||||
class BMailStatusWindow : public BWindow {
|
class MailStatusWindow : public BWindow {
|
||||||
public:
|
public:
|
||||||
BMailStatusWindow(BRect rect, const char *name, uint32 showMode);
|
MailStatusWindow(BRect rect, const char *name, uint32 showMode);
|
||||||
~BMailStatusWindow();
|
~MailStatusWindow();
|
||||||
|
|
||||||
virtual void FrameMoved(BPoint origin);
|
virtual void FrameMoved(BPoint origin);
|
||||||
virtual void WorkspaceActivated(int32 workspace, bool active);
|
virtual void WorkspaceActivated(int32 workspace, bool active);
|
||||||
virtual void MessageReceived(BMessage *msg);
|
virtual void MessageReceived(BMessage *msg);
|
||||||
|
|
||||||
BMailStatusView *NewStatusView(const char *description, bool upstream);
|
MailStatusView *NewStatusView(const char *description, bool upstream);
|
||||||
void RemoveView(BMailStatusView *view);
|
void RemoveView(MailStatusView *view);
|
||||||
int32 CountVisibleItems();
|
int32 CountVisibleItems();
|
||||||
|
|
||||||
bool HasItems(void);
|
bool HasItems(void);
|
||||||
@@ -36,11 +36,11 @@ class BMailStatusWindow : public BWindow {
|
|||||||
void SetDefaultMessage(const BString &message);
|
void SetDefaultMessage(const BString &message);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class BMailStatusView;
|
friend class MailStatusView;
|
||||||
|
|
||||||
void _CheckChains();
|
void _CheckChains();
|
||||||
void SetBorderStyle(int32 look);
|
void SetBorderStyle(int32 look);
|
||||||
void ActuallyAddStatusView(BMailStatusView *status);
|
void ActuallyAddStatusView(MailStatusView *status);
|
||||||
|
|
||||||
node_ref fChainDirectory;
|
node_ref fChainDirectory;
|
||||||
BButton* fCheckNowButton;
|
BButton* fCheckNowButton;
|
||||||
@@ -57,26 +57,27 @@ class BMailStatusWindow : public BWindow {
|
|||||||
uint32 _reserved[5];
|
uint32 _reserved[5];
|
||||||
};
|
};
|
||||||
|
|
||||||
class BMailStatusView : public BBox {
|
class MailStatusView : public BBox {
|
||||||
public:
|
public:
|
||||||
void AddProgress(int32 how_much);
|
~MailStatusView();
|
||||||
void SetMessage(const char *msg);
|
|
||||||
void SetMaximum(int32 max_bytes);
|
|
||||||
int32 CountTotalItems();
|
|
||||||
void SetTotalItems(int32 items);
|
|
||||||
void AddItem(void);
|
|
||||||
void Reset(bool hide = true);
|
|
||||||
|
|
||||||
virtual ~BMailStatusView();
|
|
||||||
|
|
||||||
private:
|
void AddProgress(int32 how_much);
|
||||||
friend class BMailStatusWindow;
|
void SetMessage(const char *msg);
|
||||||
|
void SetMaximum(int32 max_bytes);
|
||||||
|
int32 CountTotalItems();
|
||||||
|
void SetTotalItems(int32 items);
|
||||||
|
void AddItem(void);
|
||||||
|
void Reset(bool hide = true);
|
||||||
|
int32 ItemsNow() { return items_now; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class MailStatusWindow;
|
||||||
|
|
||||||
BMailStatusView(BRect rect,const char *description,bool upstream);
|
MailStatusView(BRect rect,const char *description,bool upstream);
|
||||||
void AddSelfToWindow();
|
void AddSelfToWindow();
|
||||||
|
|
||||||
BStatusBar *status;
|
BStatusBar *status;
|
||||||
BMailStatusWindow *window;
|
MailStatusWindow *window;
|
||||||
int32 items_now;
|
int32 items_now;
|
||||||
int32 total_items;
|
int32 total_items;
|
||||||
bool is_upstream;
|
bool is_upstream;
|
||||||
+7
-788
@@ -1,786 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2009-2010, Axel Dörfler, axeld@pinc-software.de.
|
* Copyright 2007-2011, Haiku, Inc. All rights reserved.
|
||||||
* Copyright 2001 Dr. Zoidberg Enterprises. 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.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
//! The daemon's inner workings
|
#include "MailDaemon.h"
|
||||||
|
|
||||||
|
|
||||||
#include <Application.h>
|
|
||||||
#include <Beep.h>
|
|
||||||
#include <Button.h>
|
|
||||||
#include <ChainRunner.h>
|
|
||||||
#include <Deskbar.h>
|
|
||||||
#include <Directory.h>
|
|
||||||
#include <File.h>
|
|
||||||
#include <FindDirectory.h>
|
|
||||||
#include <fs_index.h>
|
|
||||||
#include <fs_info.h>
|
|
||||||
#include <Message.h>
|
|
||||||
#include <MessageRunner.h>
|
|
||||||
#include <Mime.h>
|
|
||||||
#include <NodeMonitor.h>
|
|
||||||
#include <Path.h>
|
|
||||||
#include <Query.h>
|
|
||||||
#include <Roster.h>
|
|
||||||
#include <String.h>
|
|
||||||
#include <StringView.h>
|
|
||||||
#include <VolumeRoster.h>
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
#include <E-mail.h>
|
|
||||||
#include <MailSettings.h>
|
|
||||||
#include <MailMessage.h>
|
|
||||||
#include <status.h>
|
|
||||||
#include <StringList.h>
|
|
||||||
|
|
||||||
#include "DeskbarView.h"
|
|
||||||
#include "LEDAnimation.h"
|
|
||||||
|
|
||||||
#include <MDRLanguage.h>
|
|
||||||
|
|
||||||
|
|
||||||
using std::map;
|
|
||||||
|
|
||||||
typedef struct glorbal {
|
|
||||||
size_t bytes;
|
|
||||||
BStringList msgs;
|
|
||||||
} snuzzwut;
|
|
||||||
|
|
||||||
|
|
||||||
static BMailStatusWindow* sStatus;
|
|
||||||
|
|
||||||
|
|
||||||
class MailDaemonApp : public BApplication {
|
|
||||||
public:
|
|
||||||
MailDaemonApp();
|
|
||||||
virtual ~MailDaemonApp();
|
|
||||||
|
|
||||||
virtual void MessageReceived(BMessage* message);
|
|
||||||
virtual void RefsReceived(BMessage* message);
|
|
||||||
|
|
||||||
virtual void Pulse();
|
|
||||||
virtual bool QuitRequested();
|
|
||||||
virtual void ReadyToRun();
|
|
||||||
|
|
||||||
void InstallDeskbarIcon();
|
|
||||||
void RemoveDeskbarIcon();
|
|
||||||
|
|
||||||
void RunChains(BList& list, BMessage* message);
|
|
||||||
void SendPendingMessages(BMessage* message);
|
|
||||||
void GetNewMessages(BMessage* message);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void _UpdateAutoCheck(bigtime_t interval);
|
|
||||||
static bool _IsPending(BNode& node);
|
|
||||||
static bool _IsEntryInTrash(BEntry& entry);
|
|
||||||
|
|
||||||
private:
|
|
||||||
BMessageRunner* fAutoCheckRunner;
|
|
||||||
BMailSettings fSettingsFile;
|
|
||||||
|
|
||||||
int32 fNewMessages;
|
|
||||||
bool fCentralBeep;
|
|
||||||
// TRUE to do a beep when the status window closes. This happens
|
|
||||||
// when all mail has been received, so you get one beep for
|
|
||||||
// everything rather than individual beeps for each mail
|
|
||||||
// account.
|
|
||||||
// Set to TRUE by the 'mcbp' message that the mail Notification
|
|
||||||
// filter sends us, cleared when the beep is done.
|
|
||||||
BList fFetchDoneRespondents;
|
|
||||||
BList fQueries;
|
|
||||||
|
|
||||||
LEDAnimation* fLEDAnimation;
|
|
||||||
|
|
||||||
BString fAlertString;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
MailDaemonApp::MailDaemonApp()
|
|
||||||
:
|
|
||||||
BApplication("application/x-vnd.Be-POST")
|
|
||||||
{
|
|
||||||
sStatus = new BMailStatusWindow(BRect(40, 400, 360, 400), "Mail Status",
|
|
||||||
fSettingsFile.ShowStatusWindow());
|
|
||||||
fAutoCheckRunner = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
MailDaemonApp::~MailDaemonApp()
|
|
||||||
{
|
|
||||||
delete fAutoCheckRunner;
|
|
||||||
|
|
||||||
for (int32 i = 0; i < fQueries.CountItems(); i++)
|
|
||||||
delete (BQuery*)fQueries.ItemAt(i);
|
|
||||||
|
|
||||||
delete fLEDAnimation;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
MailDaemonApp::ReadyToRun()
|
|
||||||
{
|
|
||||||
InstallDeskbarIcon();
|
|
||||||
|
|
||||||
_UpdateAutoCheck(fSettingsFile.AutoCheckInterval());
|
|
||||||
|
|
||||||
BVolume volume;
|
|
||||||
BVolumeRoster roster;
|
|
||||||
|
|
||||||
fNewMessages = 0;
|
|
||||||
|
|
||||||
while (roster.GetNextVolume(&volume) == B_OK) {
|
|
||||||
//{char name[255];volume.GetName(name);printf("Volume: %s\n",name);}
|
|
||||||
|
|
||||||
BQuery* query = new BQuery;
|
|
||||||
|
|
||||||
query->SetTarget(this);
|
|
||||||
query->SetVolume(&volume);
|
|
||||||
query->PushAttr(B_MAIL_ATTR_STATUS);
|
|
||||||
query->PushString("New");
|
|
||||||
query->PushOp(B_EQ);
|
|
||||||
query->PushAttr("BEOS:TYPE");
|
|
||||||
query->PushString("text/x-email");
|
|
||||||
query->PushOp(B_EQ);
|
|
||||||
query->PushAttr("BEOS:TYPE");
|
|
||||||
query->PushString("text/x-partial-email");
|
|
||||||
query->PushOp(B_EQ);
|
|
||||||
query->PushOp(B_OR);
|
|
||||||
query->PushOp(B_AND);
|
|
||||||
query->Fetch();
|
|
||||||
|
|
||||||
BEntry entry;
|
|
||||||
while (query->GetNextEntry(&entry) == B_OK)
|
|
||||||
fNewMessages++;
|
|
||||||
|
|
||||||
fQueries.AddItem(query);
|
|
||||||
}
|
|
||||||
|
|
||||||
BString string;
|
|
||||||
MDR_DIALECT_CHOICE(
|
|
||||||
if (fNewMessages > 0)
|
|
||||||
string << fNewMessages;
|
|
||||||
else
|
|
||||||
string << "No";
|
|
||||||
if (fNewMessages != 1)
|
|
||||||
string << " new messages.";
|
|
||||||
else
|
|
||||||
string << " new message.";,
|
|
||||||
if (fNewMessages > 0)
|
|
||||||
string << fNewMessages << " 通の未読メッセージがあります ";
|
|
||||||
else
|
|
||||||
string << "未読メッセージはありません";
|
|
||||||
);
|
|
||||||
fCentralBeep = false;
|
|
||||||
sStatus->SetDefaultMessage(string);
|
|
||||||
|
|
||||||
fLEDAnimation = new LEDAnimation;
|
|
||||||
SetPulseRate(1000000);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
MailDaemonApp::RefsReceived(BMessage* message)
|
|
||||||
{
|
|
||||||
sStatus->Activate(true);
|
|
||||||
|
|
||||||
entry_ref ref;
|
|
||||||
for (int32 i = 0; message->FindRef("refs", i, &ref) == B_OK; i++) {
|
|
||||||
BNode node(&ref);
|
|
||||||
if (node.InitCheck() < B_OK)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
BString uid;
|
|
||||||
if (node.ReadAttrString("MAIL:unique_id", &uid) < 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
int32 id;
|
|
||||||
if (node.ReadAttr("MAIL:chain", B_INT32_TYPE, 0, &id, sizeof(id)) < 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
int32 size;
|
|
||||||
if (node.ReadAttr("MAIL:fullsize", B_SIZE_T_TYPE, 0, &size,
|
|
||||||
sizeof(size)) < 0) {
|
|
||||||
size = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
BPath path(&ref);
|
|
||||||
BMailChainRunner* runner = GetMailChainRunner(id, sStatus);
|
|
||||||
if (runner != NULL)
|
|
||||||
runner->GetSingleMessage(uid.String(), size, &path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
MailDaemonApp::_UpdateAutoCheck(bigtime_t interval)
|
|
||||||
{
|
|
||||||
if (interval > 0) {
|
|
||||||
if (fAutoCheckRunner != NULL) {
|
|
||||||
fAutoCheckRunner->SetInterval(interval);
|
|
||||||
fAutoCheckRunner->SetCount(-1);
|
|
||||||
} else
|
|
||||||
fAutoCheckRunner = new BMessageRunner(be_app_messenger,
|
|
||||||
new BMessage('moto'), interval);
|
|
||||||
} else {
|
|
||||||
delete fAutoCheckRunner;
|
|
||||||
fAutoCheckRunner = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
MailDaemonApp::MessageReceived(BMessage* msg)
|
|
||||||
{
|
|
||||||
switch (msg->what) {
|
|
||||||
case 'moto':
|
|
||||||
if (fSettingsFile.CheckOnlyIfPPPUp()) {
|
|
||||||
// TODO: check whether internet is up and running!
|
|
||||||
}
|
|
||||||
// supposed to fall through
|
|
||||||
case 'mbth': // check & send messages
|
|
||||||
msg->what = 'msnd';
|
|
||||||
PostMessage(msg);
|
|
||||||
// supposed to fall trough
|
|
||||||
case 'mnow': // check messages
|
|
||||||
GetNewMessages(msg);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'msnd': // send messages
|
|
||||||
SendPendingMessages(msg);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'mrrs':
|
|
||||||
fSettingsFile.Reload();
|
|
||||||
_UpdateAutoCheck(fSettingsFile.AutoCheckInterval());
|
|
||||||
sStatus->SetShowCriterion(fSettingsFile.ShowStatusWindow());
|
|
||||||
break;
|
|
||||||
case 'shst': // when to show the status window
|
|
||||||
{
|
|
||||||
int32 mode;
|
|
||||||
if (msg->FindInt32("ShowStatusWindow", &mode) == B_OK)
|
|
||||||
sStatus->SetShowCriterion(mode);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'lkch': // status window look changed
|
|
||||||
case 'wsch': // workspace changed
|
|
||||||
sStatus->PostMessage(msg);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'stwg': // Status window gone
|
|
||||||
{
|
|
||||||
BMessage reply('mnuc');
|
|
||||||
reply.AddInt32("num_new_messages", fNewMessages);
|
|
||||||
|
|
||||||
while ((msg = (BMessage*)fFetchDoneRespondents.RemoveItem(0L))) {
|
|
||||||
msg->SendReply(&reply);
|
|
||||||
delete msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fAlertString != B_EMPTY_STRING) {
|
|
||||||
fAlertString.Truncate(fAlertString.Length() - 1);
|
|
||||||
BAlert* alert = new BAlert(MDR_DIALECT_CHOICE("New Messages",
|
|
||||||
"新着メッセージ"), fAlertString.String(), "OK", NULL, NULL,
|
|
||||||
B_WIDTH_AS_USUAL);
|
|
||||||
alert->SetFeel(B_NORMAL_WINDOW_FEEL);
|
|
||||||
alert->Go(NULL);
|
|
||||||
fAlertString = B_EMPTY_STRING;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fCentralBeep) {
|
|
||||||
system_beep("New E-mail");
|
|
||||||
fCentralBeep = false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'mcbp':
|
|
||||||
if (fNewMessages > 0)
|
|
||||||
fCentralBeep = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'mnum': // Number of new messages
|
|
||||||
{
|
|
||||||
BMessage reply('mnuc'); // Mail New message Count
|
|
||||||
if (msg->FindBool("wait_for_fetch_done")) {
|
|
||||||
fFetchDoneRespondents.AddItem(DetachCurrentMessage());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
reply.AddInt32("num_new_messages", fNewMessages);
|
|
||||||
msg->SendReply(&reply);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'mblk': // Mail Blink
|
|
||||||
if (fNewMessages > 0)
|
|
||||||
fLEDAnimation->Start();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'enda': // End Auto Check
|
|
||||||
delete fAutoCheckRunner;
|
|
||||||
fAutoCheckRunner = NULL;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'numg':
|
|
||||||
{
|
|
||||||
int32 numMessages = msg->FindInt32("num_messages");
|
|
||||||
MDR_DIALECT_CHOICE(
|
|
||||||
fAlertString << numMessages << " new message";
|
|
||||||
if (numMessages > 1)
|
|
||||||
fAlertString << 's';
|
|
||||||
|
|
||||||
fAlertString << " for " << msg->FindString("chain_name")
|
|
||||||
<< '\n';,
|
|
||||||
|
|
||||||
fAlertString << msg->FindString("chain_name") << "より\n"
|
|
||||||
<< numMessages << " 通のメッセージが届きました ";
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case B_QUERY_UPDATE:
|
|
||||||
{
|
|
||||||
int32 what;
|
|
||||||
msg->FindInt32("opcode", &what);
|
|
||||||
switch (what) {
|
|
||||||
case B_ENTRY_CREATED:
|
|
||||||
fNewMessages++;
|
|
||||||
break;
|
|
||||||
case B_ENTRY_REMOVED:
|
|
||||||
fNewMessages--;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
BString string;
|
|
||||||
|
|
||||||
MDR_DIALECT_CHOICE(
|
|
||||||
if (fNewMessages > 0)
|
|
||||||
string << fNewMessages;
|
|
||||||
else
|
|
||||||
string << "No";
|
|
||||||
if (fNewMessages != 1)
|
|
||||||
string << " new messages.";
|
|
||||||
else
|
|
||||||
string << " new message.";,
|
|
||||||
|
|
||||||
if (fNewMessages > 0)
|
|
||||||
string << fNewMessages << " 通の未読メッセージがあります";
|
|
||||||
else
|
|
||||||
string << "未読メッセージはありません";
|
|
||||||
);
|
|
||||||
|
|
||||||
sStatus->SetDefaultMessage(string.String());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
BApplication::MessageReceived(msg);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
MailDaemonApp::InstallDeskbarIcon()
|
|
||||||
{
|
|
||||||
BDeskbar deskbar;
|
|
||||||
|
|
||||||
if (!deskbar.HasItem("mail_daemon")) {
|
|
||||||
BRoster roster;
|
|
||||||
entry_ref ref;
|
|
||||||
|
|
||||||
status_t status = roster.FindApp("application/x-vnd.Be-POST", &ref);
|
|
||||||
if (status < B_OK) {
|
|
||||||
fprintf(stderr, "Can't find application to tell deskbar: %s\n",
|
|
||||||
strerror(status));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
status = deskbar.AddItem(&ref);
|
|
||||||
if (status < B_OK) {
|
|
||||||
fprintf(stderr, "Can't add deskbar replicant: %s\n", strerror(status));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
MailDaemonApp::RemoveDeskbarIcon()
|
|
||||||
{
|
|
||||||
BDeskbar deskbar;
|
|
||||||
if (deskbar.HasItem("mail_daemon"))
|
|
||||||
deskbar.RemoveItem("mail_daemon");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
MailDaemonApp::QuitRequested()
|
|
||||||
{
|
|
||||||
RemoveDeskbarIcon();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
MailDaemonApp::RunChains(BList& list, BMessage* msg)
|
|
||||||
{
|
|
||||||
BMailChain* chain;
|
|
||||||
|
|
||||||
int32 index = 0, id;
|
|
||||||
for (; msg->FindInt32("chain", index, &id) == B_OK; index++) {
|
|
||||||
for (int32 i = 0; i < list.CountItems(); i++) {
|
|
||||||
chain = (BMailChain*)list.ItemAt(i);
|
|
||||||
|
|
||||||
if (chain->ID() == (unsigned)id) {
|
|
||||||
chain->RunChain(sStatus, true, false, true);
|
|
||||||
list.RemoveItem(i); // the chain runner deletes the chain
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index == 0) {
|
|
||||||
// invoke all chains
|
|
||||||
for (int32 i = 0; i < list.CountItems(); i++) {
|
|
||||||
chain = (BMailChain*)list.ItemAt(i);
|
|
||||||
|
|
||||||
chain->RunChain(sStatus, true, false, true);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// delete unused chains
|
|
||||||
for (int32 i = list.CountItems(); i-- > 0;)
|
|
||||||
delete (BMailChain*)list.RemoveItem(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
MailDaemonApp::GetNewMessages(BMessage* msg)
|
|
||||||
{
|
|
||||||
BList list;
|
|
||||||
GetInboundMailChains(&list);
|
|
||||||
|
|
||||||
RunChains(list, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
MailDaemonApp::SendPendingMessages(BMessage* msg)
|
|
||||||
{
|
|
||||||
BVolumeRoster roster;
|
|
||||||
BVolume volume;
|
|
||||||
|
|
||||||
while (roster.GetNextVolume(&volume) == B_OK) {
|
|
||||||
BQuery query;
|
|
||||||
query.SetVolume(&volume);
|
|
||||||
query.PushAttr(B_MAIL_ATTR_FLAGS);
|
|
||||||
query.PushInt32(B_MAIL_PENDING);
|
|
||||||
query.PushOp(B_EQ);
|
|
||||||
|
|
||||||
query.PushAttr(B_MAIL_ATTR_FLAGS);
|
|
||||||
query.PushInt32(B_MAIL_PENDING | B_MAIL_SAVE);
|
|
||||||
query.PushOp(B_EQ);
|
|
||||||
|
|
||||||
query.PushOp(B_OR);
|
|
||||||
|
|
||||||
int32 chainID = -1;
|
|
||||||
|
|
||||||
if (msg->FindInt32("chain", &chainID) == B_OK) {
|
|
||||||
query.PushAttr("MAIL:chain");
|
|
||||||
query.PushInt32(chainID);
|
|
||||||
query.PushOp(B_EQ);
|
|
||||||
query.PushOp(B_AND);
|
|
||||||
} else
|
|
||||||
chainID = -1;
|
|
||||||
|
|
||||||
if (!msg->HasString("message_path")) {
|
|
||||||
if (chainID == -1) {
|
|
||||||
map<int32, snuzzwut*> messages;
|
|
||||||
|
|
||||||
query.Fetch();
|
|
||||||
BEntry entry;
|
|
||||||
BPath path;
|
|
||||||
BNode node;
|
|
||||||
int32 chain;
|
|
||||||
int32 defaultChain(BMailSettings().DefaultOutboundChainID());
|
|
||||||
off_t size;
|
|
||||||
|
|
||||||
while (query.GetNextEntry(&entry) == B_OK) {
|
|
||||||
if (_IsEntryInTrash(entry))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
while (node.SetTo(&entry) == B_BUSY)
|
|
||||||
snooze(1000);
|
|
||||||
if (!_IsPending(node))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (node.ReadAttr("MAIL:chain", B_INT32_TYPE, 0, &chain, 4)
|
|
||||||
< B_OK)
|
|
||||||
chain = defaultChain;
|
|
||||||
entry.GetPath(&path);
|
|
||||||
node.GetSize(&size);
|
|
||||||
if (messages[chain] == NULL) {
|
|
||||||
messages[chain] = new snuzzwut;
|
|
||||||
messages[chain]->bytes = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
messages[chain]->msgs += path.Path();
|
|
||||||
messages[chain]->bytes += size;
|
|
||||||
}
|
|
||||||
|
|
||||||
map<int32, snuzzwut*>::iterator iter = messages.begin();
|
|
||||||
map<int32, snuzzwut*>::iterator end = messages.end();
|
|
||||||
while (iter != end) {
|
|
||||||
if (iter->first > 0 && BMailChain(iter->first)
|
|
||||||
.ChainDirection() == outbound) {
|
|
||||||
BMailChainRunner* runner
|
|
||||||
= GetMailChainRunner(iter->first, sStatus);
|
|
||||||
runner->GetMessages(&messages[iter->first]->msgs,
|
|
||||||
messages[iter->first]->bytes);
|
|
||||||
delete messages[iter->first];
|
|
||||||
runner->Stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
iter++;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
BStringList ids;
|
|
||||||
size_t bytes = 0;
|
|
||||||
|
|
||||||
query.Fetch();
|
|
||||||
BEntry entry;
|
|
||||||
BPath path;
|
|
||||||
BNode node;
|
|
||||||
off_t size;
|
|
||||||
|
|
||||||
while (query.GetNextEntry(&entry) == B_OK) {
|
|
||||||
if (_IsEntryInTrash(entry))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
node.SetTo(&entry);
|
|
||||||
if (!_IsPending(node))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
entry.GetPath(&path);
|
|
||||||
node.GetSize(&size);
|
|
||||||
ids += path.Path();
|
|
||||||
bytes += size;
|
|
||||||
}
|
|
||||||
|
|
||||||
BMailChainRunner* runner
|
|
||||||
= GetMailChainRunner(chainID, sStatus);
|
|
||||||
runner->GetMessages(&ids, bytes);
|
|
||||||
runner->Stop();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const char* path;
|
|
||||||
if (msg->FindString("message_path", &path) != B_OK)
|
|
||||||
return;
|
|
||||||
|
|
||||||
off_t size;
|
|
||||||
if (BNode(path).GetSize(&size) != B_OK)
|
|
||||||
return;
|
|
||||||
|
|
||||||
BStringList ids;
|
|
||||||
ids += path;
|
|
||||||
|
|
||||||
BMailChainRunner* runner = GetMailChainRunner(chainID, sStatus);
|
|
||||||
runner->GetMessages(&ids, size);
|
|
||||||
runner->Stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
MailDaemonApp::Pulse()
|
|
||||||
{
|
|
||||||
bigtime_t idle = idle_time();
|
|
||||||
if (fLEDAnimation->IsRunning() && idle < 100000)
|
|
||||||
fLEDAnimation->Stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*! Work-around for a broken index that contains out-of-date information.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* static */
|
|
||||||
bool
|
|
||||||
MailDaemonApp::_IsPending(BNode& node)
|
|
||||||
{
|
|
||||||
int32 flags;
|
|
||||||
if (node.ReadAttr(B_MAIL_ATTR_FLAGS, B_INT32_TYPE, 0, &flags, sizeof(int32))
|
|
||||||
!= (ssize_t)sizeof(int32))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return (flags & B_MAIL_PENDING) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* static */
|
|
||||||
bool
|
|
||||||
MailDaemonApp::_IsEntryInTrash(BEntry& entry)
|
|
||||||
{
|
|
||||||
entry_ref ref;
|
|
||||||
entry.GetRef(&ref);
|
|
||||||
|
|
||||||
BVolume volume(ref.device);
|
|
||||||
BPath path;
|
|
||||||
if (volume.InitCheck() != B_OK
|
|
||||||
|| find_directory(B_TRASH_DIRECTORY, &path, false, &volume) != B_OK)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
BDirectory trash(path.Path());
|
|
||||||
return trash.Contains(&entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
makeIndices()
|
|
||||||
{
|
|
||||||
const char* stringIndices[] = {
|
|
||||||
B_MAIL_ATTR_ACCOUNT, B_MAIL_ATTR_CC, B_MAIL_ATTR_FROM, B_MAIL_ATTR_NAME,
|
|
||||||
B_MAIL_ATTR_PRIORITY, B_MAIL_ATTR_REPLY, B_MAIL_ATTR_STATUS,
|
|
||||||
B_MAIL_ATTR_SUBJECT, B_MAIL_ATTR_TO, B_MAIL_ATTR_THREAD,
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
// add mail indices for all devices capable of querying
|
|
||||||
|
|
||||||
int32 cookie = 0;
|
|
||||||
dev_t device;
|
|
||||||
while ((device = next_dev(&cookie)) >= B_OK) {
|
|
||||||
fs_info info;
|
|
||||||
if (fs_stat_dev(device, &info) < 0
|
|
||||||
|| (info.flags & B_FS_HAS_QUERY) == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
for (int32 i = 0; stringIndices[i]; i++)
|
|
||||||
fs_create_index(device, stringIndices[i], B_STRING_TYPE, 0);
|
|
||||||
|
|
||||||
fs_create_index(device, "MAIL:draft", B_INT32_TYPE, 0);
|
|
||||||
fs_create_index(device, B_MAIL_ATTR_WHEN, B_INT32_TYPE, 0);
|
|
||||||
fs_create_index(device, B_MAIL_ATTR_FLAGS, B_INT32_TYPE, 0);
|
|
||||||
fs_create_index(device, "MAIL:chain", B_INT32_TYPE, 0);
|
|
||||||
fs_create_index(device, "MAIL:pending_chain", B_INT32_TYPE, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
addAttribute(BMessage& msg, const char* name, const char* publicName,
|
|
||||||
int32 type = B_STRING_TYPE, bool viewable = true, bool editable = false,
|
|
||||||
int32 width = 200)
|
|
||||||
{
|
|
||||||
msg.AddString("attr:name", name);
|
|
||||||
msg.AddString("attr:public_name", publicName);
|
|
||||||
msg.AddInt32("attr:type", type);
|
|
||||||
msg.AddBool("attr:viewable", viewable);
|
|
||||||
msg.AddBool("attr:editable", editable);
|
|
||||||
msg.AddInt32("attr:width", width);
|
|
||||||
msg.AddInt32("attr:alignment", B_ALIGN_LEFT);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
makeMimeType(bool remakeMIMETypes)
|
|
||||||
{
|
|
||||||
// Add MIME database entries for the e-mail file types we handle. Either
|
|
||||||
// do a full rebuild from nothing, or just add on the new attributes that
|
|
||||||
// we support which the regular BeOS mail daemon didn't have.
|
|
||||||
|
|
||||||
const char* types[2] = {"text/x-email", "text/x-partial-email"};
|
|
||||||
BMimeType mime;
|
|
||||||
BMessage info;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < sizeof(types) / sizeof(types[0]); i++) {
|
|
||||||
info.MakeEmpty();
|
|
||||||
mime.SetTo(types[i]);
|
|
||||||
if (mime.InitCheck() != B_OK) {
|
|
||||||
fputs("could not init mime type.\n", stderr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!mime.IsInstalled() || remakeMIMETypes) {
|
|
||||||
// install the full mime type
|
|
||||||
mime.Delete ();
|
|
||||||
mime.Install();
|
|
||||||
|
|
||||||
// Set up the list of e-mail related attributes that Tracker will
|
|
||||||
// let you display in columns for e-mail messages.
|
|
||||||
addAttribute(info, B_MAIL_ATTR_NAME, "Name");
|
|
||||||
addAttribute(info, B_MAIL_ATTR_SUBJECT, "Subject");
|
|
||||||
addAttribute(info, B_MAIL_ATTR_TO, "To");
|
|
||||||
addAttribute(info, B_MAIL_ATTR_CC, "Cc");
|
|
||||||
addAttribute(info, B_MAIL_ATTR_FROM, "From");
|
|
||||||
addAttribute(info, B_MAIL_ATTR_REPLY, "Reply To");
|
|
||||||
addAttribute(info, B_MAIL_ATTR_STATUS, "Status");
|
|
||||||
addAttribute(info, B_MAIL_ATTR_PRIORITY, "Priority", B_STRING_TYPE,
|
|
||||||
true, true, 40);
|
|
||||||
addAttribute(info, B_MAIL_ATTR_WHEN, "When", B_TIME_TYPE, true,
|
|
||||||
false, 150);
|
|
||||||
addAttribute(info, B_MAIL_ATTR_THREAD, "Thread");
|
|
||||||
addAttribute(info, B_MAIL_ATTR_ACCOUNT, "Account", B_STRING_TYPE,
|
|
||||||
true, false, 100);
|
|
||||||
mime.SetAttrInfo(&info);
|
|
||||||
|
|
||||||
if (i == 0) {
|
|
||||||
mime.SetShortDescription("E-mail");
|
|
||||||
mime.SetLongDescription("Electronic Mail Message");
|
|
||||||
mime.SetPreferredApp("application/x-vnd.Be-MAIL");
|
|
||||||
} else {
|
|
||||||
mime.SetShortDescription("Partial E-mail");
|
|
||||||
mime.SetLongDescription("A Partially Downloaded E-mail");
|
|
||||||
mime.SetPreferredApp("application/x-vnd.Be-POST");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Just add the e-mail related attribute types we use to the MIME
|
|
||||||
// system.
|
|
||||||
mime.GetAttrInfo(&info);
|
|
||||||
bool hasAccount = false;
|
|
||||||
bool hasThread = false;
|
|
||||||
bool hasSize = false;
|
|
||||||
const char* result;
|
|
||||||
for (int32 index = 0; info.FindString("attr:name", index, &result)
|
|
||||||
== B_OK; index++) {
|
|
||||||
if (!strcmp(result, B_MAIL_ATTR_ACCOUNT))
|
|
||||||
hasAccount = true;
|
|
||||||
if (!strcmp(result, B_MAIL_ATTR_THREAD))
|
|
||||||
hasThread = true;
|
|
||||||
if (!strcmp(result, "MAIL:fullsize"))
|
|
||||||
hasSize = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!hasAccount) {
|
|
||||||
addAttribute(info, B_MAIL_ATTR_ACCOUNT, "Account",
|
|
||||||
B_STRING_TYPE, true, false, 100);
|
|
||||||
}
|
|
||||||
if (!hasThread)
|
|
||||||
addAttribute(info, B_MAIL_ATTR_THREAD, "Thread");
|
|
||||||
/*if (!hasSize)
|
|
||||||
addAttribute(info,"MAIL:fullsize","Message Size",B_SIZE_T_TYPE,true,false,100);*/
|
|
||||||
// TODO: Tracker can't display SIZT attributes. What a pain.
|
|
||||||
if (!hasAccount || !hasThread/* || !hasSize*/)
|
|
||||||
mime.SetAttrInfo(&info);
|
|
||||||
}
|
|
||||||
mime.Unset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
@@ -799,15 +25,8 @@ main(int argc, const char** argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
MailDaemonApp app;
|
MailDaemonApp app;
|
||||||
|
if (remakeMIMETypes)
|
||||||
// install MimeTypes, attributes, indices, and the
|
app.MakeMimeTypes(true);
|
||||||
// system beep add startup
|
app.Run();
|
||||||
|
|
||||||
makeMimeType(remakeMIMETypes);
|
|
||||||
makeIndices();
|
|
||||||
add_system_beep_event("New E-mail");
|
|
||||||
|
|
||||||
be_app->Run();
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user