summaryrefslogtreecommitdiffstats
path: root/mimelib/entity.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'mimelib/entity.cpp')
-rw-r--r--mimelib/entity.cpp302
1 files changed, 302 insertions, 0 deletions
diff --git a/mimelib/entity.cpp b/mimelib/entity.cpp
new file mode 100644
index 000000000..a97d96e57
--- /dev/null
+++ b/mimelib/entity.cpp
@@ -0,0 +1,302 @@
+//=============================================================================
+// File: entity.cpp
+// Contents: Definitions for DwEntity
+// Maintainer: Doug Sauder <dwsauder@fwb.gulf.net>
+// WWW: http://www.fwb.gulf.net/~dwsauder/mimepp.html
+//
+// Copyright (c) 1996, 1997 Douglas W. Sauder
+// All rights reserved.
+//
+// IN NO EVENT SHALL DOUGLAS W. SAUDER BE LIABLE TO ANY PARTY FOR DIRECT,
+// INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF
+// THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF DOUGLAS W. SAUDER
+// HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// DOUGLAS W. SAUDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT
+// NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+// PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
+// BASIS, AND DOUGLAS W. SAUDER HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
+// SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+//
+//=============================================================================
+
+#define DW_IMPLEMENTATION
+
+#include <mimelib/config.h>
+#include <mimelib/debug.h>
+#include <mimelib/string.h>
+#include <mimelib/enum.h>
+#include <mimelib/entity.h>
+#include <mimelib/headers.h>
+#include <mimelib/body.h>
+#include <mimelib/mediatyp.h>
+
+
+class DwEntityParser {
+ friend class DwEntity;
+private:
+ DwEntityParser(const DwString&);
+ void Parse();
+ const DwString mString;
+ DwString mHeaders;
+ DwString mBody;
+};
+
+
+DwEntityParser::DwEntityParser(const DwString& aStr)
+ : mString(aStr)
+{
+ Parse();
+}
+
+
+void DwEntityParser::Parse()
+{
+ const char* buf = mString.data();
+ size_t bufEnd = mString.length();
+ size_t pos = 0;
+ size_t headersStart = 0;
+ size_t headersLength = 0;
+ size_t lineStart = pos;
+ DwBool isHeaderLine = DwFalse;
+ // If first character is a LF (ANSI C or UNIX)
+ // or if first two characters are CR LF (MIME or DOS),
+ // there are no headers.
+ if (pos < bufEnd && buf[pos] != '\n'
+ && ! (buf[pos] == '\r' && pos+1 < bufEnd && buf[pos+1] == '\n')) {
+
+ while (pos < bufEnd) {
+ // End of line marked by LF
+ if (buf[pos] == '\n') {
+ ++pos;
+ if (!isHeaderLine) {
+ pos = lineStart;
+ break;
+ }
+ // Check for LF LF
+ else if (pos < bufEnd && buf[pos] == '\n') {
+ break;
+ }
+ lineStart = pos;
+ isHeaderLine = DwFalse;
+ }
+ // End of line marked by CRLF
+ else if (buf[pos] == '\r' && pos+1 < bufEnd
+ && buf[pos+1] == '\n') {
+ pos += 2;
+ if (!isHeaderLine) {
+ pos = lineStart;
+ break;
+ }
+ // Check for CR LF CR LF
+ else if (pos+1 < bufEnd && buf[pos] == '\r'
+ && buf[pos+1] == '\n') {
+ break;
+ }
+ lineStart = pos;
+ isHeaderLine = DwFalse;
+ }
+ else if (buf[pos] == ':') {
+ isHeaderLine = DwTrue;
+ ++pos;
+ }
+ else if (pos == lineStart &&
+ (buf[pos] == ' ' || buf[pos] == '\t')) {
+ isHeaderLine = DwTrue;
+ ++pos;
+ }
+ else {
+ ++pos;
+ }
+ }
+ }
+ headersLength = pos;
+ mHeaders = mString.substr(headersStart, headersLength);
+ // Skip blank line
+ // LF (ANSI C or UNIX)
+ if (pos < bufEnd && buf[pos] == '\n') {
+ ++pos;
+ }
+ // CR LF (MIME or DOS)
+ else if (pos < bufEnd && buf[pos] == '\r'
+ && pos+1 < bufEnd && buf[pos+1] == '\n') {
+
+ pos += 2;
+ }
+ size_t bodyStart = pos;
+ size_t bodyLength = mString.length() - bodyStart;
+ mBody = mString.substr(bodyStart, bodyLength);
+}
+
+
+//==========================================================================
+
+
+const char* const DwEntity::sClassName = "DwEntity";
+
+
+DwEntity::DwEntity()
+{
+ mHeaders = DwHeaders::NewHeaders("", this);
+ ASSERT(mHeaders != 0);
+ mBody = DwBody::NewBody("", this);
+ ASSERT(mBody != 0);
+ mClassId = kCidEntity;
+ mClassName = sClassName;
+ mBodySize = -1;
+}
+
+
+DwEntity::DwEntity(const DwEntity& aEntity)
+ : DwMessageComponent(aEntity)
+{
+ mHeaders = (DwHeaders*) aEntity.mHeaders->Clone();
+ ASSERT(mHeaders != 0);
+ mHeaders->SetParent(this);
+ mBody = (DwBody*) aEntity.mBody->Clone();
+ ASSERT(mBody != 0);
+ mBody->SetParent(this);
+ mClassId = kCidEntity;
+ mClassName = sClassName;
+ mBodySize = aEntity.mBodySize;
+}
+
+
+DwEntity::DwEntity(const DwString& aStr, DwMessageComponent* aParent)
+ : DwMessageComponent(aStr, aParent)
+{
+ mHeaders = DwHeaders::NewHeaders("", this);
+ ASSERT(mHeaders != 0);
+ mBody = DwBody::NewBody("", this);
+ ASSERT(mBody != 0);
+ mClassId = kCidEntity;
+ mClassName = sClassName;
+ mBodySize = -1;
+}
+
+
+DwEntity::~DwEntity()
+{
+ delete mHeaders;
+ delete mBody;
+}
+
+
+const DwEntity& DwEntity::operator = (const DwEntity& aEntity)
+{
+ if (this == &aEntity) return *this;
+ DwMessageComponent::operator = (aEntity);
+ // Note: Because of the derived assignment problem, we cannot use the
+ // assignment operator for DwHeaders and DwBody in the following.
+ delete mHeaders;
+ mHeaders = (DwHeaders*) aEntity.mHeaders->Clone();
+ ASSERT(mHeaders != 0);
+ mHeaders->SetParent(this);
+ delete mBody;
+ mBody = (DwBody*) aEntity.mBody->Clone();
+ ASSERT(mBody != 0);
+ mBody->SetParent(this);
+ if (mParent) {
+ mParent->SetModified();
+ }
+ return *this;
+}
+
+
+void DwEntity::Parse()
+{
+ mIsModified = 0;
+ DwEntityParser parser(mString);
+ mHeaders->FromString(parser.mHeaders);
+ mHeaders->Parse();
+ mBody->FromString(parser.mBody);
+ mBody->Parse();
+}
+
+
+void DwEntity::Assemble(DwHeaders& aHeaders, DwBody& aBody)
+{
+ mString = "";
+ mString += aHeaders.AsString();
+
+ // DwEntityParser skips the line separating the headers from the
+ // body. So it's neither part of DwHeaders, nor of DwBody
+ // -> we need to readd it here:
+ mString += DW_EOL;
+
+ mString += aBody.AsString();
+ mIsModified = 0;
+}
+
+
+void DwEntity::Assemble()
+{
+ if (!mIsModified) return;
+ mBody->Assemble();
+ mHeaders->Assemble();
+ Assemble( *mHeaders, *mBody );
+}
+
+
+DwHeaders& DwEntity::Headers() const
+{
+ ASSERT(mHeaders != 0);
+ return *mHeaders;
+}
+
+
+DwBody& DwEntity::Body() const
+{
+ return *mBody;
+}
+
+int DwEntity::BodySize() const
+{
+ if ( mBody->AsString().length() > 0 )
+ return mBody->AsString().length();
+ else if ( mBodySize > 0 )
+ return mBodySize;
+ else
+ return 0;
+}
+
+
+#if defined(DW_DEBUG_VERSION)
+void DwEntity::PrintDebugInfo(std::ostream& aStrm, int aDepth) const
+{
+ aStrm << "------------ Debug info for DwEntity class ------------\n";
+ _PrintDebugInfo(aStrm);
+ int depth = aDepth - 1;
+ depth = (depth >= 0) ? depth : 0;
+ if (aDepth == 0 || depth > 0) {
+ mHeaders->PrintDebugInfo(aStrm, depth);
+ mBody->PrintDebugInfo(aStrm, depth);
+ }
+}
+#else
+void DwEntity::PrintDebugInfo(std::ostream& , int ) const {}
+#endif // defined(DW_DEBUG_VERSION)
+
+
+#if defined(DW_DEBUG_VERSION)
+void DwEntity::_PrintDebugInfo(std::ostream& aStrm) const
+{
+ DwMessageComponent::_PrintDebugInfo(aStrm);
+ aStrm << "Headers: " << mHeaders->ObjectId() << '\n';
+ aStrm << "Body: " << mBody->ObjectId() << '\n';
+}
+#else
+void DwEntity::_PrintDebugInfo(std::ostream& ) const {}
+#endif // defined(DW_DEBUG_VERSION)
+
+
+void DwEntity::CheckInvariants() const
+{
+#if defined(DW_DEBUG_VERSION)
+ DwMessageComponent::CheckInvariants();
+ mHeaders->CheckInvariants();
+ assert((DwMessageComponent*) this == mHeaders->Parent());
+ mBody->CheckInvariants();
+ assert((DwMessageComponent*) this == mBody->Parent());
+#endif // defined(DW_DEBUG_VERSION)
+}