--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookui/Phonebook/BCardEng/src/BCardEng.cpp Tue Feb 02 10:12:17 2010 +0200
@@ -0,0 +1,490 @@
+/*
+* Copyright (c) 2002 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:
+* A class to convert Phonebook items to vCard stream and vice versa
+*
+*/
+
+
+// INCLUDE FILES
+#include "BCardEng.h" // This class
+
+// System APIs
+#include <s32mem.h>
+#include <barsc.h>
+#include <barsread.h>
+#include <cntfldst.h>
+#include <vcard.h>
+
+// Series 60 APIs
+#include <StringLoader.h>
+#include <featmgr.h>
+#include <bldvariant.hrh>
+
+// Phonebook APIs
+#include <PbkEngUtils.h>
+#include <CPbkContactEngine.h>
+#include <CPbkContactItem.h>
+#include <CPbkFieldsInfo.h>
+#include <CPbkFieldInfo.h>
+#include <CPbkAttachmentFile.h>
+#include <CPbkConstants.h>
+
+#include <BCardEng.rsg>
+#include "CBCardParserParamArray.h"
+#include "CBCardFieldAction.h"
+#include "CBCardFieldUidMapping.h"
+#include "CBCardExportProperty.h"
+#include "TPbkMatchPriorityLevel.h"
+#include "TBCardVersitPlugin.h"
+#include "CBCardParser.h"
+#include "PbkDataCaging.hrh"
+
+/// Unnamed namespace for local definitons
+namespace {
+
+// LOCAL CONSTANTS AND MACROS
+_LIT(KResFileName, "BCardEng.rsc");
+_LIT(KBusinessCardText, "Business Card"); // Business card signature
+_LIT(KCloseParenthesis, ")");
+_LIT(KTelText, "tel ");
+_LIT(KFaxText, "fax ");
+_LIT(KSeparatorText, ", ");
+
+const TText KOpenParenthesis = '(';
+const TInt KBufferSize = 200;
+const TInt KStartPosition = 4;
+const TInt KLabelStartPosition = 5;
+const TInt KLabelValueDelimiterLength = 2;
+
+} // namespace
+
+// ================= MEMBER FUNCTIONS =======================
+
+inline CBCardEngine::CBCardEngine()
+ {
+ }
+
+EXPORT_C CBCardEngine* CBCardEngine::NewL(CPbkContactEngine *aEngine)
+ {
+ CBCardEngine* self = new(ELeave) CBCardEngine();
+ CleanupStack::PushL(self);
+ self->ConstructL(aEngine);
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+/*
+ * ConstructL() reads the import/export definitions from the resource file
+ * and stores them into class member arrays.
+ */
+void CBCardEngine::ConstructL(CPbkContactEngine* aEngine)
+ {
+ // Open a file server session
+ RFs fs;
+ User::LeaveIfError(fs.Connect());
+ CleanupClosePushL(fs);
+
+ // Initialize feature manager
+ FeatureManager::InitializeLibL();
+
+ // Open the resource file
+ RResourceFile resourceFile;
+ PbkEngUtils::FindAndOpenResourceFileLC(fs, KResFileName,
+ KDC_RESOURCE_FILES_DIR, KPbkRomFileDrive, resourceFile);
+
+ TResourceReader resReader;
+
+ // Read picture filenames
+ resReader.SetBuffer(resourceFile.AllocReadLC(R_QTN_BCARD_FILENAME_PICTURE));
+ iPictureFileName = resReader.ReadHBufCL();
+ CleanupStack::PopAndDestroy(); // R_QTN_BCARD_FILENAME_PICTURE
+
+ resReader.SetBuffer(resourceFile.AllocReadLC(R_QTN_BCARD_FILENAME_THUMBNAIL));
+ iThumbnailFileName = resReader.ReadHBufCL();
+ CleanupStack::PopAndDestroy(); // R_QTN_BCARD_FILENAME_THUMBNAIL
+
+ // Read propery name (+index) <-> Uid mapping
+ resReader.SetBuffer(resourceFile.AllocReadLC(R_PBK_BCARD_NAME_UID_MAPPING));
+ iNameUidMap = CBCardFieldUidMapping::NewL(resReader);
+ CleanupStack::PopAndDestroy(); // R_PBK_BCARD_NAME_UID_MAPPING
+
+ // Read export properties
+ resReader.SetBuffer(resourceFile.AllocReadLC(R_PBK_BCARD_EXPORT_VCARD));
+ TInt count = resReader.ReadInt16();
+ while (--count >= 0)
+ {
+ CBCardExportProperty* property =
+ CBCardExportProperty::NewLC(resReader, aEngine->FieldsInfo());
+ // Do not export non-existing fields, this check is required for
+ // western version not to export japanese reading fields
+ if (property->InfoCount() > 0)
+ {
+ // Array takes ownership of the property
+ User::LeaveIfError(iExportProperties.Append(property));
+ CleanupStack::Pop(property);
+ }
+ else
+ {
+ CleanupStack::PopAndDestroy(property);
+ }
+ }
+ CleanupStack::PopAndDestroy(3); // resourceFile, fs
+
+ iEngine = aEngine;
+ iFieldAction = CBCardFieldAction::NewL(
+ *aEngine,*iNameUidMap, *iPictureFileName, *iThumbnailFileName);
+ }
+
+EXPORT_C CBCardEngine::~CBCardEngine()
+ {
+ delete iNameUidMap;
+ delete iThumbnailFileName;
+ delete iPictureFileName;
+ delete iFieldAction;
+ iExportProperties.ResetAndDestroy();
+ iExportProperties.Close();
+ FeatureManager::UnInitializeLib();
+ }
+
+/*
+ * THE MAIN IMPORT FUNCTION
+ * Properties are imported from vCard file according to the specifications
+ * loaded from the resource file.
+ */
+EXPORT_C void CBCardEngine::ImportBusinessCardL(
+ CPbkContactItem& aDestItem, RReadStream &aSourceStream)
+ {
+ // Must use CParserVCard here, not the own parser class!
+ // Otherwise there will be problems, and the parsing goes wrongly
+ CParserVCard* parser = CParserVCard::NewL();
+ CleanupStack::PushL(parser);
+
+ if (FeatureManager::FeatureSupported(KFeatureIdJapanese))
+ {
+ // if in Japanese mode, use shift-jis by default
+ parser->SetDefaultCharSet(Versit::EShiftJISCharSet);
+ parser->SetFlags(CVersitParser::EUseDefaultCharSetForAllProperties);
+ }
+
+ // This has to be trapped
+ TRAPD(err,parser->InternalizeL(aSourceStream));
+ if ((err != KErrNone) && (err != KErrEof))
+ {
+ User::Leave(err);
+ }
+
+ CArrayPtr<CParserProperty>* arr = parser->ArrayOfProperties(EFalse);
+ if (!arr)
+ {
+ // Return if there are no properties
+ CleanupStack::PopAndDestroy(parser);
+ return;
+ }
+
+ // Loop through different prioritylevels
+ for (TPbkMatchPriorityLevel priorityLevel(iEngine->FieldsInfo().CreateMatchPriority());
+ !priorityLevel.End();
+ priorityLevel.Next())
+ {
+ // Loop through all the fields
+ for (TInt i=0; i<arr->Count(); i++)
+ {
+ CParserProperty* prop = arr->At(i);
+ if (prop)
+ {
+ iFieldAction->AddFieldL(aDestItem, *prop, priorityLevel);
+ }
+ }
+ }
+
+ CleanupStack::PopAndDestroy(parser); // parser
+ }
+
+/**
+ * The main Export function.
+ */
+EXPORT_C void CBCardEngine::ExportBusinessCardL(
+ RWriteStream& aDestStream,
+ CPbkContactItem& aSourceItem)
+ {
+ CParserVCard* parser = CParserVCard::NewL();
+ CleanupStack::PushL(parser);
+
+ // For Japanese: Set charset based on local variation setting
+ if (FeatureManager::FeatureSupported(KFeatureIdJapanese))
+ {
+ if (iEngine->Constants()->LocallyVariatedFeatureEnabled(EPbkLVUseJapaneseUTF8))
+ {
+ parser->SetDefaultCharSet(Versit::EUTF8CharSet);
+ }
+ else
+ {
+ parser->SetDefaultCharSet(Versit::EShiftJISCharSet);
+ }
+ parser->SetFlags(CVersitParser::EUseDefaultCharSetForAllProperties);
+ }
+
+ // use plug in for disabling encoding
+ TBCardVersitPlugin* exportPlugin = new (ELeave) TBCardVersitPlugin;
+ CleanupStack::PushL(exportPlugin);
+ parser->SetPlugIn(exportPlugin);
+
+ for (TInt i = 0; i < iExportProperties.Count(); i++)
+ {
+ ProcessExportPropertyL(*parser, aSourceItem, *iExportProperties[i]);
+ }
+
+ // Externalize the Parser to the Stream
+ parser->ExternalizeL(aDestStream);
+
+ CleanupStack::PopAndDestroy(exportPlugin);
+ CleanupStack::PopAndDestroy(parser);
+ }
+
+void CBCardEngine::ProcessExportPropertyL(
+ CParserVCard& aParser,
+ CPbkContactItem& aSourceItem,
+ const CBCardExportProperty& aExportProperty)
+ {
+ if (aExportProperty.StorageType() == EPbkVersitPropertyCDesCArray)
+ {
+ iFieldAction->ExportArrayOfFieldsL(aParser, aSourceItem, aExportProperty);
+ }
+ else
+ {
+ const CPbkFieldInfo* info = aExportProperty.InfoAt(0);
+
+ TBool doContinue = (info->Multiplicity() == EPbkFieldMultiplicityMany);
+
+ TInt index = 0;
+ do
+ {
+ TPbkContactItemField* field = aSourceItem.FindField(*info, index);
+ if (field)
+ {
+ ++index;
+ iFieldAction->ExportContactFieldL(
+ aExportProperty,
+ aParser,
+ aSourceItem,
+ *field);
+ }
+ else
+ {
+ doContinue = EFalse;
+ }
+
+ } while (doContinue);
+ }
+ }
+
+TInt CBCardEngine::GetByteFromStream(TUint8& aByte, RReadStream& aSourceStream)
+ {
+ TRAPD(err, aByte = aSourceStream.ReadUint8L());
+ return err;
+ }
+
+TInt CBCardEngine::GetLineFromStreamL(TDes& aBuf, RReadStream& aSourceStream)
+ {
+ aBuf.SetLength(0);
+ TUint8 byte=0;
+ while(GetByteFromStream(byte, aSourceStream) == KErrNone)
+ {
+ if(byte == EKeyLineFeed)
+ {
+ break;
+ }
+ if(byte != EKeyEnter)
+ {
+ if (aBuf.Length() < aBuf.MaxLength())
+ {
+ aBuf.Append(byte);
+ }
+ else
+ {
+ User::Leave(KErrCorrupt);
+ }
+ }
+ }
+ return aBuf.Length();
+ }
+
+EXPORT_C TBool CBCardEngine::ImportCompactBusinessCardL(
+ CPbkContactItem& aDestItem, RReadStream &aSourceStream)
+ {
+ TBuf<KBufferSize> buf;
+
+ // "Business Card" signature
+ if(GetLineFromStreamL(buf, aSourceStream))
+ {
+ if(buf.Match(KBusinessCardText)==KErrNotFound)
+ {
+ return EFalse;
+ }
+ }
+
+ // Name
+ if(GetLineFromStreamL(buf, aSourceStream))
+ {
+ iFieldAction->AddCompactCardFieldL(aDestItem, EPbkFieldIdLastName, buf);
+ }
+
+ // Company
+ if(GetLineFromStreamL(buf, aSourceStream))
+ {
+ iFieldAction->AddCompactCardFieldL(aDestItem, EPbkFieldIdCompanyName, buf);
+ }
+
+ // Title
+ if(GetLineFromStreamL(buf, aSourceStream))
+ {
+ iFieldAction->AddCompactCardFieldL(aDestItem, EPbkFieldIdJobTitle, buf);
+ }
+
+ // Telephone numbers
+ TInt len=0;
+ while((len = GetLineFromStreamL(buf, aSourceStream))>0)
+ {
+ TPbkFieldId fieldid = EPbkFieldIdNone;
+ if(buf.Find(KTelText)>=0)
+ {
+ fieldid = EPbkFieldIdPhoneNumberStandard;
+ }
+ else if(buf.Find(KFaxText)>=0)
+ {
+ fieldid = EPbkFieldIdFaxNumber;
+ }
+
+ if(fieldid == EPbkFieldIdNone)
+ {
+ break;
+ }
+ else if(len <= KStartPosition)
+ {
+ // no data on this field, try next
+ continue;
+ }
+
+ // Read tel num label
+ TInt position = KStartPosition;
+ HBufC* label = NULL;
+ if(buf[KStartPosition] == KOpenParenthesis)
+ {
+ position = buf.Find(KCloseParenthesis);
+ if(position == KErrNotFound)
+ {
+ continue;
+ }
+ label = HBufC::NewLC(position-KStartPosition);
+ TPtr writebuf = label->Des();
+ writebuf = KNullDesC;
+ for(TInt i=KLabelStartPosition; i<position; i++)
+ {
+ writebuf.Append(buf[i]);
+ }
+ // Jump few characters
+ position += KLabelValueDelimiterLength;
+ }
+
+ if(position < buf.Length())
+ {
+ // Read value
+ HBufC* value = HBufC::NewLC(buf.Length()-position);
+ TPtr writebuf = value->Des();
+ writebuf = KNullDesC;
+ for(TInt i=position; i<buf.Length(); i++)
+ {
+ writebuf.Append(buf[i]);
+ }
+
+ iFieldAction->AddCompactCardFieldL(aDestItem, fieldid,
+ *value, EFalse, label);
+
+ CleanupStack::PopAndDestroy(value);
+ }
+
+ if(label)
+ {
+ CleanupStack::PopAndDestroy(label);
+ }
+ }
+
+ // Email address
+ if(len)
+ {
+ iFieldAction->AddCompactCardFieldL(aDestItem,
+ EPbkFieldIdEmailAddress, buf);
+ }
+
+ // Postal address (one or more lines)
+ // First read all the address lines and store them
+ // in a list
+ CDesCArray* arr = new(ELeave) CDesCArrayFlat(2); // typically 2 lines
+ CleanupStack::PushL(arr);
+ len=0;
+ while(GetLineFromStreamL(buf, aSourceStream))
+ {
+ arr->AppendL(buf);
+ if(len)
+ {
+ len+=KSeparatorText().Length();
+ }
+ len+=buf.Length();
+ }
+
+ // Then concatenate them with commas into one string
+ // and use that as field value.
+ HBufC* fielddata = HBufC::NewLC(len);
+ TPtr writebuf = fielddata->Des();
+ writebuf = KNullDesC;
+ for(TInt i=0;i<arr->Count();i++)
+ {
+ if(i)
+ {
+ writebuf.Append(KSeparatorText);
+ }
+ writebuf.Append(arr->MdcaPoint(i));
+ }
+
+ iFieldAction->AddCompactCardFieldL(aDestItem, EPbkFieldIdPostalAddress,
+ *fielddata);
+
+ CleanupStack::PopAndDestroy(2); // fielddata, arr
+
+ return ETrue;
+ }
+
+EXPORT_C TBool CBCardEngine::SupportsFieldType(TPbkFieldId aFieldId)
+ {
+ TBool isSupported = EFalse;
+ CBCardExportProperty* property;
+
+ // Go trough the array of supported fields and try to find the fieldId
+ for (TInt i=0; i < iExportProperties.Count(); i++)
+ {
+ property = iExportProperties[i];
+ for (TInt j=0; j < property->InfoCount(); j++)
+ {
+ if (property->InfoAt(j)->FieldId() == aFieldId)
+ {
+ isSupported = ETrue;
+ break;
+ }
+ }
+ }
+ return isSupported;
+ }
+
+// End of File