void
GMMIMEParser::ParseByType
	(
	std::istream&			input,
	const GMIMEHeader&	header,
	const JIndex		isEnd
	)
{
	 if (header.GetType()    == kMessageType &&
		 header.GetSubType() == "rfc822")
		{
		Parse(input, isEnd, kJTrue);
		}
	else if (TextIsReadable(header))
		{
		JString data;
		JIndex current	= JTellg(input);
		data.Read(input, isEnd - current + 1);
		WriteTextString(&data, header);
		}
	else if (header.GetType() == kMultipartType)
		{
		if (header.GetSubType() == kMixedType ||
			header.GetSubType() == kRelatedType)
			{
			ParseMixed(input, header);
			}
		else if (header.GetSubType() == kAlternateType)
			{
			ParseAlternate(input, header);
			}
		else
			{
			ParseMixed(input, header);
			}
		}
	else
		{
		JString data;
		JIndex current	= JTellg(input);
		data.Read(input, isEnd - current + 1);
		WriteAttachment(data, header);
		}
}
JBoolean
JFSBindingList::GetBinding
	(
	const JCharacter*	origFileName,
	const JFSBinding**	binding
	)
{
	// ignore # and ~ on end

	JString fileName = origFileName;
	CleanFileName(&fileName);

	// read content

	JString content;
	ifstream input(origFileName);
	content.Read(input, kContentLength);
	input.close();

	// scan bindings for match -- check content types first

	const JSize count = GetElementCount();
	for (JIndex j=0; j<=1; j++)
		{
		const JBoolean isContent = JNegate(j);
		for (JIndex i=1; i<=count; i++)
			{
			*binding = GetBinding(i);
			if ((**binding).IsContentBinding() == isContent &&
				(**binding).Match(fileName, content))
				{
				return kJTrue;
				}
			}
		}

	if (itsUseDefaultFlag && itsUserDefault != NULL)
		{
		*binding = itsUserDefault;
		return kJTrue;
		}

	if (itsUseDefaultFlag && itsSystemDefault != NULL)
		{
		*binding = itsSystemDefault;
		return kJTrue;
		}

	*binding = NULL;
	return kJFalse;
}
void
GMMIMEParser::ParseAlternate
	(
	std::istream&			input,
	const GMIMEHeader&	header
	)
{
	JString boundary	= "-" + header.GetBoundary();
	JString data;
	JString junk;

	// slurp the initial empty part
	JIndex bstart, bend;
	ReadUntilBoundary(input, boundary, &bstart, &bend);
	JIndex current = JTellg(input);
	data.Read(input, bend - current + 1);

	JString text;
	JString charset;
	JString subType;

	GMIMEHeader shownHeader;

	while (1)
		{
		GMIMEHeader child;
		ParseMIMEHeader(input, &child);

		if (child.GetSubType() != kPlainType && child.GetSubType() != kHTMLType)
			{
			text = data;
			while (!ReadUntilBoundary(input, boundary, &bstart, &bend))
				{
				// slurp up the rest, because it is useless to us.
				current	= JTellg(input);
				data.Read(input, bend - current + 1);
				}
			current	= JTellg(input);
			data.Read(input, bend - current + 1);
			data.Clear();
			break;
			}
		else
			{
			shownHeader	= child;
			}

		// when the following function returns true, it has found the
		// last boundary
		data.Clear();
		JBoolean end = ReadUntilBoundary(input, boundary, &bstart, &bend);
		current	= JTellg(input);
		data.Read(input, bstart - current);
		current = JTellg(input);
		junk.Read(input, bend - current + 1);

		if (end)
			{
			text = data;
			data.Clear();
			break;
			}
		}

	WriteTextString(&text, shownHeader);

	if (itsTextInfo != NULL)
		{
		itsTextInfo->ForceUpdate();
		}
	if (itsAttachInfo != NULL)
		{
		itsAttachInfo->ForceUpdate();
		}
}
void
GMMIMEParser::ParseMixed
	(
	std::istream&			input,
	const GMIMEHeader&	header
	)
{
	JString boundary	= "-" + header.GetBoundary();
	JString endBoundary = boundary + "--";

	// slurp the initial empty part
	JIndex bstart, bend;
	ReadUntilBoundary(input, boundary, &bstart, &bend);
	JIndex current = JTellg(input);
	JString data;
	data.Read(input, bend - current + 1);

	while (1)
		{
		GMIMEHeader child;
		ParseMIMEHeader(input, &child);

		// when the following function returns true, it has found the
		// last boundary
		data.Clear();
		JBoolean end;
		if (child.GetEncoding() == kBase64Encoding)
			{
			JString filename = child.GetFileName();
			if (filename.IsEmpty())
				{
				JCreateTempFile(itsAttachDir, NULL, &filename);
				}
			else
				{
				filename = JCombinePathAndName(itsAttachDir, filename);
				}
			if (!filename.IsEmpty())
				{
				AdjustAttachmentName(child, &filename);
				std::ofstream os(filename);
				JDecodeBase64(input, os);
				end = ReadUntilBoundary(input, boundary, &bstart, &bend);
	//			JBoolean found;
	//			JString line;
	//			while (line.IsEmpty() && !input.fail())
	//				{
	//				line = JReadLine(input, &found);
	//				}
	//			JString endBoundary = boundary + "--";
	//			if (line.Contains(endBoundary))
	//				{
	//				end = kJTrue;
	//				}
				}
			}
		else if ((child.GetType() != kMultipartType) &&
				 (!child.GetFileName().IsEmpty()))
			{
			JIndex startI = JTellg(input);
			JIndex findex = startI;
			if (itsData->LocateNextSubstring(boundary, &findex))
				{
				const JCharacter* c = itsData->GetCString() + startI;
				JString filename	= child.GetFileName();
				if (filename.IsEmpty())
					{
					JCreateTempFile(itsAttachDir, NULL, &filename);
					}
				else
					{
					filename = JCombinePathAndName(itsAttachDir, filename);
					}
				if (!filename.IsEmpty())
					{
					AdjustAttachmentName(child, &filename);
					std::ofstream os(filename);
					JSeekg(input, findex - 1);
					if (child.GetEncoding() == kQPEncoding)
						{
						JString data	= itsData->GetSubstring(startI, findex - 3);
						ParseQuotedPrintable(&data);
						data.Print(os);
						}
					else
						{
						os.write(c, findex - startI - 3);
						}				
					JBoolean found;
					JString line = JReadLine(input, &found);
					if (line.BeginsWith(endBoundary))
						{
						end = kJTrue;
						}
					}
				}
			}
		else
			{
			end = ReadUntilBoundary(input, boundary, &bstart, &bend);
			ParseByType(input, child, bstart - 1);

			current	= JTellg(input);
			data.Read(input, bend - current + 1);
			}
		if (end)
			{
			break;
			}
		}

	if (itsTextInfo != NULL)
		{
		itsTextInfo->ForceUpdate();
		}
	if (itsAttachInfo != NULL)
		{
		itsAttachInfo->ForceUpdate();
		}
}