webservices/wsframework/src/senmultipartutils.cpp
changeset 0 62f9d29f7211
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/webservices/wsframework/src/senmultipartutils.cpp	Thu Jan 07 16:19:19 2010 +0200
@@ -0,0 +1,347 @@
+/*
+* Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies). 
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:        Preparation XOP message for HTTP transmission in case 
+*				 of request	and extracting BLOBs from XOP message responsed 
+*				 through HTTP channel in case of response
+*
+*/
+
+
+
+
+
+
+
+
+#include "senmultipartutils.h"
+
+
+
+// ======== MEMBER FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+// Serializes SoapEnvelope message in XOP message
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void SenMultiPartUtils::SerializeMessageL(CSenFragmentBase& aMessage, 
+                                                RBuf8& aMultiPartMessage,
+                                                TXmlEngSerializerType aType)
+    {
+	__ASSERT_ALWAYS(&aMessage, 
+	                User::Panic(KMultiPartNoRequestMessagePanicText, EMultiPartNoRequestMessage));
+	RSenDocument doc = aMessage.AsDocumentL();
+    CXmlEngSerializer* serializer = CXmlEngSerializer::NewL(aType);
+	__ASSERT_ALWAYS(serializer, User::Panic(KMultiPartPanicText, KErrNotFound));
+    CleanupStack::PushL(serializer);
+    TXmlEngSerializationOptions options(TXmlEngSerializationOptions::KOptionIndent & TXmlEngSerializationOptions::KOptionOmitXMLDeclaration);
+    serializer->SetOutput(aMultiPartMessage);	
+    serializer->SetSerializationOptions(options);
+    serializer->SerializeL(doc);
+    CleanupStack::PopAndDestroy(serializer);
+    }
+
+// ---------------------------------------------------------------------------
+// Generates random content-ID for header of XOP message and for headers of BLOBs 
+// as randomNumber@homeTime
+// @param aRootCid is ReAlloc'd, which means that any existing data is freed
+// prior the generated root cid is assinged to that buffer.
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void SenMultiPartUtils::GenerateRandomRootCidL(RBuf8& aRootCid)
+    {
+    _LIT8(KAt, "@");
+	TTime now;
+	now.HomeTime();
+	TInt64 homeTime = now.Int64();
+	TInt64 randomNumber = Math::Random();
+	aRootCid.ReAllocL(32+KAt().Length());
+	aRootCid.AppendNum(randomNumber);
+	aRootCid.Append(KAt);
+	aRootCid.AppendNum(homeTime);
+    }
+
+// ---------------------------------------------------------------------------
+// Generates random boundary for mime header as randomNumber
+// @param aBoundary is ReAlloc'd, which means that any existing data is freed
+// prior the generated root cid is assinged to that buffer.
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void SenMultiPartUtils::GenerateRandomBoundaryL(RBuf8& aBoundary)
+    {
+  	TInt64 randomNumber = Math::Random();
+  	aBoundary.ReAllocL(16);
+	aBoundary.AppendNum(randomNumber);
+    }
+
+// ---------------------------------------------------------------------------
+// Generates MimeBoundary to separate mime parts of the message
+// as --randomNumber
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void SenMultiPartUtils::BoundaryLineStartL(const RBuf8& aBoundary, RBuf8& aBoundaryStart)
+	{
+	aBoundaryStart.ReAllocL(KNewLine().Length()+KDush().Length()+aBoundary.Length());
+	aBoundaryStart.Append(KDush);
+	aBoundaryStart.Append(aBoundary);
+	aBoundaryStart.Append(KNewLine);
+	}
+
+// ---------------------------------------------------------------------------
+// Generates MimeBoundaryEnd to end the multipart message (MultiPart message)
+// as --randomNumber--
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void SenMultiPartUtils::BoundaryLineEndL(const RBuf8& aBoundary, RBuf8& aBoundaryEnd)
+	{
+	aBoundaryEnd.ReAllocL(3*KNewLine().Length()+2*KDush().Length()+aBoundary.Length());
+	aBoundaryEnd.Append(KNewLine);
+	aBoundaryEnd.Append(KNewLine);
+	aBoundaryEnd.Append(KDush);
+	aBoundaryEnd.Append(aBoundary);
+	aBoundaryEnd.Append(KDush);
+	aBoundaryEnd.Append(KNewLine);
+	}
+         
+// ---------------------------------------------------------------------------
+// Creates header for root of XOP message or other multiPart message
+// The header sould be the next:
+//
+// Content-Type: application/xop+xml;
+// charset=UTF-8; 
+// type="text/xml" (for SOAP 1.1) or "application/soap+xml" (for SOAP 1.2)
+// Content-Transfer-Encoding: 8bit
+// Content-ID: <randomNumber@homeTime>
+//
+// where "Content-ID" is the same as "start" in Header of Outer Package
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void SenMultiPartUtils::HeaderRootL(MSenMessage* aMessage,
+										const RBuf8& aRootCid, RBuf8& aHeaderRoot)
+	{
+	
+	if( aMessage->IsSafeToCast(MSenMessage::ESoapEnvelope2 ))
+	    {
+	    CSenSoapEnvelope2* pSoapEnvelope2 = (CSenSoapEnvelope2*)aMessage;
+    	switch (pSoapEnvelope2->SoapVersion())
+    		{
+     		case ESOAP11:
+    			{
+    			aHeaderRoot.ReAllocL(KMultiPartHeaderRootStart11().Length()+KMultiPartHeaderRootEnd().Length()+aRootCid.Length());
+    			aHeaderRoot.Append(KMultiPartHeaderRootStart11);
+    			break;
+    			}
+    		case ESOAP12:
+    			{
+    			aHeaderRoot.ReAllocL(KMultiPartHeaderRootStart12().Length()+KMultiPartHeaderRootEnd().Length()+aRootCid.Length());
+    			aHeaderRoot.Append(KMultiPartHeaderRootStart12);		
+    			break;
+    			}
+    		default:
+    			{
+    			User::Panic(KMultiPartSoapVersionInvalidPanicText, EMultiPartSoapVersionInvalid);
+    			}			
+    		}
+	    }
+	else if( aMessage->IsSafeToCast(MSenMessage::EAtomMessage ))
+	    {
+		aHeaderRoot.ReAllocL(KMultiPartAtomHeaderRootStart().Length()+KMultiPartHeaderRootEnd().Length()+aRootCid.Length());
+		aHeaderRoot.Append(KMultiPartAtomHeaderRootStart);
+	    }
+	aHeaderRoot.Append(aRootCid);
+	aHeaderRoot.Append(KMultiPartHeaderRootEnd);
+	}
+	
+// ---------------------------------------------------------------------------
+// Creates  the header for binary data[aIndex] of XOP message
+// The header sould be the next:
+//
+// --MIME_boundary
+// Content-Type: image/png (for images) or some other type for other BLOBs
+// Content-Transfer-Encoding: binary
+// Content-ID: <randomNumber@homeTime>
+//
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void SenMultiPartUtils::HeaderBinaryDataL(TUint aIndex, 
+										      RArray<TXmlEngDataContainer>& aBinaryDataList,
+			 					     	      RBuf8& aHeaderBinaryData)
+	{
+	__ASSERT_ALWAYS(aBinaryDataList.Count(), User::Panic(KMultiPartNoBlobsPanicText, EMultiPartNoBlobs)); 
+	__ASSERT_ALWAYS((aIndex < aBinaryDataList.Count()), User::Panic(KMultiPartPanicText, KErrArgument));	    
+	
+	TPtrC8 cid = aBinaryDataList[aIndex].Cid();
+	
+	RXmlEngNodeList<TXmlEngAttr> attributes; // to take value of "ContentType" attribute
+	aBinaryDataList[aIndex].ParentNode().AsElement().GetAttributes(attributes);
+	CleanupClosePushL(attributes);
+
+	RBuf8 contentType;
+	CleanupClosePushL(contentType);
+	while (attributes.HasNext())
+		{
+		TXmlEngAttr attr = attributes.Next();
+		if (attr.Name() == KMultiPartContentTypeName)
+			{
+			contentType.ReAllocL(attr.Value().Length());
+			contentType.Copy(attr.Value()); 
+			break;
+			}
+		}
+    if (contentType == KNullDesC8)
+        {
+        contentType.ReAllocL(KMultiPartDefaultBinaryContentTypeValue().Length());
+        contentType.Copy(KMultiPartDefaultBinaryContentTypeValue);
+        }
+
+	
+	aHeaderBinaryData.ReAllocL(KMultiPartHeaderBinaryDataContentType().Length()+
+							   KMultiPartHeaderBinaryDataContentID().Length()+
+							   KMultiPartHeaderBinaryDataEnd().Length()+
+							   contentType.Length()+
+							   cid.Length());
+	aHeaderBinaryData.Append(KMultiPartHeaderBinaryDataContentType);
+	aHeaderBinaryData.Append(contentType);
+	aHeaderBinaryData.Append(KMultiPartHeaderBinaryDataContentID);
+	aHeaderBinaryData.Append(cid);
+	aHeaderBinaryData.Append(KMultiPartHeaderBinaryDataEnd);
+
+	CleanupStack::PopAndDestroy(&contentType);
+	CleanupStack::PopAndDestroy(&attributes);
+	}
+
+// ---------------------------------------------------------------------------
+// Extracts a part of BLOB (10KB) from a file
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void SenMultiPartUtils::FileDataPartL(TUint aPart, TUint aIndex, 
+									      RArray<TXmlEngDataContainer>& aBinaryDataList,
+						       		      RBuf8& aBinaryData)
+	{
+	__ASSERT_ALWAYS(aBinaryDataList.Count(), User::Panic(KMultiPartNoBlobsPanicText, EMultiPartNoBlobs)); 
+	__ASSERT_ALWAYS((aIndex < aBinaryDataList.Count()), User::Panic(KMultiPartPanicText, KErrArgument));	    
+	
+   	aBinaryData.ReAllocL(KTenKBytes);
+
+	RFile& file = aBinaryDataList[aIndex].AsFileContainer().File();
+	file.Flush();
+	file.Read(aPart*KTenKBytes, aBinaryData, KTenKBytes);
+	}
+
+// ---------------------------------------------------------------------------
+// Extracts the rest of BLOB (less than 10KB) from a file
+// ---------------------------------------------------------------------------
+//	
+EXPORT_C void SenMultiPartUtils::FileDataRestL(TUint aParts, TUint aRest, TUint aIndex, 
+									      RArray<TXmlEngDataContainer>& aBinaryDataList,
+						       		      RBuf8& aBinaryData)
+	{
+	__ASSERT_ALWAYS(aBinaryDataList.Count(), User::Panic(KMultiPartNoBlobsPanicText, EMultiPartNoBlobs)); 
+	__ASSERT_ALWAYS((aIndex < aBinaryDataList.Count()), User::Panic(KMultiPartPanicText, KErrArgument));	    
+
+   	aBinaryData.ReAllocL(aRest);
+	RFile& file = aBinaryDataList[aIndex].AsFileContainer().File();
+	file.Flush();
+	file.Read(aParts*KTenKBytes, aBinaryData, aRest);
+	}
+
+// ---------------------------------------------------------------------------
+// Extracts CIDs of BLOBs from response MultiPart message
+// ---------------------------------------------------------------------------
+//	
+EXPORT_C void SenMultiPartUtils::CidL(const RBuf8& aBlobHeader, RArray<RBuf8>& aCids)
+	{
+    _LIT8(KContentIDName, "Content-ID: <");
+    _LIT8(KGreaterThan,">");
+	TInt offset = aBlobHeader.Find(KContentIDName);
+	if (offset == KErrNotFound)
+		{
+		User::Panic(KMultiPartNoCidPanicText, EMultiPartNoCid);
+		}
+	TPtrC8 blobHeaderPtr; // to extract BLOB header from Response message
+	blobHeaderPtr.Set(aBlobHeader.Right(aBlobHeader.Length()-offset-KContentIDName().Length()));
+		
+	offset = blobHeaderPtr.Find(KGreaterThan);//CodeScannerWarning
+	if (offset == KErrNotFound)
+		{
+		User::Panic(KMultiPartCidInvalidPanicText, EMultiPartCidInvalid);
+		}
+	RBuf8 cid; // CID of the BLOB
+	cid.ReAllocL(offset);		
+	cid.Copy(blobHeaderPtr.Left(offset));
+	aCids.AppendL(cid); // collects CIDs of all BLOBs
+	}	
+
+// ---------------------------------------------------------------------------
+// Generates the file name for BLOB of response MultiPart message 
+// and collects it in array of file names for the all BLOBs
+// ---------------------------------------------------------------------------
+//	
+void SenMultiPartUtils::FileNameL(TUint aIndex, RArray<RBuf8>& aFileNames)
+	{
+	RBuf8 fileName;
+	fileName.ReAllocL(KFileName().Length()+7);
+	fileName.Append(KFileName);
+	fileName.AppendNum(aIndex);
+	aFileNames.Append(fileName);
+	}
+
+// ---------------------------------------------------------------------------
+// Extracts BLOB from response MultiPart message and writes it in a file
+// ---------------------------------------------------------------------------
+//	
+EXPORT_C TInt SenMultiPartUtils::SetFileL(TUint aIndex, TBool aFirst, TDesC8& aBlob, 
+						             RArray<RBuf8>& aFileNames)
+	{
+	RFs rfs;
+	RFile file;
+
+    User::LeaveIfError(rfs.Connect());
+	CleanupClosePushL(rfs);	
+	TInt retVal = rfs.ShareProtected();
+    CleanupClosePushL(file);
+    
+    TInt sizeFile = 0;
+    RBuf fileName; //fileName is necessary to convert from 8bites(aFileNames[aIndex]) to 16
+    CleanupClosePushL(fileName);
+    if (aFirst) // check if is it the first part of a BLOB to write in a file
+        {
+        FileNameL(aIndex, aFileNames); // generates the new file
+        fileName.ReAllocL(aFileNames[aIndex].Length());
+        fileName.Copy(aFileNames[aIndex]);
+        User::LeaveIfError(file.Replace(rfs, fileName, EFileWrite)); // replases the old one to the new one
+        }
+    else // if it's not the first part of BLOB then only open the existing file and write a BLOB part in it 
+        {
+        fileName.ReAllocL(aFileNames[aIndex].Length());
+        fileName.Copy(aFileNames[aIndex]);
+        User::LeaveIfError(file.Open(rfs, fileName, EFileWrite));
+        }
+  
+    file.Size(sizeFile);
+	User::LeaveIfError(file.Write(sizeFile, aBlob, aBlob.Length()));
+    
+    file.Flush();
+    file.Close();
+
+    User::LeaveIfError(file.Open(rfs, fileName, EFileRead));
+    
+    //fileName.Close();
+    CleanupStack::PopAndDestroy(&fileName);
+    CleanupStack::PopAndDestroy(&file);
+	CleanupStack::PopAndDestroy(&rfs);
+	return (sizeFile+aBlob.Length());
+	}
+
+// End of file
+