Exemple #1
0
status_t RuleFilter::ProcessMailMessage
(
	BPositionIO** , BEntry* entry,
	BMessage* io_headers, BPath* io_folder, const char* 
) {
	const char *data;
	if (!attribute)
		return B_OK; //----That field doesn't exist? NO match
	
	if (io_headers->FindString(attribute,&data) < B_OK) { //--Maybe the capitalization was wrong?
		BString capped(attribute);
		capped.CapitalizeEachWord(); //----Enfore capitalization
		if (io_headers->FindString(capped.String(),&data) < B_OK) //----This time it's *really* not there
			return B_OK; //---No match
	}
	
	if (data == NULL) //--- How would this happen? No idea
		return B_OK;
	
	if (!matcher.Match(data))
		return B_OK; //-----There wasn't an error. We're just not supposed to do anything
	
	switch (do_what) {
		case Z_MOVE_TO:
			if (io_headers->ReplaceString("DESTINATION",arg) != B_OK)
				io_headers->AddString("DESTINATION",arg);
			break;
		case Z_TRASH:
			return B_MAIL_DISCARD;
		case Z_FLAG:
			{
			BString string = arg;
			BNode(entry).WriteAttrString("MAIL:filter_flags",&string);
			}
			break;
		case Z_SET_REPLY:
			BNode(entry).WriteAttr("MAIL:reply_with",B_INT32_TYPE,0,&chain_id,4);
			break;
		case Z_SET_READ:
			if (io_headers->ReplaceString("STATUS", "Read") != B_OK)
				io_headers->AddString("STATUS", "Read");
			break;			
		default:
			fprintf(stderr,"Unknown do_what: 0x%04x!\n",do_what);
	}
	
	return B_OK;
}
Exemple #2
0
status_t
OpenAction(const BMessage &action, entry_ref &ref)
{
	entry_ref app;
	BString appName("");
	if (be_roster->FindApp(&ref,&app) == B_OK)
		appName = app.name;
	
	status_t status = be_roster->Launch(&ref);
	
	if (status == B_OK)
		printf("\tOpened %s in program %s\n",ref.name,appName.String());
	else
	{
		// R5 (and probably others) don't seem to want to open folders in Tracker --
		// FindApp() returns B_OK, but sets the entry_ref of the app to open it to
		// the folder's ref, which is dumb. This works around this apparent stupidity.
		BString typestr;
		if (BNode(&ref).ReadAttrString("BEOS:TYPE",&typestr) == B_OK &&
			typestr.Compare("application/x-vnd.Be-directory") == 0)
		{
			BMessage *msg = new BMessage(B_REFS_RECEIVED);
			msg->AddRef("refs",&ref);
			be_roster->Launch("application/x-vnd.Be-TRAK",msg);
			printf("\tOpened %s in program Tracker\n",ref.name);
			return B_OK;
		}
		if (appName.CountChars() > 0)
			printf("\tCouldn't open %s in program %s\n",ref.name,appName.String());
		else
			printf("\tCouldn't open %s -- the system couldn't find a program to do it.\n",ref.name);
	}
	
	return status;
}
Exemple #3
0
void
ActivityView::_LoadBackgroundInfo(bool watch)
{
	fCachedOutline = false;
	fCachedWorkspace = -1;
	BPath path;
	if (find_directory(B_DESKTOP_DIRECTORY, &path) == B_OK) {
		BNode desktopNode = BNode(path.Path());

		attr_info info;
		if (desktopNode.GetAttrInfo(kDesktopAttrName, &info) != B_OK)
			return;

		char* buffer = new char[info.size];
		if (desktopNode.ReadAttr(kDesktopAttrName, B_MESSAGE_TYPE, 0,
			buffer, (size_t)info.size) == info.size) {
				BMessage message;
				if (message.Unflatten(buffer) == B_OK)
					fBackgroundInfo = message;
		}
		delete[] buffer;

		if (watch) {
			node_ref nref;
			desktopNode.GetNodeRef(&nref);
			watch_node(&nref, B_WATCH_ATTR, this);
		}
	}
}
Exemple #4
0
void
POP3Protocol::CheckForDeletedMessages()
{
	{
		// Delete things from the manifest no longer on the server
		BStringList list;
		NotHere(fUniqueIDs, fManifest, &list);
		fManifest.Remove(list);
	}

	if (!fSettings.FindBool("delete_remote_when_local")
		|| fManifest.CountStrings() == 0)
		return;

	BStringList toDelete;

	BStringList queryContents;
	BVolumeRoster volumes;
	BVolume volume;

	while (volumes.GetNextVolume(&volume) == B_OK) {
		BQuery fido;
		entry_ref entry;

		fido.SetVolume(&volume);
		fido.PushAttr(B_MAIL_ATTR_ACCOUNT_ID);
		fido.PushInt32(fAccountSettings.AccountID());
		fido.PushOp(B_EQ);

		fido.Fetch();

		BString uid;
		while (fido.GetNextRef(&entry) == B_OK) {
			BNode(&entry).ReadAttrString("MAIL:unique_id", &uid);
			queryContents.Add(uid);
		}
	}
	NotHere(queryContents, fManifest, &toDelete);

	for (int32 i = 0; i < toDelete.CountStrings(); i++) {
		printf("delete mail on server uid %s\n", toDelete.StringAt(i).String());
		Delete(fUniqueIDs.IndexOf(toDelete.StringAt(i)));
	}

	// Don't remove ids from fUniqueIDs, the indices have to stay the same when
	// retrieving new messages.
	fManifest.Remove(toDelete);

	// TODO: at some point the purged manifest should be written to disk
	// otherwise it will grow forever
}
Exemple #5
0
void
POP3Protocol::CheckForDeletedMessages()
{
	{
		//---Delete things from the manifest no longer on the server
		BStringList temp;
		fManifest.NotThere(fUniqueIDs, &temp);
		fManifest -= temp;
	}

	if (!fSettings.FindBool("delete_remote_when_local")
		|| fManifest.CountItems() == 0)
		return;

	BStringList to_delete;

	BStringList query_contents;
	BVolumeRoster volumes;
	BVolume volume;

	while (volumes.GetNextVolume(&volume) == B_OK) {
		BQuery fido;
		entry_ref entry;

		fido.SetVolume(&volume);
		fido.PushAttr(B_MAIL_ATTR_ACCOUNT_ID);
		fido.PushInt32(fAccountSettings.AccountID());
		fido.PushOp(B_EQ);

		fido.Fetch();

		BString uid;
		while (fido.GetNextRef(&entry) == B_OK) {
			BNode(&entry).ReadAttrString("MAIL:unique_id", &uid);
			query_contents.AddItem(uid.String());
		}
	}
	query_contents.NotHere(fManifest, &to_delete);

	for (int32 i = 0; i < to_delete.CountItems(); i++) {
		printf("delete mail on server uid %s\n", to_delete[i]);
		Delete(fUniqueIDs.IndexOf(to_delete[i]));
	}

	//*(unique_ids) -= to_delete; --- This line causes bad things to
	// happen (POP3 client uses the wrong indices to retrieve
	// messages).  Without it, bad things don't happen.
	fManifest -= to_delete;
}
/*
* Given a local file path,
* update the corresponding file on Dropbox
*/
void
update_file_in_dropbox(const char * filepath, const char *parent_rev)
{
  char * argv[4];
  argv[0] = "db_put.py";

  BString db_filepath = local_to_db_filepath(filepath);
  const char * tmp = db_filepath.String();
  char not_const[db_filepath.CountChars()];
  strcpy(not_const,tmp);
  argv[2] = not_const;

  char not_const2[strlen(filepath)];
  strcpy(not_const2,filepath);
  argv[1] = not_const2;

  char not_const3[strlen(parent_rev)];
  strcpy(not_const3,parent_rev);
  argv[3] = not_const3;

  BString *result = run_python_script(argv,4);
  BString *real_path = parse_path(result);
  BString *new_parent_rev = parse_parent_rev(result);
  delete result;

  printf("path:|%s|\nparent_rev:|%s|\n",real_path->String(),new_parent_rev->String());

  BNode node = BNode(filepath);
  set_parent_rev(&node,new_parent_rev);
  delete new_parent_rev;

  BEntry entry = BEntry(filepath);
  BPath old_path;
  entry.GetPath(&old_path);

  BPath new_path = BPath(db_to_local_filepath(real_path->String()).String());

  printf("Should I move %s to %s?\n", old_path.Path(), new_path.Path());
  if(strcmp(new_path.Leaf(),old_path.Leaf()) != 0)
  {
    printf("moving %s to %s\n", old_path.Leaf(), new_path.Leaf());
    BEntry entry = BEntry(old_path.Path()); //entry for local path
    status_t err = entry.Rename(new_path.Leaf(),true);
    if(err != B_OK) printf("error moving: %s\n",strerror(err));
  }
  delete real_path;
}
Exemple #7
0
void BlockerApp::RefsReceived(BMessage *msg) {
	entry_ref ref;
	BNode node;
	attr_info info;
	
	IM::Manager man;
	
	for (int32 i = 0; msg->FindRef("refs", i, &ref ) == B_OK; i++ ) {
		node = BNode(&ref);
		char *type = ReadAttribute(node, "BEOS:TYPE");
		if (strcmp(type, "application/x-person") == 0) {

			IM::Contact contact(ref);
			
			char status[256];
			
			if (contact.GetStatus(status, sizeof(status)) != B_OK )	status[0] = '\0';
			
			if (strcmp(status, BLOCKED_TEXT) == 0) {
				// already blocked, unblocked
				contact.SetStatus(OFFLINE_TEXT);
				
				BMessage update_msg(IM::UPDATE_CONTACT_STATUS);
				update_msg.AddRef("contact", &ref);
				
				man.SendMessage(&update_msg);
			} else {
				if (contact.SetStatus(BLOCKED_TEXT) != B_OK) {
					LOG("im_blocker", liHigh, "Error setting contact status");
				};
			};
		};
		free(type);
	};
	
	BMessenger(this).SendMessage(B_QUIT_REQUESTED);
};
/*
* Message Handling Function
* If it's a node monitor message,
* then figure out what to do based on it.
* Otherwise, let BApplication handle it.
*/
void
App::MessageReceived(BMessage *msg)
{
  printf("message received:\n");
  msg->PrintToStream();
  switch(msg->what)
  {
    case MY_DELTA_CONST:
    {
      printf("Pulling changes from Dropbox\n");
      pull_and_apply_deltas();
      break;
    }
    case B_NODE_MONITOR:
    {
      printf("Received Node Monitor Alert\n");
      status_t err;
      int32 opcode;
      err = msg->FindInt32("opcode",&opcode);
      if(err == B_OK)
      {
        switch(opcode)
        {
          case B_ENTRY_CREATED:
          {
            printf("CREATED NEW FILE\n");
            entry_ref ref;
            BPath path;
            const char * name;

            // unpack the message
            msg->FindInt32("device",&ref.device);
            msg->FindInt64("directory",&ref.directory);
            msg->FindString("name",&name);
            ref.set_name(name);

            BEntry new_file = BEntry(&ref);
            new_file.GetPath(&path);


            //if we said to ignore a `NEW` msg from the path, then ignore it
            if(this->ignore_created(&path)) return;

            this->track_file(&new_file);

            if(new_file.IsDirectory())
            {
               add_folder_to_dropbox(path.Path());
               BDirectory new_dir = BDirectory(&new_file);
               this->recursive_watch(&new_dir);
            }
            else
            {
              BString *result = add_file_to_dropbox(path.Path());
              BString *real_path = parse_path(result);
              BString *parent_rev = parse_parent_rev(result);
              delete result;

              printf("path:|%s|\nparent_rev:|%s|\n",real_path->String(),parent_rev->String());

              BNode node = BNode(&new_file);
              set_parent_rev(&node,parent_rev);
              delete parent_rev;
              BPath new_path = BPath(db_to_local_filepath(real_path->String()).String());

              if(strcmp(new_path.Leaf(),path.Leaf()) != 0)
              {
                printf("moving %s to %s\n", path.Leaf(), new_path.Leaf());
                BEntry entry = BEntry(path.Path()); //entry for local path
                status_t err = entry.Rename(new_path.Leaf(),true);
                if(err != B_OK) printf("error moving: %s\n",strerror(err));
              }
              
              delete real_path;
              watch_entry(&new_file,B_WATCH_STAT);
            }
            break;
          }
          case B_ENTRY_MOVED:
          {
            printf("MOVED FILE\n");
            entry_ref eref;
            BDirectory from_dir, to_dir;
            node_ref from_ref,to_ref,nref;
            BPath path;
            const char* name;

            msg->FindInt32("device",&from_ref.device);
            msg->FindInt32("device",&to_ref.device);
            msg->FindInt32("device",&eref.device);
            msg->FindInt32("device",&nref.device);

            msg->FindInt64("from directory",&from_ref.node);
            msg->FindInt64("to directory",&to_ref.node);
            msg->FindInt64("to directory",&eref.directory);

            msg->FindInt64("node",&nref.node);

            msg->FindString("name",&name);
            eref.set_name(name);

            err = from_dir.SetTo(&from_ref);
            err = to_dir.SetTo(&to_ref);

            BEntry dest_entry = BEntry(&eref);
            BEntry test = BEntry("/boot/home/Dropbox/hi");
            BDirectory dropbox_local = BDirectory(local_path_string);
            bool into_dropbox = dropbox_local.Contains(&dest_entry);
            int32 index = this->find_nref_in_tracked_files(nref);
            if((index >= 0) && into_dropbox)
            {
              printf("moving within dropbox\n");
              BPath *old_path = (BPath*)this->tracked_filepaths.ItemAt(index);
              BPath new_path;
              dest_entry.GetPath(&new_path);

              char *argv[3];
              argv[0] = "db_mv.py";
              BString opath = local_to_db_filepath(old_path->Path());
              BString npath = local_to_db_filepath(new_path.Path());
              char not_const_o[opath.CountChars()];
              char not_const_n[npath.CountChars()];
              strcpy(not_const_o,opath.String());
              strcpy(not_const_n,npath.String());
              argv[1] = not_const_o;
              argv[2] = not_const_n;
              run_python_script(argv,3);

              old_path->SetTo(&dest_entry);
            }
            else if(index >= 0)
            {
              printf("moving the file out of dropbox\n");
              BPath *old_path = (BPath*)this->tracked_filepaths.ItemAt(index);
              delete_file_on_dropbox(old_path->Path());
              this->tracked_files.RemoveItem(index);
              this->tracked_filepaths.RemoveItem(index);
            }
            else if(into_dropbox)
            {
              printf("moving file into dropbox\n");
              BPath new_path;
              dest_entry.GetPath(&new_path);

              this->track_file(&dest_entry);

              if(dest_entry.IsDirectory())
              {
                 add_folder_to_dropbox(new_path.Path());
                 BDirectory new_dir = BDirectory(&dest_entry);
                 this->recursive_watch(&new_dir);
              }
              else
              {
                add_file_to_dropbox(new_path.Path());
                watch_entry(&dest_entry,B_WATCH_STAT);
              }
            }
            else
            {
              printf("moving unrelated file...?\n");
            }

            break;
          }
          case B_ENTRY_REMOVED:
          {
            printf("DELETED FILE\n");
            node_ref nref;
            msg->FindInt32("device", &nref.device);
            msg->FindInt64("node", &nref.node);

            int32 index = this->find_nref_in_tracked_files(nref);
            if(index >= 0)
            {
              BPath *path = (BPath*)this->tracked_filepaths.ItemAt(index);
              printf("local file %s deleted\n",path->Path());
              
              if(ignore_removed(path)) return;

              delete_file_on_dropbox(path->Path());
              this->tracked_files.RemoveItem(index);
              this->tracked_filepaths.RemoveItem(index);
            }
            else
            {
              printf("could not find deleted file\n");
            }

            break;
          }
          case B_STAT_CHANGED:
          {
            printf("EDITED FILE\n");
            node_ref nref;
            msg->FindInt32("device", &nref.device);
            msg->FindInt64("node", &nref.node);

            int32 index = this->find_nref_in_tracked_files(nref);
            if(index >= 0)
            {
              BPath *path = (BPath*)this->tracked_filepaths.ItemAt(index);
              if(ignore_edited(path)) return;
              BNode node = BNode(path->Path());
              BString * rev = get_parent_rev(&node);
              printf("parent_rev:|%s|\n",rev->String());
              
              update_file_in_dropbox(path->Path(),rev->String());
            }
            else
            {
              printf("Could not find edited file\n");
            }
            break;
          }
          default:
          {
            printf("default case opcode...\n");
          }
        }
      }
      break;
    }
    default:
    {
      BApplication::MessageReceived(msg);
      break;
    }
  }
}
/*
* Given a single line of the output of db_delta.py
* Figures out what to do and does it.
* (adds and removes files and directories)
*/
int
App::parse_command(BString command)
{
  command.RemoveAll("\n"); //remove trailing whitespace
  if(command.Compare("RESET") == 0)
  {
    printf("Burn Everything. 8D\n");

    status_t err = stop_watching(be_app_messenger);
    if(err != B_OK) printf("stop_watching error: %s\n",strerror(err));

    BDirectory dir = BDirectory(local_path_string);
    rm_rf(&dir);

    BString str = BString("/"); //create_local_path wants a remote path 
    create_local_directory(&str);

    this->recursive_watch(&dir);
  }
  else if(command.Compare("FILE ",5) == 0)
  {
    BString path, dirpath, partial_path;
    BPath *bpath;
    int32 last_space = command.FindLast(" ");
    command.CopyInto(path,5,last_space - 5);

    path.CopyInto(dirpath,0,path.FindLast("/"));

    create_local_directory(&dirpath);
    //TODO fix watching new dirs
    bpath = new BPath(db_to_local_filepath(path.String()).String());
    BEntry new_file = BEntry(bpath->Path());
    if(new_file.InitCheck() && new_file.Exists()) {
      this->new_paths.AddItem((void*)bpath);
    } else {
      this->edited_paths.AddItem((void*)bpath);
    }

    printf("create a file at |%s|\n",path.String());
    char *argv[3];
    argv[0] = "db_get.py";
    char not_const1[path.CountChars() + 1];
    strcpy(not_const1,path.String());
    argv[1] = not_const1;
    BString tmp = db_to_local_filepath(path.String());
    char not_const2[tmp.CountChars() + 1]; //plus one for null
    strcpy(not_const2,tmp.String());
    argv[2] = not_const2;

    //create/update file
    //potential problem: takes awhile to do this step
    // having watching for dir turned off is risky.    
    BString * b = run_python_script(argv,3);
    delete b;

    //start watching the new/updated file
    node_ref nref;
    new_file = BEntry(db_to_local_filepath(path.String()).String());
    new_file.GetNodeRef(&nref);
    status_t err = watch_node(&nref,B_WATCH_STAT,be_app_messenger);

    BString parent_rev;
    command.CopyInto(parent_rev,last_space + 1, command.CountChars() - (last_space+1));
    BNode node = BNode(db_to_local_filepath(path.String()).String());
    set_parent_rev(&node,&parent_rev);
  }
  else if(command.Compare("FOLDER ",7) == 0)
  {
    BString path;
    command.CopyInto(path,7,command.FindLast(" ") - 7);

    //ignore the creation message
    BPath bpath = BPath(db_to_local_filepath(path.String()).String());
    BPath *actually_exists = find_existing_subpath(&bpath);
    this->new_paths.AddItem((void*)actually_exists);

    //create all nescessary dirs in path
    printf("create a folder at |%s|\n", path.String());
    create_local_directory(&path);

    //start watching the new dir
    BDirectory existing_dir = BDirectory(actually_exists->Path());
    recursive_watch(&existing_dir);
  }
  else if(command.Compare("REMOVE ",7) == 0)
  {
    //TODO: deal with Dropbox file paths being case-insensitive
    //which here means all lower case
    BString path;
    command.CopyInto(path,7,command.Length() - 7);

    const char * pathstr = db_to_local_filepath(path.String()).String();
    BPath *bpath = new BPath(pathstr);
    //TODO: check if it exists...
    this->removed_paths.AddItem((void*)bpath);

    printf("Remove whatever is at |%s|\n", pathstr);

    BEntry entry = BEntry(pathstr);
    status_t err = entry.Remove();
    if(err != B_OK)
      printf("Removal error: %s\n", strerror(err));
  }
  else
  {
    printf("Did not recognize command.\n");
    return B_ERROR;
  }
  return B_OK;
}
Exemple #10
0
void
ChatWindow::MessageReceived( BMessage * msg )
{
	switch ( msg->what )
	{
		case IM::SETTINGS_UPDATED: {
			if (msg->FindString("people_handler", &fPeopleHandler) != B_OK) {
				fPeopleHandler = kDefaultPeopleHandler;
			};
			
			RebuildDisplay();
		} break;
		case IM::USER_STOPPED_TYPING: {
			BMessage im_msg(IM::MESSAGE);
			im_msg.AddInt32("im_what",IM::USER_STOPPED_TYPING);
			im_msg.AddRef("contact",&fEntry);
			fMan->SendMessage(&im_msg);
			
			stopSelfTypingTimer();
		} break;
		case IM::USER_STARTED_TYPING: {
			BMessage im_msg(IM::MESSAGE);
			im_msg.AddInt32("im_what", IM::USER_STARTED_TYPING);
			im_msg.AddRef("contact", &fEntry);
			fMan->SendMessage(&im_msg);
			
			startSelfTypingTimer();
		} break;
		case IM::DESKBAR_ICON_CLICKED:
		{ // deskbar icon clicked, move to current workspace and activate
			SetWorkspaces( 1 << current_workspace() );
			Activate();
		}	break;
		
		case IM::ERROR:
		case IM::MESSAGE:
		{
			entry_ref contact;
			
			if ( msg->FindRef("contact",&contact) != B_OK )
				return;
				
			if ( contact != fEntry )
				// message not for us, skip it.
				return;
			
			int32 im_what=IM::ERROR;
			
			if ( msg->FindInt32("im_what",&im_what) != B_OK )
				im_what = IM::ERROR;
			
//			int32 old_sel_start, old_sel_end;
			
			char timestr[10];
			time_t now = time(NULL);
			strftime(timestr, sizeof(timestr),"[%H:%M]: ", localtime(&now) );
				
			switch ( im_what )
			{
				case IM::STATUS_CHANGED:
				{
					// This means we're rebuilding menus we don't rally need to rebuild..
					BuildProtocolMenu();
				}	break;
				
				case IM::MESSAGE_SENT:
				{
					fText->Append(timestr, C_TIMESTAMP, C_TIMESTAMP, F_TIMESTAMP);

					BString message;
					msg->FindString("message", &message);
					if (message.Compare("/me ", 4) == 0) {
						fText->Append(_T("* You "), C_ACTION, C_ACTION, F_ACTION);
						message.Remove(0, 4);
						fText->Append(message.String(), C_ACTION, C_ACTION, F_ACTION);
					} else {
						fText->Append(_T("You say: "), C_OWNNICK, C_OWNNICK, F_TEXT);
						//fText->Append(msg->FindString("message"), C_TEXT, C_TEXT, F_TEXT);
					    emoticor->AddText(fText,msg->FindString("message"), C_TEXT, F_TEXT,C_TEXT,F_EMOTICON); //by xeD

					}
					fText->Append("\n", C_TEXT, C_TEXT, F_TEXT);
					fText->ScrollToSelection();
				}	break;
				
				case IM::ERROR:
				{
					BMessage error;
					msg->FindMessage("message", &error);
					
					int32 error_what = -1;
					
					error.FindInt32("im_what", &error_what );
					
					if ( error_what != IM::USER_STARTED_TYPING && 
						 error_what != IM::USER_STOPPED_TYPING )
					{ // ignore messages du to typing
						fText->Append(timestr, C_TIMESTAMP, C_TIMESTAMP, F_TIMESTAMP);
						fText->Append("Error: ", C_TEXT, C_TEXT, F_TEXT);
						fText->Append(msg->FindString("error"), C_TEXT, C_TEXT, F_TEXT);
						fText->Append("\n", C_TEXT, C_TEXT, F_TEXT);
					
						if (!IsActive()) startNotify();
					}
				}	break;
				
				case IM::MESSAGE_RECEIVED:
				{
					if ( msg->FindString("message") == NULL )
					{ // no message to display, probably opened by user
						return;
					}
					
					fText->Append(timestr, C_TIMESTAMP, C_TIMESTAMP, F_TIMESTAMP);
					
					BString protocol = msg->FindString("protocol");
					BString message = msg->FindString("message");
					
					
										
					if (protocol.Length() > 0) {
						fName.ReplaceAll("$protocol$",protocol.String());
					} else {
						fName.ReplaceAll("$protocol$"," ");
					};
					
					if (message.Compare("/me ", 4) == 0) {
						fText->Append("* ", C_ACTION, C_ACTION, F_ACTION);
						fText->Append(fName.String(), C_ACTION, C_ACTION, F_ACTION);
						fText->Append(" ", C_ACTION, C_ACTION, F_ACTION);
						message.Remove(0, 4);
						fText->Append(message.String(), C_ACTION, C_ACTION, F_ACTION);
					} else {
						fText->Append(fName.String(), C_OTHERNICK, C_OTHERNICK, F_TEXT);
						fText->Append(": ", C_OTHERNICK, C_OTHERNICK, F_TEXT);
						emoticor->AddText(fText,msg->FindString("message"), C_TEXT, F_TEXT,C_TEXT,F_EMOTICON); //by xeD

					}
					fText->Append("\n", C_TEXT, C_TEXT, F_TEXT);
					fText->ScrollToSelection();

					if (!IsActive()) startNotify();
					
					stopTypingTimer();
				}	break;
				
				case IM::CONTACT_STARTED_TYPING: {	
					startTypingTimer();
				} break;
				
				case IM::CONTACT_STOPPED_TYPING: {
					stopTypingTimer();
				} break;
				
			}
			
			fText->ScrollToSelection();
			
		}	break;
		
		case SEND_MESSAGE:
		{
			if (fInput->TextLength() == 0) return;
			BMessage im_msg(IM::MESSAGE);
			im_msg.AddInt32("im_what",IM::SEND_MESSAGE);
			im_msg.AddRef("contact",&fEntry);
			im_msg.AddString("message", fInput->Text() );
			
			BMenu *menu = fProtocolMenu->Menu();
			if (menu) {
				IconMenuItem *item = dynamic_cast<IconMenuItem*>(menu->FindMarked());
				if ( item )
				{
					BString connection = item->Extra();
					if (connection.Length() > 0) 
					{
						IM::Connection conn(connection.String());
						
						im_msg.AddString("protocol", conn.Protocol());
						im_msg.AddString("id", conn.ID());
					}
				}	
			};
			
			if ( fMan->SendMessage(&im_msg) == B_OK ) {
				fInput->SetText("");
			} else {
				LOG("im_emoclient", liHigh, "Error sending message to im_server");

				fText->Append(_T("Error: im_server not running, can't send message\n"), C_TEXT, C_TEXT, F_TEXT);
					
				fText->ScrollToSelection();
			};
		}	break;
		
		case SHOW_INFO:
		{
			BMessage open_msg(B_REFS_RECEIVED);
			open_msg.AddRef("refs", &fEntry);
			
			be_roster->Launch(fPeopleHandler.String(), &open_msg);
		}	break;
		
		case VIEW_LOG: {
			BMessage open(B_REFS_RECEIVED);
			open.AddRef("refs", &fEntry);
			be_roster->Launch("application/x-vnd.BeClan.im_binlog_viewer", &open);
		} break;
		
		case VIEW_WEBPAGE: {
			entry_ref htmlRef;
			be_roster->FindApp("application/x-vnd.Be.URL.http", &htmlRef);
			BPath htmlPath(&htmlRef);

			BMessage argv(B_ARGV_RECEIVED);
			argv.AddString("argv", htmlPath.Path());

			int32 length = -1;
			char *url = ReadAttribute(BNode(&fEntry), "META:url", &length);
			if ((url != NULL) && (length > 1)) {
				url = (char *)realloc(url, (length + 1) * sizeof(char));
				url[length] = '\0';
				
				argv.AddString("argv", url);	
				argv.AddInt32("argc", 2);
	
				be_roster->Launch(&htmlRef, &argv);
			} else {
				LOG("im_emoclient", liMedium, "Contact had no homepage");
			};
			
			if (url) free(url);
		} break;
		case VIEW_EMOTICONS: {
			//find emoticon button
 			BView* button = FindView("Emoticons");
 			BRect buttonBounds = button->Bounds();
 			//move emoticon window to just below the button
 			BPoint emotLeftBottom = button->ConvertToScreen(buttonBounds.LeftBottom());
 				
 			popup->SetTargetForItems(this);	
			popup->Go(emotLeftBottom,true,true);
			
		} break;
		case ADD_EMOTICON:
		{
			
			int32 index=msg->FindInt32("index");
			BString txt;
			emoticor->config->menu.FindString("face",index,&txt);
			txt << " ";
			fInput->Insert(txt.String());
		} break;
		case EMAIL:
		{
			BMessage open_msg(B_REFS_RECEIVED);
			open_msg.AddRef("refs", &fEntry);
			// "application/x-vnd.Be-MAIL"
			be_roster->Launch("text/x-email", &open_msg );
		}	break;
		
		case BLOCK:
		{
			IM::Contact contact(fEntry);
			
			char status[256];
			
			if ( contact.GetStatus( status, sizeof(status) ) != B_OK )
				status[0] = 0;
			
			if ( strcmp(status, BLOCKED_TEXT) == 0 )
			{ // already blocked, unblocked
				contact.SetStatus(OFFLINE_TEXT);
				
				BMessage update_msg(IM::UPDATE_CONTACT_STATUS);
				update_msg.AddRef("contact", &fEntry);
				
				fMan->SendMessage( &update_msg );
			} else
			{
				if ( contact.SetStatus(BLOCKED_TEXT) != B_OK )
				{
					LOG("im_emoclient", liHigh, "Block: Error setting contact status");
				}
			}
		}	break;
		
		case AUTH:
		{
			BMessage auth_msg(IM::MESSAGE);
			auth_msg.AddInt32("im_what", IM::REQUEST_AUTH);
			auth_msg.AddRef("contact", &fEntry);
			
			fMan->SendMessage( &auth_msg );
		}	break;
		
		case B_NODE_MONITOR:
		{
			int32 opcode=0;
			
			if ( msg->FindInt32("opcode",&opcode) != B_OK )
				return;
			
			switch ( opcode )
			{
				case B_ENTRY_REMOVED: {
					// oops. should we close down this window now?
					// Nah, we'll just disable everything.
					fInput->MakeEditable(false);
					fInput->SetViewColor( 198,198,198 );
					fInput->Invalidate();
					
					BString title( Title() );
					title += " - DELETED!";
					SetTitle( title.String() );
				}	break;
				case B_ENTRY_MOVED:
				{
					entry_ref ref;
					
					msg->FindInt32("device", &ref.device);
					msg->FindInt64("to directory", &ref.directory);
					ref.set_name( msg->FindString("name") );
					
					fEntry = ref;
					
					BEntry entry(&fEntry);
					if ( !entry.Exists() )
					{
						LOG("im_emoclient", liHigh, "Entry moved: New entry invalid");
					}
				}	break;
				case B_STAT_CHANGED:
				case B_ATTR_CHANGED:
					reloadContact();
					BuildProtocolMenu();
					break;
			}
		}	break;
		
		case kResizeMessage: {
			BView *view = NULL;
			msg->FindPointer("view", reinterpret_cast<void**>(&view));
			if (dynamic_cast<BScrollView *>(view)) {
				BPoint point;
				msg->FindPoint("loc", &point);
				
				fResize->MoveTo(fResize->Frame().left, point.y);
				
				fTextScroll->ResizeTo(fTextScroll->Frame().Width(), point.y - 1 - fDock->Frame().Height() - 1);
				
				fInputScroll->MoveTo(fInputScroll->Frame().left, point.y + 3);
				fInputScroll->ResizeTo( 
					fInputScroll->Bounds().Width(),
					fStatusBar->Frame().top - fInputScroll->Frame().top
				);
				fInput->SetTextRect(fInput->Bounds());
				fInput->ScrollToSelection();
				
				if ( fSendButton )
				{
					fSendButton->MoveTo(fSendButton->Frame().left, point.y + 3);
					fSendButton->ResizeTo( 
						fSendButton->Bounds().Width(),
						fStatusBar->Frame().top - fSendButton->Frame().top
					);
				}
			};
		} break;
		
		case B_MOUSE_WHEEL_CHANGED: {
			fText->MessageReceived(msg);
		} break;
		
		case B_COPY: {
			int32 start = 0;
			int32 end = 0;
			
			fInput->GetSelection(&start, &end);
			
			//printf("%ld - > %ld\n", start, end);
		} break;
		
		case B_SIMPLE_DATA: {
			entry_ref ref;
			BNode node;
//			attr_info info;
			
			for (int i = 0; msg->FindRef("refs", i, &ref) == B_OK; i++) {
				node = BNode(&ref);
				
				char *type = ReadAttribute(node, "BEOS:TYPE");
				if (strcmp(type, "application/x-person") == 0) {
					char *name = ReadAttribute(node, "META:name");
					char *nickname = ReadAttribute(node, "META:nickname");
					char connection[100];
					IM::Contact con(ref);
					con.ConnectionAt(0, connection);

					if (fInput->TextLength() > 0) fInput->Insert("\n");
					fInput->Insert(name);
					fInput->Insert(" (");
					fInput->Insert(nickname);
					fInput->Insert("): ");
					fInput->Insert(connection);

					free(name);
					free(nickname);
				};
				free(type);
			};
			fInput->ScrollToOffset(fInput->TextLength());
		} break;
		
		case CLEAR_TYPING:
			stopTypingTimer();
			break;
		
		case PROTOCOL_SELECTED: {
			// a protocol has been selected. Since BMenuField doesn't resize until later,
			// we have to wait 1000us before actually responding to the change, see below
			if ( fProtocolHack )
				delete fProtocolHack;
			BMessage protoHack(PROTOCOL_SELECTED2);
			fProtocolHack = new BMessageRunner( BMessenger(this), &protoHack, 1000, 1 );
		}	break;
		
		case PROTOCOL_SELECTED2:
			// do what should be done on protocol change
			fStatusBar->PositionViews();
			fInfoView->ResizeTo(
				fStatusBar->Bounds().Width() - fInfoView->Frame().left,
				fInfoView->Bounds().Height()
			);
			break;
		
		default:
			BWindow::MessageReceived(msg);
	}
}