Imported MDR. Some code still not entirely functional -- I haven't been able to figure out how to detect SSL, so IMAP and POP have it turned off. PPP auto-detect is also not functional at the moment. Other than that, it seems to work beautifully. Packaging will come later.
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@9016 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -2,6 +2,7 @@ SubDir OBOS_TOP src servers ;
|
||||
|
||||
SubInclude OBOS_TOP src servers app ;
|
||||
SubInclude OBOS_TOP src servers input ;
|
||||
SubInclude OBOS_TOP src servers mail ;
|
||||
SubInclude OBOS_TOP src servers media ;
|
||||
SubInclude OBOS_TOP src servers media_addon ;
|
||||
SubInclude OBOS_TOP src servers midi ;
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
SubDir OBOS_TOP src servers mail ;
|
||||
|
||||
UsePrivateHeaders mail ;
|
||||
|
||||
SubDirHdrs [ FDirName $(OBOS_TOP) headers os add-ons mail_daemon ] ;
|
||||
|
||||
AddResources E-mail : <$(SOURCE_GRIST)>mail_daemon.rsrc ;
|
||||
|
||||
Server mail_daemon :
|
||||
deskbarview.cpp
|
||||
LEDAnimation.cpp
|
||||
main.cpp
|
||||
;
|
||||
|
||||
LinkSharedOSLibs mail_daemon :
|
||||
be
|
||||
mail
|
||||
tracker
|
||||
stdc++.r4
|
||||
;
|
||||
@@ -0,0 +1,100 @@
|
||||
#include "LEDAnimation.h"
|
||||
|
||||
#include <InterfaceDefs.h>
|
||||
|
||||
#define SNOOZE_TIME 150000
|
||||
#include <stdio.h>
|
||||
|
||||
/***********************************************************
|
||||
* Constructor
|
||||
***********************************************************/
|
||||
LEDAnimation::LEDAnimation()
|
||||
:fThread(-1)
|
||||
,fRunning(false)
|
||||
,fOrigModifiers(::modifiers())
|
||||
{
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
* Destructor
|
||||
***********************************************************/
|
||||
LEDAnimation::~LEDAnimation()
|
||||
{
|
||||
Stop();
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
* Start
|
||||
***********************************************************/
|
||||
void
|
||||
LEDAnimation::Start()
|
||||
{
|
||||
// don't do anything if the thread is already running
|
||||
if (fThread >= 0)
|
||||
return;
|
||||
|
||||
fOrigModifiers = ::modifiers();
|
||||
::set_keyboard_locks(0);
|
||||
fRunning = true;
|
||||
fThread = ::spawn_thread(AnimationThread,"LED thread",B_NORMAL_PRIORITY,this);
|
||||
::resume_thread(fThread);
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
* Stop
|
||||
***********************************************************/
|
||||
void
|
||||
LEDAnimation::Stop()
|
||||
{
|
||||
// don't do anything if the thread doesn't run
|
||||
if (fThread < 0)
|
||||
return;
|
||||
|
||||
fRunning = false;
|
||||
status_t result;
|
||||
::wait_for_thread(fThread,&result);
|
||||
|
||||
::set_keyboard_locks(fOrigModifiers);
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
* AnimationThread
|
||||
***********************************************************/
|
||||
int32
|
||||
LEDAnimation::AnimationThread(void* data)
|
||||
{
|
||||
LEDAnimation *anim = (LEDAnimation*)data;
|
||||
|
||||
while (anim->fRunning)
|
||||
{
|
||||
LED(B_NUM_LOCK,true);
|
||||
LED(B_NUM_LOCK,false);
|
||||
|
||||
LED(B_CAPS_LOCK,true);
|
||||
LED(B_CAPS_LOCK,false);
|
||||
|
||||
LED(B_SCROLL_LOCK,true);
|
||||
LED(B_SCROLL_LOCK,false);
|
||||
|
||||
LED(B_CAPS_LOCK,true);
|
||||
LED(B_CAPS_LOCK,false);
|
||||
}
|
||||
anim->fThread = -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
* LED
|
||||
***********************************************************/
|
||||
void
|
||||
LEDAnimation::LED(uint32 mod,bool on)
|
||||
{
|
||||
uint32 current_modifiers = ::modifiers();
|
||||
if(on)
|
||||
current_modifiers |= mod;
|
||||
else
|
||||
current_modifiers &= ~mod;
|
||||
::set_keyboard_locks(current_modifiers);
|
||||
if(on)
|
||||
::snooze(SNOOZE_TIME);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
#ifndef __LEDANIMATION_H__
|
||||
#define __LEDANIMATION_H__
|
||||
|
||||
//! Keyboard LED Animation class.
|
||||
|
||||
#include <SupportDefs.h>
|
||||
#include <OS.h>
|
||||
|
||||
class LEDAnimation {
|
||||
public:
|
||||
//! Constructor
|
||||
LEDAnimation();
|
||||
//! Destructor
|
||||
~LEDAnimation();
|
||||
//!Start LED animation.
|
||||
void Start();
|
||||
//!Stop LED animation.
|
||||
void Stop();
|
||||
//! Check animation thread is running.
|
||||
bool IsRunning() const {return fRunning;}
|
||||
private:
|
||||
//!Anination thread.
|
||||
static int32 AnimationThread(void *data);
|
||||
//!Set LED on or off.
|
||||
static void LED(uint32 mod/*!Modifier key*/,bool on/*!If LED on, value is true*/);
|
||||
//!Animation thread ID.
|
||||
thread_id fThread;
|
||||
//!Thread running flag.
|
||||
volatile bool fRunning;
|
||||
uint32 fOrigModifiers;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
Open Tracker License
|
||||
|
||||
Terms and Conditions
|
||||
|
||||
Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice applies to all licensees
|
||||
and shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the name of Be Incorporated shall not be
|
||||
used in advertising or otherwise to promote the sale, use or other dealings in
|
||||
this Software without prior written authorization from Be Incorporated.
|
||||
|
||||
Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks
|
||||
of Be Incorporated in the United States and other countries. Other brand product
|
||||
names are registered trademarks or trademarks of their respective holders.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
// NavMenu is a hierarchical menu of volumes, folders, files and queries
|
||||
// displays icons, uses the SlowMenu API for full interruptability
|
||||
|
||||
#ifndef NAV_MENU_H
|
||||
#define NAV_MENU_H
|
||||
|
||||
|
||||
#include <Messenger.h>
|
||||
#include <StorageDefs.h>
|
||||
#include <Entry.h>
|
||||
|
||||
#include "SlowMenu.h"
|
||||
|
||||
template<class T> class BObjectList;
|
||||
class BMenuItem;
|
||||
|
||||
namespace BPrivate {
|
||||
|
||||
class Model;
|
||||
class BContainerWindow;
|
||||
class ModelMenuItem;
|
||||
class EntryListBase;
|
||||
|
||||
|
||||
class TrackingHookData {
|
||||
public:
|
||||
TrackingHookData()
|
||||
: fTrackingHook(NULL),
|
||||
fDragMessage(NULL)
|
||||
{}
|
||||
|
||||
bool (*fTrackingHook)(BMenu *, void *);
|
||||
BMessenger fTarget;
|
||||
const BMessage *fDragMessage;
|
||||
};
|
||||
|
||||
|
||||
class BNavMenu : public BSlowMenu {
|
||||
|
||||
public:
|
||||
BNavMenu(const char* title, uint32 message, const BHandler *,
|
||||
BWindow *parentWindow = NULL, const BObjectList<BString> *list = NULL);
|
||||
BNavMenu(const char* title, uint32 message, const BMessenger &,
|
||||
BWindow *parentWindow = NULL, const BObjectList<BString> *list = NULL);
|
||||
// parentWindow, if specified, will be closed if nav menu item invoked
|
||||
// with option held down
|
||||
|
||||
virtual ~BNavMenu();
|
||||
|
||||
virtual void AttachedToWindow();
|
||||
virtual void DetachedFromWindow();
|
||||
|
||||
void SetNavDir(const entry_ref *);
|
||||
void ForceRebuild();
|
||||
bool NeedsToRebuild() const;
|
||||
// will cause menu to get rebuilt next time it is shown
|
||||
|
||||
virtual void ResetTargets();
|
||||
void SetTarget(const BMessenger &);
|
||||
BMessenger Target();
|
||||
|
||||
void SetTypesList(const BObjectList<BString> *list);
|
||||
const BObjectList<BString> *TypesList() const;
|
||||
|
||||
void AddNavDir(const Model *mode, uint32 what, BHandler *target,
|
||||
bool populateSubmenu);
|
||||
|
||||
static int32 GetMaxMenuWidth();
|
||||
|
||||
static int CompareFolderNamesFirstOne(const BMenuItem *, const BMenuItem *);
|
||||
static int CompareOne(const BMenuItem *, const BMenuItem *);
|
||||
|
||||
static ModelMenuItem *NewModelItem(Model *, const BMessage *, const BMessenger &,
|
||||
bool suppressFolderHierarchy=false, BContainerWindow * = NULL,
|
||||
const BObjectList<BString> *typeslist = NULL,
|
||||
TrackingHookData *hook = NULL);
|
||||
|
||||
TrackingHookData *InitTrackingHook(bool (*hookfunction)(BMenu *, void *),
|
||||
const BMessenger *target, const BMessage *dragMessage);
|
||||
|
||||
protected:
|
||||
virtual bool StartBuildingItemList();
|
||||
virtual bool AddNextItem();
|
||||
virtual void DoneBuildingItemList();
|
||||
virtual void ClearMenuBuildingState();
|
||||
|
||||
void BuildVolumeMenu();
|
||||
|
||||
void AddOneItem(Model *);
|
||||
void AddRootItemsIfNeeded();
|
||||
static void SetTrackingHookDeep(BMenu *, bool (*)(BMenu *, void *), void *);
|
||||
|
||||
entry_ref fNavDir;
|
||||
BMessage fMessage;
|
||||
BMessenger fMessenger;
|
||||
BWindow *fParentWindow;
|
||||
|
||||
// menu building state
|
||||
bool fVolsOnly;
|
||||
BObjectList<BMenuItem> *fItemList;
|
||||
EntryListBase *fContainer;
|
||||
bool fIteratingDesktop;
|
||||
|
||||
const BObjectList<BString> *fTypesList;
|
||||
|
||||
TrackingHookData fTrackingHook;
|
||||
};
|
||||
|
||||
// Spring Loaded Folder convenience routines
|
||||
// used in both Tracker and Deskbar
|
||||
#if B_BEOS_VERSION_DANO
|
||||
#define _IMPEXP_TRACKER
|
||||
#endif
|
||||
_IMPEXP_TRACKER bool SpringLoadedFolderCompareMessages(const BMessage *incoming,
|
||||
const BMessage *dragmessage);
|
||||
_IMPEXP_TRACKER void SpringLoadedFolderSetMenuStates(const BMenu *menu,
|
||||
const BObjectList<BString> *typeslist);
|
||||
_IMPEXP_TRACKER void SpringLoadedFolderAddUniqueTypeToList(entry_ref *ref,
|
||||
BObjectList<BString> *typeslist);
|
||||
_IMPEXP_TRACKER void SpringLoadedFolderCacheDragData(const BMessage *incoming,
|
||||
BMessage **, BObjectList<BString> **typeslist);
|
||||
#if B_BEOS_VERSION_DANO
|
||||
#undef _IMPEXP_TRACKER
|
||||
#endif
|
||||
|
||||
} // namespace BPrivate
|
||||
|
||||
using namespace BPrivate;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
Open Tracker License
|
||||
|
||||
Terms and Conditions
|
||||
|
||||
Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice applies to all licensees
|
||||
and shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the name of Be Incorporated shall not be
|
||||
used in advertising or otherwise to promote the sale, use or other dealings in
|
||||
this Software without prior written authorization from Be Incorporated.
|
||||
|
||||
Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks
|
||||
of Be Incorporated in the United States and other countries. Other brand product
|
||||
names are registered trademarks or trademarks of their respective holders.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __SLOW_MENU__
|
||||
#define __SLOW_MENU__
|
||||
|
||||
#include <Menu.h>
|
||||
#include <MenuItem.h>
|
||||
#include <Debug.h>
|
||||
|
||||
// SlowMenu is a convenience class that makes it easier to
|
||||
// use the AddDynamicItem callback to implement a menu that can
|
||||
// checks periodically between creating new items and quits
|
||||
// early if needed
|
||||
|
||||
namespace BPrivate {
|
||||
|
||||
class BSlowMenu : public BMenu {
|
||||
public:
|
||||
BSlowMenu(const char *title, menu_layout layout = B_ITEMS_IN_COLUMN);
|
||||
|
||||
protected:
|
||||
virtual bool StartBuildingItemList();
|
||||
// set up state to start building the item list
|
||||
// returns false if setup failed
|
||||
virtual bool AddNextItem() = 0;
|
||||
// returns false if done
|
||||
virtual void DoneBuildingItemList() = 0;
|
||||
// default version adds items from itemList to menu and deletes
|
||||
// the list; override to sort items first, etc.
|
||||
|
||||
virtual void ClearMenuBuildingState() = 0;
|
||||
|
||||
protected:
|
||||
virtual bool AddDynamicItem(add_state state);
|
||||
// this is the callback from BMenu, you shouldn't need to override this
|
||||
|
||||
bool fMenuBuilt;
|
||||
};
|
||||
|
||||
} // namespace BPrivate
|
||||
|
||||
using namespace BPrivate;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,560 @@
|
||||
/* DeskbarView - main_daemon's deskbar menu and view
|
||||
**
|
||||
** Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved.
|
||||
*/
|
||||
|
||||
|
||||
#include <PopUpMenu.h>
|
||||
#include <Bitmap.h>
|
||||
#include <Rect.h>
|
||||
#include <MenuItem.h>
|
||||
#include <Window.h>
|
||||
#include <Messenger.h>
|
||||
#include <Roster.h>
|
||||
#include <Resources.h>
|
||||
#include <Entry.h>
|
||||
#include <Path.h>
|
||||
#include <NodeMonitor.h>
|
||||
#include <VolumeRoster.h>
|
||||
#include <Directory.h>
|
||||
#include <FindDirectory.h>
|
||||
#include <Query.h>
|
||||
#include <SymLink.h>
|
||||
#include <NodeInfo.h>
|
||||
#include <kernel/fs_info.h>
|
||||
#include <kernel/fs_index.h>
|
||||
#include <Deskbar.h>
|
||||
#include <String.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <malloc.h>
|
||||
|
||||
#include <E-mail.h>
|
||||
#include <MailSettings.h>
|
||||
#include <MailDaemon.h>
|
||||
|
||||
#include <MDRLanguage.h>
|
||||
|
||||
#include "deskbarview.h"
|
||||
|
||||
const char *kTrackerSignature = "application/x-vnd.Be-TRAK";
|
||||
|
||||
|
||||
//-----The following #defines get around a bug in get_image_info on ppc---
|
||||
#if __INTEL__
|
||||
#define text_part text
|
||||
#define text_part_size text_size
|
||||
#else
|
||||
#define text_part data
|
||||
#define text_part_size data_size
|
||||
#endif
|
||||
|
||||
extern "C" _EXPORT BView* instantiate_deskbar_item();
|
||||
|
||||
|
||||
status_t our_image(image_info* image)
|
||||
{
|
||||
int32 cookie = 0;
|
||||
status_t ret;
|
||||
while ((ret = get_next_image_info(0,&cookie,image)) == B_OK)
|
||||
{
|
||||
if ((char*)our_image >= (char*)image->text_part &&
|
||||
(char*)our_image <= (char*)image->text_part + image->text_part_size)
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
BView* instantiate_deskbar_item(void)
|
||||
{
|
||||
return new DeskbarView(BRect(0, 0, 15, 15));
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
DeskbarView::DeskbarView(BRect frame)
|
||||
: BView(frame, "mail_daemon", B_FOLLOW_NONE, B_WILL_DRAW | B_PULSE_NEEDED)
|
||||
, fIcon(NULL)
|
||||
, fCurrentIconState(NEW_MAIL)
|
||||
{
|
||||
}
|
||||
|
||||
DeskbarView::DeskbarView(BMessage *message)
|
||||
: BView(message)
|
||||
, fIcon(NULL)
|
||||
, fCurrentIconState(NEW_MAIL)
|
||||
{
|
||||
ChangeIcon(NO_MAIL);
|
||||
}
|
||||
|
||||
DeskbarView::~DeskbarView()
|
||||
{
|
||||
delete fIcon;
|
||||
for (int32 i = 0; i < fNewMailQueries.CountItems(); i++)
|
||||
delete ((BQuery *)(fNewMailQueries.ItemAt(i)));
|
||||
}
|
||||
|
||||
void DeskbarView::AttachedToWindow()
|
||||
{
|
||||
if (be_roster->IsRunning("application/x-vnd.Be-POST"))
|
||||
{
|
||||
BVolumeRoster volumes;
|
||||
BVolume volume;
|
||||
fNewMessages = 0;
|
||||
|
||||
while (volumes.GetNextVolume(&volume) == B_OK) {
|
||||
BQuery *fNewMailQuery = new BQuery;
|
||||
|
||||
fNewMailQuery->SetTarget(this);
|
||||
fNewMailQuery->SetVolume(&volume);
|
||||
fNewMailQuery->PushAttr(B_MAIL_ATTR_STATUS);
|
||||
fNewMailQuery->PushString("New");
|
||||
fNewMailQuery->PushOp(B_EQ);
|
||||
fNewMailQuery->PushAttr("BEOS:TYPE");
|
||||
fNewMailQuery->PushString("text/x-email");
|
||||
fNewMailQuery->PushOp(B_EQ);
|
||||
fNewMailQuery->PushAttr("BEOS:TYPE");
|
||||
fNewMailQuery->PushString("text/x-partial-email");
|
||||
fNewMailQuery->PushOp(B_EQ);
|
||||
fNewMailQuery->PushOp(B_OR);
|
||||
fNewMailQuery->PushOp(B_AND);
|
||||
fNewMailQuery->Fetch();
|
||||
|
||||
BEntry entry;
|
||||
while (fNewMailQuery->GetNextEntry(&entry) == B_OK)
|
||||
if (entry.InitCheck() == B_OK)
|
||||
fNewMessages++;
|
||||
|
||||
fNewMailQueries.AddItem(fNewMailQuery);
|
||||
}
|
||||
|
||||
ChangeIcon((fNewMessages > 0) ? NEW_MAIL : NO_MAIL);
|
||||
}
|
||||
else
|
||||
{
|
||||
BDeskbar deskbar;
|
||||
deskbar.RemoveItem("mail_daemon");
|
||||
}
|
||||
}
|
||||
|
||||
DeskbarView* DeskbarView::Instantiate(BMessage *data)
|
||||
{
|
||||
if (!validate_instantiation(data, "DeskbarView"))
|
||||
return NULL;
|
||||
|
||||
return new DeskbarView(data);
|
||||
}
|
||||
|
||||
status_t DeskbarView::Archive(BMessage *data,bool deep) const
|
||||
{
|
||||
BView::Archive(data, deep);
|
||||
|
||||
data->AddString("add_on", "application/x-vnd.Be-POST");
|
||||
return B_NO_ERROR;
|
||||
}
|
||||
|
||||
void DeskbarView::Draw(BRect /*updateRect*/)
|
||||
{
|
||||
PushState();
|
||||
|
||||
SetHighColor(Parent()->ViewColor());
|
||||
FillRect(BRect(0.0,0.0,15.0,15.0));
|
||||
if(fIcon)
|
||||
{
|
||||
SetDrawingMode(B_OP_OVER);
|
||||
DrawBitmap(fIcon,BRect(0.0,0.0,15.0,15.0));
|
||||
}
|
||||
|
||||
PopState();
|
||||
Sync();
|
||||
}
|
||||
|
||||
status_t OpenFolder(const char* end)
|
||||
{
|
||||
BPath path;
|
||||
find_directory(B_USER_DIRECTORY, &path);
|
||||
path.Append(end);
|
||||
|
||||
entry_ref ref;
|
||||
if (get_ref_for_path(path.Path(),&ref) != B_OK) return B_NAME_NOT_FOUND;
|
||||
if (!BEntry(&ref).Exists()) return B_NAME_NOT_FOUND;
|
||||
|
||||
|
||||
BMessage open_mbox(B_REFS_RECEIVED);
|
||||
open_mbox.AddRef("refs",&ref);
|
||||
|
||||
BMessenger tracker("application/x-vnd.Be-TRAK");
|
||||
tracker.SendMessage(&open_mbox);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DeskbarView::MessageReceived(BMessage *message)
|
||||
{
|
||||
switch(message->what)
|
||||
{
|
||||
case MD_CHECK_SEND_NOW:
|
||||
// also happens in DeskbarView::MouseUp() with
|
||||
// B_TERTIARY_MOUSE_BUTTON pressed
|
||||
BMailDaemon::CheckMail(true);
|
||||
break;
|
||||
case MD_CHECK_FOR_MAILS:
|
||||
BMailDaemon::CheckMail(false,message->FindString("account"));
|
||||
break;
|
||||
case MD_SEND_MAILS:
|
||||
BMailDaemon::SendQueuedMail();
|
||||
break;
|
||||
|
||||
case MD_OPEN_NEW:
|
||||
{
|
||||
char *argv[] = {"New Message", "mailto:"};
|
||||
be_roster->Launch("text/x-email",2,argv);
|
||||
break;
|
||||
}
|
||||
case MD_OPEN_PREFS:
|
||||
be_roster->Launch("application/x-vnd.Be-mprf");
|
||||
break;
|
||||
|
||||
case B_QUERY_UPDATE:
|
||||
{
|
||||
int32 what;
|
||||
message->FindInt32("opcode",&what);
|
||||
switch (what) {
|
||||
case B_ENTRY_CREATED:
|
||||
fNewMessages++;
|
||||
break;
|
||||
case B_ENTRY_REMOVED:
|
||||
fNewMessages--;
|
||||
break;
|
||||
}
|
||||
ChangeIcon((fNewMessages > 0) ? NEW_MAIL : NO_MAIL);
|
||||
break;
|
||||
}
|
||||
case B_QUIT_REQUESTED:
|
||||
BMailDaemon::Quit();
|
||||
break;
|
||||
|
||||
case B_REFS_RECEIVED: // open received files in the standard mail application
|
||||
{
|
||||
BMessage argv(B_ARGV_RECEIVED);
|
||||
argv.AddString("argv", "E-mail");
|
||||
|
||||
entry_ref ref;
|
||||
BPath path;
|
||||
int i = 0;
|
||||
|
||||
while (message->FindRef("refs",i++,&ref) == B_OK && path.SetTo(&ref) == B_OK)
|
||||
{
|
||||
//fprintf(stderr,"got %s\n", path.Path());
|
||||
argv.AddString("argv", path.Path());
|
||||
}
|
||||
|
||||
if (i > 1)
|
||||
{
|
||||
argv.AddInt32("argc", i);
|
||||
be_roster->Launch("text/x-email", &argv);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
BView::MessageReceived(message);
|
||||
}
|
||||
}
|
||||
|
||||
void DeskbarView::ChangeIcon(int32 icon)
|
||||
{
|
||||
if(fCurrentIconState == icon)
|
||||
return;
|
||||
|
||||
BBitmap *newIcon(NULL);
|
||||
|
||||
image_info info;
|
||||
if (our_image(&info) == B_OK)
|
||||
{
|
||||
BFile file(info.name,B_READ_ONLY);
|
||||
if (file.InitCheck() < B_OK)
|
||||
goto err;
|
||||
|
||||
BResources rsrc(&file);
|
||||
size_t len;
|
||||
const void *data = rsrc.LoadResource('BBMP',icon == NEW_MAIL ? "New" : "Read",&len);
|
||||
if (len == 0)
|
||||
goto err;
|
||||
|
||||
BMemoryIO stream(data, len);
|
||||
stream.Seek(0, SEEK_SET);
|
||||
BMessage archive;
|
||||
if (archive.Unflatten(&stream) != B_OK)
|
||||
goto err;
|
||||
newIcon = new BBitmap(&archive);
|
||||
}
|
||||
else
|
||||
fputs("no image!", stderr);
|
||||
|
||||
err:
|
||||
fCurrentIconState = icon;
|
||||
delete fIcon;
|
||||
fIcon = newIcon;
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
void DeskbarView::Pulse()
|
||||
{
|
||||
// Check if mail_daemon is still running
|
||||
}
|
||||
|
||||
void DeskbarView::MouseUp(BPoint pos)
|
||||
{
|
||||
if (fLastButtons & B_PRIMARY_MOUSE_BUTTON) {
|
||||
if (OpenFolder("mail/mailbox") != B_OK)
|
||||
if (OpenFolder("mail/in") != B_OK)
|
||||
if (OpenFolder("mail/INBOX") != B_OK)
|
||||
OpenFolder("mail");
|
||||
}
|
||||
|
||||
if (fLastButtons & B_TERTIARY_MOUSE_BUTTON)
|
||||
BMailDaemon::CheckMail(true);
|
||||
}
|
||||
|
||||
void DeskbarView::MouseDown(BPoint pos)
|
||||
{
|
||||
Looper()->CurrentMessage()->FindInt32("buttons",&fLastButtons);
|
||||
Looper()->CurrentMessage()->PrintToStream();
|
||||
|
||||
if (fLastButtons & B_SECONDARY_MOUSE_BUTTON)
|
||||
{
|
||||
ConvertToScreen(&pos);
|
||||
|
||||
BPopUpMenu *menu = BuildMenu();
|
||||
if (menu)
|
||||
menu->Go(pos,true,true,BRect(pos.x - 2, pos.y - 2, pos.x + 2, pos.y + 2),true);
|
||||
}
|
||||
}
|
||||
|
||||
bool DeskbarView::CreateMenuLinks(BDirectory &directory,BPath &path)
|
||||
{
|
||||
status_t status = directory.SetTo(path.Path());
|
||||
if (status == B_OK)
|
||||
return true;
|
||||
|
||||
// Check if the directory has to be created (and do it in this case,
|
||||
// filling it with some standard links). Normally the installer will
|
||||
// create the directory and fill it with links, so normally this doesn't
|
||||
// get used.
|
||||
|
||||
BEntry entry(path.Path());
|
||||
if (status != B_ENTRY_NOT_FOUND
|
||||
|| entry.GetParent(&directory) < B_OK
|
||||
|| directory.CreateDirectory(path.Leaf(), NULL) < B_OK
|
||||
|| directory.SetTo(path.Path()) < B_OK)
|
||||
return false;
|
||||
|
||||
BPath targetPath;
|
||||
find_directory(B_USER_DIRECTORY, &targetPath);
|
||||
targetPath.Append("mail/in");
|
||||
|
||||
directory.CreateSymLink("Open Inbox Folder",targetPath.Path(),NULL);
|
||||
targetPath.GetParent(&targetPath);
|
||||
directory.CreateSymLink("Open Mail Folder",targetPath.Path(),NULL);
|
||||
|
||||
// create the draft query
|
||||
|
||||
BFile file;
|
||||
if (directory.CreateFile("Open Draft",&file) < B_OK)
|
||||
return true;
|
||||
|
||||
BString string("MAIL:draft==1");
|
||||
file.WriteAttrString("_trk/qrystr",&string);
|
||||
string = "E-mail";
|
||||
file.WriteAttrString("_trk/qryinitmime", &string);
|
||||
BNodeInfo(&file).SetType("application/x-vnd.Be-query");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void DeskbarView::CreateNewMailQuery(BEntry &query)
|
||||
{
|
||||
BFile file(&query, B_READ_WRITE | B_CREATE_FILE);
|
||||
if(file.InitCheck() != B_OK)
|
||||
return;
|
||||
|
||||
BString string("((" B_MAIL_ATTR_STATUS "==\"[nN][eE][wW]\")&&((BEOS:TYPE==\"text/x-email\")||(BEOS:TYPE==\"text/x-partial-email\")))");
|
||||
file.WriteAttrString("_trk/qrystr",&string);
|
||||
string = "E-mail";
|
||||
file.WriteAttrString("_trk/qryinitmime", &string);
|
||||
BNodeInfo(&file).SetType("application/x-vnd.Be-query");
|
||||
}
|
||||
|
||||
|
||||
BPopUpMenu *
|
||||
DeskbarView::BuildMenu()
|
||||
{
|
||||
BPopUpMenu *menu = new BPopUpMenu(B_EMPTY_STRING,false,false);
|
||||
menu->SetFont(be_plain_font);
|
||||
|
||||
menu->AddItem(new BMenuItem(MDR_DIALECT_CHOICE (
|
||||
"Create New Message","N) 新規メッセージ作成")B_UTF8_ELLIPSIS,
|
||||
new BMessage(MD_OPEN_NEW)));
|
||||
menu->AddSeparatorItem();
|
||||
|
||||
BMessenger tracker(kTrackerSignature);
|
||||
BNavMenu *navMenu;
|
||||
BMenuItem *item;
|
||||
BMessage *msg;
|
||||
entry_ref ref;
|
||||
|
||||
BPath path;
|
||||
find_directory(B_USER_SETTINGS_DIRECTORY, &path);
|
||||
path.Append("Mail/Menu Links");
|
||||
|
||||
BDirectory directory;
|
||||
if (CreateMenuLinks(directory,path))
|
||||
{
|
||||
int32 count = 0;
|
||||
|
||||
while (directory.GetNextRef(&ref) == B_OK)
|
||||
{
|
||||
count++;
|
||||
|
||||
path.SetTo(&ref);
|
||||
// the true here dereferences the symlinks all the way :)
|
||||
BEntry entry(&ref, true);
|
||||
|
||||
// do we want to use the NavMenu, or just an ordinary BMenuItem?
|
||||
// we are using the NavMenu only for directories and queries
|
||||
bool useNavMenu = false;
|
||||
|
||||
if (entry.InitCheck() == B_OK)
|
||||
{
|
||||
if (entry.IsDirectory())
|
||||
useNavMenu = true;
|
||||
else if (entry.IsFile())
|
||||
{
|
||||
// Files should use the BMenuItem unless they are queries
|
||||
char mimeString[B_MIME_TYPE_LENGTH];
|
||||
BNode node(&entry);
|
||||
BNodeInfo info(&node);
|
||||
if (info.GetType(mimeString) == B_OK
|
||||
&& strcmp(mimeString, "application/x-vnd.Be-query") == 0)
|
||||
useNavMenu = true;
|
||||
}
|
||||
//clobber the existing ref only if the symlink derefernces completely,
|
||||
//otherwise we'll stick with what we have
|
||||
entry.GetRef(&ref);
|
||||
}
|
||||
|
||||
msg = new BMessage(B_REFS_RECEIVED);
|
||||
msg->AddRef("refs", &ref);
|
||||
|
||||
if (useNavMenu)
|
||||
{
|
||||
item = new BMenuItem(navMenu = new BNavMenu(path.Leaf(),B_REFS_RECEIVED,tracker), msg);
|
||||
navMenu->SetNavDir(&ref);
|
||||
}
|
||||
else
|
||||
item = new BMenuItem(path.Leaf(), msg);
|
||||
|
||||
menu->AddItem(item);
|
||||
if(entry.InitCheck() != B_OK)
|
||||
item->SetEnabled(false);
|
||||
}
|
||||
if (count > 0)
|
||||
menu->AddSeparatorItem();
|
||||
}
|
||||
|
||||
// The New E-mail query
|
||||
|
||||
if (fNewMessages > 0)
|
||||
{
|
||||
BString string;
|
||||
MDR_DIALECT_CHOICE (
|
||||
string << fNewMessages << " new message" << ((fNewMessages != 1) ? "s" : B_EMPTY_STRING),
|
||||
string << fNewMessages << " 通の未読メッセージ");
|
||||
|
||||
find_directory(B_USER_SETTINGS_DIRECTORY, &path);
|
||||
path.Append("Mail/New E-mail");
|
||||
|
||||
BEntry query(path.Path());
|
||||
if (!query.Exists())
|
||||
CreateNewMailQuery(query);
|
||||
query.GetRef(&ref);
|
||||
|
||||
item = new BMenuItem(
|
||||
navMenu = new BNavMenu(string.String(),B_REFS_RECEIVED,BMessenger(kTrackerSignature)),
|
||||
msg = new BMessage(B_REFS_RECEIVED));
|
||||
msg->AddRef("refs", &ref);
|
||||
navMenu->SetNavDir(&ref);
|
||||
|
||||
menu->AddItem(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
menu->AddItem(item = new BMenuItem(
|
||||
MDR_DIALECT_CHOICE ("No new messages","未読メッセージなし"), NULL));
|
||||
item->SetEnabled(false);
|
||||
}
|
||||
|
||||
if (modifiers() & B_SHIFT_KEY)
|
||||
{
|
||||
BList list;
|
||||
GetInboundMailChains(&list);
|
||||
|
||||
BMenu *chainMenu = new BMenu(
|
||||
MDR_DIALECT_CHOICE ("Check For Mails Only","R) メール受信のみ"));
|
||||
BFont font;
|
||||
menu->GetFont(&font);
|
||||
chainMenu->SetFont(&font);
|
||||
|
||||
for (int32 i = 0;i < list.CountItems();i++) {
|
||||
BMailChain *chain = (BMailChain *)list.ItemAt(i);
|
||||
|
||||
BMessage *message = new BMessage(MD_CHECK_FOR_MAILS);
|
||||
message->AddString("account",chain->Name());
|
||||
|
||||
chainMenu->AddItem(new BMenuItem(chain->Name(),message));
|
||||
delete chain;
|
||||
}
|
||||
chainMenu->SetTargetForItems(this);
|
||||
menu->AddItem(new BMenuItem(chainMenu,new BMessage(MD_CHECK_FOR_MAILS)));
|
||||
|
||||
// Not used:
|
||||
// menu->AddItem(new BMenuItem(MDR_DIALECT_CHOICE (
|
||||
// "Check For Mails Only","メール受信のみ"), new BMessage(MD_CHECK_FOR_MAILS)));
|
||||
menu->AddItem(new BMenuItem(
|
||||
MDR_DIALECT_CHOICE ("Send Pending Mails","M) 保留メールを送信"),
|
||||
new BMessage(MD_SEND_MAILS)));
|
||||
}
|
||||
else
|
||||
menu->AddItem(new BMenuItem(
|
||||
MDR_DIALECT_CHOICE ("Check For Mail Now","C) メールチェック"),
|
||||
new BMessage(MD_CHECK_SEND_NOW)));
|
||||
|
||||
menu->AddSeparatorItem();
|
||||
menu->AddItem(new BMenuItem(
|
||||
MDR_DIALECT_CHOICE ("Edit Preferences","P) メール環境設定") B_UTF8_ELLIPSIS,
|
||||
new BMessage(MD_OPEN_PREFS)));
|
||||
menu->AddItem(new BMenuItem(
|
||||
MDR_DIALECT_CHOICE ("Quit","Q) 終了"),
|
||||
new BMessage(B_QUIT_REQUESTED)));
|
||||
|
||||
// Reset Item Targets (only those which aren't already set)
|
||||
|
||||
for (int32 i = menu->CountItems();i-- > 0;)
|
||||
{
|
||||
item = menu->ItemAt(i);
|
||||
if (item && (msg = item->Message()) != NULL)
|
||||
{
|
||||
if (msg->what == B_REFS_RECEIVED)
|
||||
item->SetTarget(tracker);
|
||||
else
|
||||
item->SetTarget(this);
|
||||
}
|
||||
}
|
||||
return menu;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
#ifndef DESKBAR_VIEW_H
|
||||
#define DESKBAR_VIEW_H
|
||||
/* DeskbarView - main_daemon's deskbar menu and view
|
||||
**
|
||||
** Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <View.h>
|
||||
|
||||
#include "NavMenu.h"
|
||||
|
||||
|
||||
enum MDDeskbarIcon {
|
||||
NO_MAIL = 0,
|
||||
NEW_MAIL,
|
||||
};
|
||||
|
||||
enum MDDeskbarMessages {
|
||||
MD_CHECK_SEND_NOW = 'MDra',
|
||||
MD_CHECK_FOR_MAILS,
|
||||
MD_SEND_MAILS,
|
||||
MD_OPEN_NEW,
|
||||
MD_OPEN_PREFS
|
||||
};
|
||||
|
||||
class BPopUpMenu;
|
||||
class BQuery;
|
||||
class BDirectory;
|
||||
class BEntry;
|
||||
class BPath;
|
||||
|
||||
class _EXPORT DeskbarView : public BView {
|
||||
public:
|
||||
DeskbarView (BRect frame);
|
||||
DeskbarView (BMessage *data);
|
||||
|
||||
virtual ~DeskbarView();
|
||||
|
||||
virtual void Draw(BRect updateRect);
|
||||
virtual void AttachedToWindow();
|
||||
static DeskbarView *Instantiate(BMessage *data);
|
||||
virtual status_t Archive(BMessage *data, bool deep = true) const;
|
||||
virtual void MouseDown(BPoint);
|
||||
virtual void MouseUp(BPoint);
|
||||
virtual void MessageReceived(BMessage *message);
|
||||
virtual void Pulse();
|
||||
|
||||
void ChangeIcon(int32 icon);
|
||||
|
||||
private:
|
||||
bool CreateMenuLinks(BDirectory &,BPath &);
|
||||
void CreateNewMailQuery(BEntry &);
|
||||
BPopUpMenu *BuildMenu();
|
||||
|
||||
BBitmap *fIcon;
|
||||
int32 fCurrentIconState;
|
||||
|
||||
BList fNewMailQueries;
|
||||
int32 fNewMessages;
|
||||
|
||||
int32 fLastButtons;
|
||||
};
|
||||
|
||||
#endif /* DESKBAR_VIEW_H */
|
||||
Binary file not shown.
@@ -0,0 +1,736 @@
|
||||
/* main - the daemon's inner workings
|
||||
**
|
||||
** Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved.
|
||||
*/
|
||||
|
||||
|
||||
#include <Application.h>
|
||||
#include <Message.h>
|
||||
#include <File.h>
|
||||
#include <MessageRunner.h>
|
||||
#include <Deskbar.h>
|
||||
#include <Roster.h>
|
||||
#include <Button.h>
|
||||
#include <StringView.h>
|
||||
#include <Mime.h>
|
||||
#include <Beep.h>
|
||||
#include <fs_index.h>
|
||||
#include <fs_info.h>
|
||||
#include <String.h>
|
||||
#include <VolumeRoster.h>
|
||||
#include <Query.h>
|
||||
#include <ChainRunner.h>
|
||||
#include <NodeMonitor.h>
|
||||
#include <Path.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.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>
|
||||
|
||||
#ifdef BONE
|
||||
#include <sys/socket.h>
|
||||
#include <bone_serial_ppp.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
typedef struct glorbal {
|
||||
size_t bytes;
|
||||
BStringList msgs;
|
||||
} snuzzwut;
|
||||
|
||||
BMailStatusWindow *status;
|
||||
|
||||
class MailDaemonApp : public BApplication {
|
||||
public:
|
||||
MailDaemonApp(void);
|
||||
virtual ~MailDaemonApp();
|
||||
|
||||
virtual void MessageReceived(BMessage *msg);
|
||||
virtual void RefsReceived(BMessage *a_message);
|
||||
|
||||
virtual void Pulse();
|
||||
virtual bool QuitRequested();
|
||||
virtual void ReadyToRun();
|
||||
|
||||
void InstallDeskbarIcon();
|
||||
void RemoveDeskbarIcon();
|
||||
|
||||
void RunChains(BList &list,BMessage *msg);
|
||||
void SendPendingMessages(BMessage *msg);
|
||||
void GetNewMessages(BMessage *msg);
|
||||
|
||||
private:
|
||||
void UpdateAutoCheck(bigtime_t interval);
|
||||
|
||||
BMessageRunner *auto_check;
|
||||
BMailSettings settings_file;
|
||||
|
||||
int32 new_messages;
|
||||
bool central_beep;
|
||||
// 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 fetch_done_respondents;
|
||||
|
||||
BList queries;
|
||||
LEDAnimation *led;
|
||||
|
||||
BString alert_string;
|
||||
};
|
||||
|
||||
|
||||
MailDaemonApp::MailDaemonApp(void)
|
||||
: BApplication("application/x-vnd.Be-POST")
|
||||
{
|
||||
status = new BMailStatusWindow(BRect(40, 400, 360, 400), "Mail Status",
|
||||
settings_file.ShowStatusWindow());
|
||||
auto_check = NULL;
|
||||
}
|
||||
|
||||
|
||||
MailDaemonApp::~MailDaemonApp()
|
||||
{
|
||||
delete auto_check;
|
||||
|
||||
for (int32 i = 0; i < queries.CountItems(); i++)
|
||||
delete ((BQuery *)(queries.ItemAt(i)));
|
||||
|
||||
delete led;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MailDaemonApp::ReadyToRun()
|
||||
{
|
||||
InstallDeskbarIcon();
|
||||
|
||||
UpdateAutoCheck(settings_file.AutoCheckInterval());
|
||||
|
||||
BVolume volume;
|
||||
BVolumeRoster roster;
|
||||
|
||||
new_messages = 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;
|
||||
for (; query->GetNextEntry(&entry) == B_OK; new_messages++);
|
||||
|
||||
queries.AddItem(query);
|
||||
}
|
||||
|
||||
BString string;
|
||||
MDR_DIALECT_CHOICE(
|
||||
if (new_messages > 0)
|
||||
string << new_messages;
|
||||
else
|
||||
string << "No";
|
||||
if (new_messages != 1)
|
||||
string << " new messages.";
|
||||
else
|
||||
string << " new message.";,
|
||||
if (new_messages > 0)
|
||||
string << new_messages << " 通の未読メッセージがあります ";
|
||||
else
|
||||
string << "未読メッセージはありません";
|
||||
);
|
||||
central_beep = false;
|
||||
status->SetDefaultMessage(string);
|
||||
|
||||
led = new LEDAnimation;
|
||||
SetPulseRate(1000000);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MailDaemonApp::RefsReceived(BMessage *message)
|
||||
{
|
||||
status->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, status);
|
||||
runner->GetSingleMessage(uid.String(), size, &path);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MailDaemonApp::UpdateAutoCheck(bigtime_t interval)
|
||||
{
|
||||
if (interval > 0) {
|
||||
if (auto_check != NULL) {
|
||||
auto_check->SetInterval(interval);
|
||||
auto_check->SetCount(-1);
|
||||
} else
|
||||
auto_check = new BMessageRunner(be_app_messenger,new BMessage('moto'),interval);
|
||||
} else {
|
||||
delete auto_check;
|
||||
auto_check = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MailDaemonApp::MessageReceived(BMessage *msg)
|
||||
{
|
||||
switch (msg->what) {
|
||||
case 'moto':
|
||||
if (settings_file.CheckOnlyIfPPPUp()) {
|
||||
#ifdef BONE
|
||||
int s = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
bsppp_status_t status;
|
||||
|
||||
strcpy(status.if_name, "ppp0");
|
||||
if (ioctl(s, BONE_SERIAL_PPP_GET_STATUS, &status, sizeof(status)) != 0) {
|
||||
close(s);
|
||||
break;
|
||||
} else {
|
||||
if (status.connection_status != BSPPP_CONNECTED) {
|
||||
close(s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
close (s);
|
||||
#else
|
||||
if (find_thread("tty_thread") <= 0)
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
// supposed to fall through
|
||||
case 'mbth': // check & send messages
|
||||
msg->what = 'msnd';
|
||||
PostMessage(msg); //'msnd');
|
||||
// supposed to fall trough
|
||||
case 'mnow': // check messages
|
||||
GetNewMessages(msg);
|
||||
break;
|
||||
case 'msnd': // send messages
|
||||
SendPendingMessages(msg);
|
||||
break;
|
||||
|
||||
case 'mrrs':
|
||||
settings_file.Reload();
|
||||
UpdateAutoCheck(settings_file.AutoCheckInterval());
|
||||
status->SetShowCriterion(settings_file.ShowStatusWindow());
|
||||
break;
|
||||
case 'shst': // when to show the status window
|
||||
{
|
||||
int32 mode;
|
||||
if (msg->FindInt32("ShowStatusWindow",&mode) == B_OK)
|
||||
status->SetShowCriterion(mode);
|
||||
break;
|
||||
}
|
||||
case 'lkch': // status window look changed
|
||||
case 'wsch': // workspace changed
|
||||
status->PostMessage(msg);
|
||||
break;
|
||||
case 'stwg': //----StaT Window Gone
|
||||
{
|
||||
BMessage *msg, reply('mnuc');
|
||||
reply.AddInt32("num_new_messages",new_messages);
|
||||
|
||||
while(msg = (BMessage *)fetch_done_respondents.RemoveItem(0L)) {
|
||||
msg->SendReply(&reply);
|
||||
delete msg;
|
||||
}
|
||||
}
|
||||
if (alert_string != B_EMPTY_STRING) {
|
||||
alert_string.Truncate(alert_string.Length()-1);
|
||||
BAlert *alert = new BAlert(MDR_DIALECT_CHOICE ("New Messages","新着メッセージ"), alert_string.String(), "OK", NULL, NULL, B_WIDTH_AS_USUAL);
|
||||
alert->SetFeel(B_NORMAL_WINDOW_FEEL);
|
||||
alert->Go(NULL);
|
||||
alert_string = B_EMPTY_STRING;
|
||||
}
|
||||
if (central_beep) {
|
||||
system_beep("New E-mail");
|
||||
central_beep = false;
|
||||
}
|
||||
break;
|
||||
case 'mcbp':
|
||||
if (new_messages > 0) {
|
||||
central_beep = true;
|
||||
}
|
||||
break;
|
||||
case 'mnum': //----Number of new messages
|
||||
{
|
||||
BMessage reply('mnuc' /* Mail NU message Count */);
|
||||
if (msg->FindBool("wait_for_fetch_done")) {
|
||||
fetch_done_respondents.AddItem(DetachCurrentMessage());
|
||||
break;
|
||||
}
|
||||
|
||||
reply.AddInt32("num_new_messages",new_messages);
|
||||
msg->SendReply(&reply);
|
||||
}
|
||||
break;
|
||||
case 'mblk': //-----Mail BLinK
|
||||
if (new_messages > 0)
|
||||
led->Start();
|
||||
break;
|
||||
case 'enda': //-----End Auto Check
|
||||
delete auto_check;
|
||||
auto_check = NULL;
|
||||
break;
|
||||
case 'numg':
|
||||
{
|
||||
int32 num_messages = msg->FindInt32("num_messages");
|
||||
MDR_DIALECT_CHOICE (
|
||||
alert_string << num_messages << " new message";
|
||||
if (num_messages > 1)
|
||||
alert_string << 's';
|
||||
|
||||
alert_string << " for " << msg->FindString("chain_name") << '\n';,
|
||||
|
||||
alert_string << msg->FindString("chain_name") << "より\n" << num_messages
|
||||
<< " 通のメッセージが届きました ";
|
||||
);
|
||||
|
||||
}
|
||||
break;
|
||||
case B_QUERY_UPDATE:
|
||||
{
|
||||
int32 what;
|
||||
msg->FindInt32("opcode",&what);
|
||||
switch (what) {
|
||||
case B_ENTRY_CREATED:
|
||||
new_messages++;
|
||||
break;
|
||||
case B_ENTRY_REMOVED:
|
||||
new_messages--;
|
||||
break;
|
||||
}
|
||||
|
||||
BString string;
|
||||
|
||||
MDR_DIALECT_CHOICE (
|
||||
if (new_messages > 0)
|
||||
string << new_messages;
|
||||
else
|
||||
string << "No";
|
||||
if (new_messages != 1)
|
||||
string << " new messages.";
|
||||
else
|
||||
string << " new message.";,
|
||||
if (new_messages > 0)
|
||||
string << new_messages << " 通の未読メッセージがあります";
|
||||
else
|
||||
string << "未読メッセージはありません";
|
||||
);
|
||||
|
||||
status->SetDefaultMessage(string.String());
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
BApplication::MessageReceived(msg);
|
||||
}
|
||||
|
||||
|
||||
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() == id) {
|
||||
chain->RunChain(status, 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(status, 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 chain_id = -1;
|
||||
|
||||
if (msg->FindInt32("chain",&chain_id) == B_OK) {
|
||||
query.PushAttr("MAIL:chain");
|
||||
query.PushInt32(chain_id);
|
||||
query.PushOp(B_EQ);
|
||||
query.PushOp(B_AND);
|
||||
} else {
|
||||
chain_id = -1;
|
||||
}
|
||||
|
||||
if (!msg->HasString("message_path")) {
|
||||
if (chain_id == -1) {
|
||||
map <int32, snuzzwut *> messages;
|
||||
|
||||
query.Fetch();
|
||||
BEntry entry;
|
||||
BPath path;
|
||||
BNode node;
|
||||
int32 chain, default_chain(BMailSettings().DefaultOutboundChainID());
|
||||
off_t size;
|
||||
|
||||
while (query.GetNextEntry(&entry) == B_OK) {
|
||||
while (node.SetTo(&entry) == B_BUSY) snooze(100);
|
||||
if (node.ReadAttr("MAIL:chain",B_INT32_TYPE,0,&chain,4) < B_OK)
|
||||
chain = default_chain;
|
||||
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,status);
|
||||
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) {
|
||||
node.SetTo(&entry);
|
||||
entry.GetPath(&path);
|
||||
node.GetSize(&size);
|
||||
ids += path.Path();
|
||||
bytes += size;
|
||||
}
|
||||
|
||||
BMailChainRunner *runner = GetMailChainRunner(chain_id,status);
|
||||
runner->GetMessages(&ids,bytes);
|
||||
runner->Stop();
|
||||
}
|
||||
} else {
|
||||
const char *path;
|
||||
msg->FindString("message_path",&path);
|
||||
BStringList ids;
|
||||
ids += path;
|
||||
off_t size;
|
||||
BNode(path).GetSize(&size);
|
||||
BMailChainRunner *runner = GetMailChainRunner(chain_id,status);
|
||||
runner->GetMessages(&ids,size);
|
||||
runner->Stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MailDaemonApp::Pulse()
|
||||
{
|
||||
bigtime_t idle = idle_time();
|
||||
if (led->IsRunning() && (idle < 100000))
|
||||
led->Stop();
|
||||
}
|
||||
|
||||
// #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;
|
||||
|
||||
// Work-around for misbehaviour of earlier versions - should be
|
||||
// kept in for some time.
|
||||
// It removes the B_MAIL_ATTR_FLAGS if it is of B_STRING_TYPE,
|
||||
// because that's what the MDR created before...
|
||||
index_info indexInfo;
|
||||
if (fs_stat_index(device, B_MAIL_ATTR_FLAGS, &indexInfo) == 0
|
||||
&& indexInfo.type == B_STRING_TYPE)
|
||||
fs_remove_index(device, B_MAIL_ATTR_FLAGS);
|
||||
|
||||
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:fullsize",B_UINT32_TYPE,0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
addAttribute(BMessage &msg,char *name,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 (int i = 0; i < 2; 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, hasThread = false, 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);*/
|
||||
//--- Tracker can't display SIZT attributes. What a pain.
|
||||
if (!hasAccount || !hasThread/* || !hasSize*/)
|
||||
mime.SetAttrInfo(&info);
|
||||
}
|
||||
mime.Unset();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, const char **argv)
|
||||
{
|
||||
bool remakeMIMETypes = false;
|
||||
|
||||
for (int i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "-E") == 0) {
|
||||
if (!BMailSettings().DaemonAutoStarts())
|
||||
return 0;
|
||||
}
|
||||
if (strcmp(argv[i], "-M") == 0) {
|
||||
remakeMIMETypes = true;
|
||||
}
|
||||
}
|
||||
|
||||
MailDaemonApp app;
|
||||
|
||||
// install MimeTypes, attributes, indices, and the
|
||||
// system beep add startup
|
||||
|
||||
makeMimeType(remakeMIMETypes);
|
||||
makeIndices();
|
||||
add_system_beep_event("New E-mail");
|
||||
|
||||
be_app->Run();
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user