Example #1
0
void
THeaderView::InitEmailCompletion()
{
	// get boot volume
	BVolume volume;
	BVolumeRoster().GetBootVolume(&volume);

	BQuery query;
	query.SetVolume(&volume);
	query.SetPredicate("META:email=**");
		// Due to R5 BFS bugs, you need two stars, META:email=** for the query.
		// META:email="*" will just return one entry and stop, same with
		// META:email=* and a few other variations.  Grumble.
	query.Fetch();
	entry_ref ref;

	while (query.GetNextRef (&ref) == B_OK) {
		BNode file;
		if (file.SetTo(&ref) == B_OK) {
			// Add the e-mail address as an auto-complete string.
			BString email;
			if (file.ReadAttrString("META:email", &email) >= B_OK)
				fEmailList.AddChoice(email.String());

			// Also add the quoted full name as an auto-complete string.  Can't
			// do unquoted since auto-complete isn't that smart, so the user
			// will have to type a quote mark if he wants to select someone by
			// name.
			BString fullName;
			if (file.ReadAttrString("META:name", &fullName) >= B_OK) {
				if (email.FindFirst('<') < 0) {
					email.ReplaceAll('>', '_');
					email.Prepend("<");
					email.Append(">");
				}
				fullName.ReplaceAll('\"', '_');
				fullName.Prepend("\"");
				fullName << "\" " << email;
				fEmailList.AddChoice(fullName.String());
			}

			// support for 3rd-party People apps.  Looks like a job for
			// multiple keyword (so you can have several e-mail addresses in
			// one attribute, perhaps comma separated) indices!  Which aren't
			// yet in BFS.
			for (int16 i = 2; i < 6; i++) {
				char attr[16];
				sprintf(attr, "META:email%d", i);
				if (file.ReadAttrString(attr, &email) >= B_OK)
					fEmailList.AddChoice(email.String());
			}
		}
	}
}
Example #2
0
status_t
write_read_attr(BNode& node, read_flags flag)
{
	if (node.WriteAttr(B_MAIL_ATTR_READ, B_INT32_TYPE, 0, &flag, sizeof(int32))
		< 0)
		return B_ERROR;

#if R5_COMPATIBLE
	// manage the status string only if it currently has a "read" status
	BString currentStatus;
	if (node.ReadAttrString(B_MAIL_ATTR_STATUS, &currentStatus) == B_OK) {
		if (currentStatus.ICompare("New") != 0
			&& currentStatus.ICompare("Read") != 0
			&& currentStatus.ICompare("Seen") != 0)
			return B_OK;
	}

	const char* statusString = (flag == B_READ) ? "Read"
		: (flag  == B_SEEN) ? "Seen" : "New";
	if (node.WriteAttr(B_MAIL_ATTR_STATUS, B_STRING_TYPE, 0, statusString,
		strlen(statusString)) < 0)
		return B_ERROR;
#endif
	return B_OK;
}
Example #3
0
status_t
StyledEditView::GetStyledText(BPositionIO* stream)
{
	fSuppressChanges = true;
	status_t result = BTranslationUtils::GetStyledText(stream, this,
		fEncoding.String());
	fSuppressChanges = false;

	if (result != B_OK)
		return result;

	BNode* node = dynamic_cast<BNode*>(stream);
	if (node != NULL) {
		// get encoding
		if (node->ReadAttrString("be:encoding", &fEncoding) != B_OK) {
			// try to read as "int32"
			int32 encoding;
			ssize_t bytesRead = node->ReadAttr("be:encoding", B_INT32_TYPE, 0,
				&encoding, sizeof(encoding));
			if (bytesRead == (ssize_t)sizeof(encoding)) {
				if (encoding == 65535) {
					fEncoding = "UTF-8";
				} else {
					const BCharacterSet* characterSet
						= BCharacterSetRoster::GetCharacterSetByConversionID(encoding);
					if (characterSet != NULL)
						fEncoding = characterSet->GetName();
				}
			}
		}

		// TODO: move those into BTranslationUtils::GetStyledText() as well?

		// restore alignment
		int32 align;
		ssize_t bytesRead = node->ReadAttr("alignment", 0, 0, &align, sizeof(align));
		if (bytesRead == (ssize_t)sizeof(align))
			SetAlignment((alignment)align);

		// restore wrapping
		bool wrap;
		bytesRead = node->ReadAttr("wrap", 0, 0, &wrap, sizeof(wrap));
		if (bytesRead == (ssize_t)sizeof(wrap)) {
			SetWordWrap(wrap);
			if (wrap == false) {
				BRect textRect;
				textRect = Bounds();
				textRect.OffsetTo(B_ORIGIN);
				textRect.InsetBy(TEXT_INSET, TEXT_INSET);
					// the width comes from stylededit R5. TODO: find a better way
				textRect.SetRightBottom(BPoint(1500.0, textRect.RightBottom().y));
				SetTextRect(textRect);
			}
		}
	}

	return result;
}
Example #4
0
uint32
IMAPFolder::_ReadUniqueID(BNode& node) const
{
	// For compatibility we must assume that the UID is stored as a string
	BString string;
	if (node.ReadAttrString(kUIDAttribute, &string) != B_OK)
		return 0;

	return strtoul(string.String(), NULL, 0);
}
Example #5
0
entry_ref* TaskFS::FileForId(Task *theTask)
{
	//**scan through all files for the ID or shell we do a querry??
	BString		fileID;
	entry_ref	*ref;
	BNode		theNode;
	
	while (tasksDir.GetNextRef(ref) == B_OK){
		theNode.SetTo(ref);
		if (theNode.ReadAttrString("META:task_id", &fileID) == B_OK)
			if (fileID==theTask->ID() && fileID.Length() != 0)
				return ref;
	}
	return NULL;
}
Example #6
0
status_t
IMAPFolder::_MailToIMAPFlags(BNode& node, uint32& flags)
{
	BString mailStatus;
	status_t status = node.ReadAttrString(B_MAIL_ATTR_STATUS, &mailStatus);
	if (status != B_OK)
		return status;

	flags &= ~(IMAP::kAnswered | IMAP::kSeen);

	// TODO: add some utility function for this in libmail.so
	if (mailStatus == "Answered")
		flags |= IMAP::kAnswered | IMAP::kSeen;
	else if (mailStatus == "Read")
		flags |= IMAP::kSeen;
	else if (mailStatus == "Starred")
		flags |= IMAP::kFlagged | IMAP::kSeen;

	return B_OK;
}
Example #7
0
status_t
read_read_attr(BNode& node, read_flags& flag)
{
	if (node.ReadAttr(B_MAIL_ATTR_READ, B_INT32_TYPE, 0, &flag, sizeof(int32))
		== sizeof(int32))
		return B_OK;

#if R5_COMPATIBLE
	BString statusString;
	if (node.ReadAttrString(B_MAIL_ATTR_STATUS, &statusString) == B_OK) {
		if (statusString.ICompare("New"))
			flag = B_UNREAD;
		else
			flag = B_READ;

		return B_OK;
	}
#endif
	return B_ERROR;
}
Example #8
0
void
THeaderView::InitGroupCompletion()
{
	// get boot volume
	BVolume volume;
	BVolumeRoster().GetBootVolume(&volume);

	// Build a list of all unique groups and the addresses they expand to.
	BQuery query;
	query.SetVolume(&volume);
	query.SetPredicate("META:group=**");
	query.Fetch();

	map<BString *, BString *, CompareBStrings> groupMap;
	entry_ref ref;
	BNode file;
	while (query.GetNextRef(&ref) == B_OK) {
		if (file.SetTo(&ref) != B_OK)
			continue;

		BString groups;
		if (file.ReadAttrString("META:group", &groups) < B_OK || groups.Length() == 0)
			continue;

		BString address;
		file.ReadAttrString("META:email", &address);

		// avoid adding an empty address
		if (address.Length() == 0)
			continue;

		char *group = groups.LockBuffer(groups.Length());
		char *next = strchr(group, ',');

		for (;;) {
			if (next)
				*next = 0;

			while (*group && *group == ' ')
				group++;

			BString *groupString = new BString(group);
			BString *addressListString = NULL;

			// nobody is in this group yet, start it off
			if (groupMap[groupString] == NULL) {
				addressListString = new BString(*groupString);
				addressListString->Append(" ");
				groupMap[groupString] = addressListString;
			} else {
				addressListString = groupMap[groupString];
				addressListString->Append(", ");
				delete groupString;
			}

			// Append the user's address to the end of the string with the
			// comma separated list of addresses.  If not present, add the
			// < and > brackets around the address.

			if (address.FindFirst ('<') < 0) {
				address.ReplaceAll ('>', '_');
				address.Prepend ("<");
				address.Append(">");
			}
			addressListString->Append(address);

			if (!next)
				break;

			group = next + 1;
			next = strchr(group, ',');
		}
	}

	map<BString *, BString *, CompareBStrings>::iterator iter;
	for (iter = groupMap.begin(); iter != groupMap.end();) {
		BString *group = iter->first;
		BString *addr = iter->second;
		fEmailList.AddChoice(addr->String());
		++iter;
		groupMap.erase(group);
		delete group;
		delete addr;
	}
}
Example #9
0
void
QPopupMenu::EntryCreated(const entry_ref &ref, ino_t node)
{
	BNode file;
	if (file.SetTo(&ref) < B_OK)
		return;

	// Make sure the pop-up menu is ready for additions.  Need a bunch of
	// groups at the top, a divider line, and miscellaneous people added below
	// the line.

	int32 items = CountItems();
	if (!items)
		AddSeparatorItem();

	// Does the file have a group attribute?  OK to have none.
	BString groups;
	const char *kNoGroup = "NoGroup!";
	file.ReadAttrString("META:group", &groups);
	if (groups.Length() <= 0)
		groups = kNoGroup;

	// Add the e-mail address to the all people group.  Then add it to all the
	// group menus that it exists in (based on the comma separated list of
	// groups from the People file), optionally making the group menu if it
	// doesn't exist.  If it's in the special NoGroup!  list, then add it below
	// the groups.

	bool allPeopleGroupDone = false;
	BMenu *groupMenu;
	do {
		BString group;

		if (!allPeopleGroupDone) {
			// Create the default group for all people, if it doesn't exist yet.
			group = "All People";
			allPeopleGroupDone = true;
		} else {
			// Break out the next group from the comma separated string.
			int32 comma;
			if ((comma = groups.FindFirst(',')) > 0) {
				groups.MoveInto(group, 0, comma);
				groups.Remove(0, 1);
			} else
				group.Adopt(groups);
		}

		// trim white spaces
		int32 i = 0;
		for (i = 0; isspace(group.ByteAt(i)); i++) {}
		if (i)
			group.Remove(0, i);
		for (i = group.Length() - 1; isspace(group.ByteAt(i)); i--) {}
		group.Truncate(i + 1);

		groupMenu = NULL;
		BMenuItem *superItem = NULL; // Corresponding item for group menu.

		if (group.Length() > 0 && group != kNoGroup) {
			BMenu *sub;

			// Look for submenu with label == group name
			for (int32 i = 0; i < items; i++) {
				if ((sub = SubmenuAt(i)) != NULL) {
					superItem = sub->Superitem();
					if (!strcmp(superItem->Label(), group.String())) {
						groupMenu = sub;
						i++;
						break;
					}
				}
			}

			// If no submenu, create one
			if (!groupMenu) {
				// Find where it should go (alphabetical)
				int32 mindex = 0;
				for (; mindex < fGroups; mindex++) {
					if (strcmp(ItemAt(mindex)->Label(), group.String()) > 0)
						break;
				}

				groupMenu = new BMenu(group.String());
				groupMenu->SetFont(be_plain_font);
				AddItem(groupMenu, mindex);

				superItem = groupMenu->Superitem();
				superItem->SetMessage(new BMessage(B_SIMPLE_DATA));
				if (fTargetHandler)
					superItem->SetTarget(fTargetHandler);

				fGroups++;
			}
		}

		BString	name;
		file.ReadAttrString("META:name", &name);

		BString email;
		file.ReadAttrString("META:email", &email);

		if (email.Length() != 0 || name.Length() != 0)
			AddPersonItem(&ref, node, name, email, NULL, groupMenu, superItem);

		// support for 3rd-party People apps
		for (int16 i = 2; i < 6; i++) {
			char attr[16];
			sprintf(attr, "META:email%d", i);
			if (file.ReadAttrString(attr, &email) >= B_OK && email.Length() > 0)
				AddPersonItem(&ref, node, name, email, attr, groupMenu, superItem);
		}
	} while (groups.Length() > 0);
}
Example #10
0
/*!
	Convert the plain text (UTF8) from inSource to plain or
	styled text in outDestination
*/
status_t
translate_from_text(BPositionIO* source, const char* encoding, bool forceEncoding,
                    BPositionIO* destination, uint32 outType)
{
    if (outType != B_TRANSLATOR_TEXT && outType != B_STYLED_TEXT_FORMAT)
        return B_BAD_VALUE;

    // find the length of the text
    off_t size = source->Seek(0, SEEK_END);
    if (size < 0)
        return (status_t)size;
    if (size > UINT32_MAX && outType == B_STYLED_TEXT_FORMAT)
        return B_NOT_SUPPORTED;

    status_t status = source->Seek(0, SEEK_SET);
    if (status < B_OK)
        return status;

    if (outType == B_STYLED_TEXT_FORMAT) {
        // output styled text headers
        status = output_headers(destination, (uint32)size);
        if (status != B_OK)
            return status;
    }

    class MallocBuffer {
    public:
        MallocBuffer() : fBuffer(NULL), fSize(0) {}
        ~MallocBuffer() {
            free(fBuffer);
        }

        void* Buffer() {
            return fBuffer;
        }
        size_t Size() const {
            return fSize;
        }

        status_t
        Allocate(size_t size)
        {
            fBuffer = malloc(size);
            if (fBuffer != NULL) {
                fSize = size;
                return B_OK;
            }
            return B_NO_MEMORY;
        }

    private:
        void*	fBuffer;
        size_t	fSize;
    } encodingBuffer;
    BMallocIO encodingIO;
    uint32 encodingID = 0;
    // defaults to UTF-8 or no encoding

    BNode* node = dynamic_cast<BNode*>(source);
    if (node != NULL) {
        // determine encoding, if available
        const BCharacterSet* characterSet = NULL;
        bool hasAttribute = false;
        if (encoding != NULL && !forceEncoding) {
            BString name;
            if (node->ReadAttrString("be:encoding", &name) == B_OK) {
                encoding = name.String();
                hasAttribute = true;
            } else {
                int32 value;
                ssize_t bytesRead = node->ReadAttr("be:encoding", B_INT32_TYPE, 0,
                                                   &value, sizeof(value));
                if (bytesRead == (ssize_t)sizeof(value)) {
                    hasAttribute = true;
                    if (value != 65535)
                        characterSet = BCharacterSetRoster::GetCharacterSetByConversionID(value);
                }
            }
        } else {
            hasAttribute = true;
            // we don't write the encoding in this case
        }
        if (characterSet == NULL && encoding != NULL)
            characterSet = BCharacterSetRoster::FindCharacterSetByName(encoding);

        if (characterSet != NULL) {
            encodingID = characterSet->GetConversionID();
            encodingBuffer.Allocate(READ_BUFFER_SIZE * 4);
        }

        if (!hasAttribute && encoding != NULL) {
            // add encoding attribute, so that someone opening the file can
            // retrieve it for persistance
            node->WriteAttr("be:encoding", B_STRING_TYPE, 0, encoding,
                            strlen(encoding));
        }
    }

    off_t outputSize = 0;
    ssize_t bytesRead;
    int32 state = 0;

    // output the actual text part of the data
    do {
        uint8 buffer[READ_BUFFER_SIZE];
        bytesRead = source->Read(buffer, READ_BUFFER_SIZE);
        if (bytesRead < B_OK)
            return bytesRead;
        if (bytesRead == 0)
            break;

        if (encodingBuffer.Size() == 0) {
            // default, no encoding
            ssize_t bytesWritten = destination->Write(buffer, bytesRead);
            if (bytesWritten != bytesRead) {
                if (bytesWritten < B_OK)
                    return bytesWritten;

                return B_ERROR;
            }

            outputSize += bytesRead;
        } else {
            // decode text file to UTF-8
            char* pos = (char*)buffer;
            int32 encodingLength = encodingIO.BufferLength();
            int32 bytesLeft = bytesRead;
            int32 bytes;
            do {
                encodingLength = READ_BUFFER_SIZE * 4;
                bytes = bytesLeft;

                status = convert_to_utf8(encodingID, pos, &bytes,
                                         (char*)encodingBuffer.Buffer(), &encodingLength, &state);
                if (status < B_OK)
                    return status;

                ssize_t bytesWritten = destination->Write(encodingBuffer.Buffer(),
                                       encodingLength);
                if (bytesWritten < encodingLength) {
                    if (bytesWritten < B_OK)
                        return bytesWritten;

                    return B_ERROR;
                }

                pos += bytes;
                bytesLeft -= bytes;
                outputSize += encodingLength;
            } while (encodingLength > 0 && bytesLeft > 0);
        }
    } while (bytesRead > 0);

    if (outType != B_STYLED_TEXT_FORMAT)
        return B_OK;

    if (encodingBuffer.Size() != 0 && size != outputSize) {
        if (outputSize > UINT32_MAX)
            return B_NOT_SUPPORTED;

        // we need to update the header as the decoded text size has changed
        status = destination->Seek(0, SEEK_SET);
        if (status == B_OK)
            status = output_headers(destination, (uint32)outputSize);
        if (status == B_OK)
            status = destination->Seek(0, SEEK_END);

        if (status < B_OK)
            return status;
    }

    // Read file attributes if outputting styled data
    // and source is a BNode object

    if (node == NULL)
        return B_OK;

    // Try to read styles - we only propagate an error if the actual on-disk
    // data is likely to be okay

    const char *kAttrName = "styles";
    attr_info info;
    if (node->GetAttrInfo(kAttrName, &info) != B_OK)
        return B_OK;

    if (info.type != B_RAW_TYPE || info.size < 160) {
        // styles seem to be broken, but since we got the text,
        // we don't propagate the error
        return B_OK;
    }

    uint8* flatRunArray = new (std::nothrow) uint8[info.size];
    if (flatRunArray == NULL)
        return B_NO_MEMORY;

    bytesRead = node->ReadAttr(kAttrName, B_RAW_TYPE, 0, flatRunArray, info.size);
    if (bytesRead != info.size)
        return B_OK;

    output_styles(destination, size, flatRunArray, info.size);

    delete[] flatRunArray;
    return B_OK;
}