pimprotocols/pbap/server/pbapserver.cpp
changeset 0 e686773b3f54
child 6 e8e3147d53eb
equal deleted inserted replaced
-1:000000000000 0:e686773b3f54
       
     1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include <s32mem.h>
       
    17 #include <e32svr.h>
       
    18 
       
    19 // KMimeVCardExtension is defined in miutmsg.h however including miutmsg.h also includes
       
    20 // flogger.h and conflicts with our inclusion of commsdebug via btaccesshostlog.h
       
    21 //#include <miutmsg.h>
       
    22 _LIT(KMimeVCardExtension, ".vcf");
       
    23 
       
    24 #include <bt_sock.h>
       
    25 #include <obex.h>
       
    26 #include <obexbttransportinfo.h>
       
    27 
       
    28 #include <cntdb.h>
       
    29 
       
    30 #include "clientserver.h"
       
    31 #include "pbapserver.h"
       
    32 #include "pbapsession.h"
       
    33 #include "pbapappheader.h"
       
    34 #include "pbapfoldertree.h"
       
    35 #include "pbapfoldertelecom.h"
       
    36 #include "pbapfolderroot.h"
       
    37 #include "pbapfoldernodepb.h"
       
    38 #include "pbapfoldernodech.h"
       
    39 #include "pbapfoldersim.h"
       
    40 #include "pbapcontactdbviews.h"
       
    41 #include "pbapauthpasswordgetter.h"
       
    42 #include "pbapxml.h"
       
    43 #include "pbapserversecuritypolicy.h"
       
    44 #include "pbaplogeng.h"
       
    45 
       
    46 #include "btaccesshostlog.h"
       
    47 
       
    48 
       
    49 _LIT8(KPBAPLocalWho, "\x79\x61\x35\xf0\xf0\xc5\x11\xd8\x09\x66\x08\x00\x20\x0c\x9a\x66");
       
    50 
       
    51 
       
    52 const TInt KBufGranularity = 100;
       
    53 const TInt KContactsDbOpenAttempts = 10;
       
    54 const TInt KContactsDbOpenDelay = 100000; //0.1 secs
       
    55 
       
    56 //
       
    57 // TCleanupItem operations - CPbapServer::ReleaseObex()
       
    58 //
       
    59 void PbapServerReleaseObex(TAny* aPtr)
       
    60 	{
       
    61 	LOG_STATIC_FUNC
       
    62 	reinterpret_cast<CPbapServer*>(aPtr)->ReleaseObex();
       
    63 	}
       
    64 
       
    65 
       
    66 void CleanupPbapServerReleaseObexPushL(CPbapServer& aPbapServer)
       
    67 	{		 
       
    68 	LOG_STATIC_FUNC
       
    69 	TCleanupItem item(PbapServerReleaseObex, &aPbapServer);
       
    70 	CleanupStack::PushL(item);
       
    71 	}	
       
    72 
       
    73 
       
    74 //
       
    75 // CPbapServerShutdown
       
    76 //
       
    77 /*static*/ CPbapServerShutdown* CPbapServerShutdown::NewL()
       
    78 	{
       
    79 	LOG_STATIC_FUNC
       
    80 	CPbapServerShutdown* self=new(ELeave) CPbapServerShutdown;
       
    81 	CleanupStack::PushL(self);
       
    82 	self->ConstructL();
       
    83 	CleanupStack::Pop(self);
       
    84 	return self;
       
    85 	}
       
    86 
       
    87 inline CPbapServerShutdown::CPbapServerShutdown()
       
    88 	: CTimer(EPriorityLow)
       
    89 	{
       
    90 	LOG_FUNC
       
    91 	CActiveScheduler::Add(this);
       
    92 	}
       
    93 
       
    94 inline void CPbapServerShutdown::ConstructL()
       
    95 	{
       
    96 	LOG_FUNC
       
    97 	CTimer::ConstructL();
       
    98 	}
       
    99 
       
   100 inline void CPbapServerShutdown::Start()
       
   101 	{
       
   102 	LOG_FUNC
       
   103 	After(KPbapServerShutdownDelay);
       
   104 	}
       
   105 
       
   106 void CPbapServerShutdown::RunL()
       
   107 	{
       
   108 	LOG_FUNC
       
   109 	CActiveScheduler::Stop();
       
   110 	}
       
   111 
       
   112 
       
   113 //
       
   114 // CPbapServer
       
   115 //
       
   116 /*static*/ CPbapServer* CPbapServer::NewL()
       
   117 	{
       
   118 	LOG_STATIC_FUNC
       
   119 	CPbapServer* self=new(ELeave) CPbapServer;
       
   120 	CleanupStack::PushL(self);
       
   121 	self->ConstructL();
       
   122 	CleanupStack::Pop(self);
       
   123 	return self;
       
   124 	}
       
   125 
       
   126 	
       
   127 CPbapServer::CPbapServer()
       
   128 : CPolicyServer(EPriorityStandard, KPbapServerPolicy, ESharableSessions)
       
   129 	{
       
   130 	LOG_FUNC
       
   131 	}
       
   132 
       
   133 
       
   134 CPbapServer::~CPbapServer()
       
   135 	{
       
   136 	LOG_FUNC
       
   137 	
       
   138 	// delete the obex server first because its destructor may call
       
   139 	// functions which this class implements
       
   140 	ReleaseObex();
       
   141 	
       
   142 	if (iAsyncRestartObex)
       
   143 		{
       
   144 		iAsyncRestartObex->Cancel();
       
   145 		delete iAsyncRestartObex;
       
   146 		}
       
   147 
       
   148 	delete iPasswordGetter;
       
   149 	delete iPassword;
       
   150 	delete iOutboundObject;
       
   151 	delete iOutboundBuffer;
       
   152 	delete iVCardExporter;
       
   153 	delete iShutdown;
       
   154 	
       
   155 	// the database must still be open when closing contact views so always 
       
   156 	// delete the object owning the views before the database
       
   157 	delete iContactViews;
       
   158 
       
   159 	delete iFolderTree;
       
   160 	delete iLogWrapper;
       
   161 	delete iContacts;
       
   162 	iFs.Close();
       
   163 	iBufStreamer.Close();
       
   164 	iAppHeaderDetails.Close();
       
   165 	}
       
   166 	
       
   167 
       
   168 void CPbapServer::ConstructL()
       
   169 	{
       
   170 	LOG_FUNC
       
   171 
       
   172 	StartL(KPbapServerName);
       
   173 
       
   174 	// ensure that the server will exit even if the 1st client fails to connect
       
   175 	iShutdown = CPbapServerShutdown::NewL();
       
   176 	
       
   177 	// create buffers ready for first obex get request
       
   178 	iOutboundBuffer = CBufFlat::NewL(KBufGranularity);
       
   179 	iOutboundObject = CObexBufObject::NewL(iOutboundBuffer);
       
   180 
       
   181 	OpenContactsDbL();
       
   182 	
       
   183 	// create contact database view manager
       
   184 	iContactViews = CPbapContactDbViews::NewL(*iContacts);
       
   185 	
       
   186 	// if there is a problem with creating a logeng client then we will continue
       
   187 	// but without any call history folders
       
   188 	TRAP_IGNORE(CreateLogEngineClientL());
       
   189 	
       
   190 	// create vCard exporter
       
   191 	iVCardExporter = CPbapVCardExporterUtil::NewL(*iContacts, iLogWrapper);
       
   192 
       
   193 	// create the restart obex callback used when an obex error occurs
       
   194  	TCallBack callback(RestartObex, this);
       
   195 	iAsyncRestartObex = new(ELeave) CAsyncCallBack(callback, CActive::EPriorityStandard);
       
   196 
       
   197 	// start shutdown timer now
       
   198 	iShutdown->Start();
       
   199 	}
       
   200 
       
   201 	
       
   202 void CPbapServer::OpenContactsDbL()
       
   203 	{
       
   204 	LOG_FUNC
       
   205 	TInt attempts=0;
       
   206 	TInt error=KErrNone;
       
   207 	while (attempts < KContactsDbOpenAttempts)
       
   208 		{
       
   209 		TRAP(error, iContacts = CContactDatabase::OpenL());
       
   210 
       
   211 		if (error==KErrLocked || error==KErrInUse)
       
   212 			{
       
   213 			// db maybe locked due to race condition so try again
       
   214 			++attempts;
       
   215 			User::After(KContactsDbOpenDelay);
       
   216 			}
       
   217 		else
       
   218 			{
       
   219 			// success or not a db locked error so exit loop
       
   220 			break;
       
   221 			}
       
   222 		}
       
   223 	if (error)
       
   224 		{
       
   225 		LOG1(_L("Contacts database failed to open, error=%d"), error);
       
   226 		User::Leave(error);	
       
   227 		}
       
   228 	}
       
   229 
       
   230 
       
   231 void CPbapServer::CreateLogEngineClientL()
       
   232 	{
       
   233 	LOG_FUNC
       
   234 	User::LeaveIfError(iFs.Connect());
       
   235 	
       
   236 	// create access to call history information
       
   237 	iLogWrapper = CPbapLogWrapper::NewL(iFs);
       
   238 	}
       
   239 
       
   240 
       
   241 void CPbapServer::BuildVirtualFolderTreeL()
       
   242 	{
       
   243 	LOG_FUNC
       
   244 
       
   245 	// create the root folder
       
   246 	CVirtualFolders* rootFolder = CVirtualFolders::NewLC();
       
   247 
       
   248 	rootFolder->PlaceFolderL(CFolderRoot::NewL(*this)); //ownership passed
       
   249 	rootFolder->AttachSubtree(TelecomSubTreeL()); //ownership passed
       
   250 	
       
   251 #ifdef __INCLUDE_SIM1_FOLDERS__
       
   252 	// create the SIM1 folder below root			
       
   253 	CVirtualFolders* sim1Folder = CVirtualFolders::NewLC();
       
   254 
       
   255 	sim1Folder->PlaceFolderL(CFolderSIM1::NewL(*this)); //ownership passed
       
   256 	sim1Folder->AttachSubtree(SIMTelecomSubTreeL()); //ownership passed
       
   257 	rootFolder->AttachSubtree(sim1Folder); //ownership passed
       
   258 
       
   259 	CleanupStack::Pop(sim1Folder);
       
   260 #endif // __INCLUDE_SIM1_FOLDERS__
       
   261 		
       
   262 	CleanupStack::Pop(rootFolder);	
       
   263 	iFolderTree = rootFolder;
       
   264 	iCurrentFolder = iFolderTree;
       
   265 	}
       
   266 
       
   267 
       
   268 CVirtualFolders* CPbapServer::TelecomSubTreeL()
       
   269 	{
       
   270 	LOG_FUNC
       
   271 	
       
   272 	// create telecom folder
       
   273 	CVirtualFolders* telecomFolder = CVirtualFolders::NewLC();
       
   274 	telecomFolder->PlaceFolderL(CFolderTelecom::NewL(*this)); //ownership passed
       
   275 	
       
   276 	// create pb sub folder
       
   277 	CVirtualFolders* pbFolder = CVirtualFolders::NewLC();
       
   278 
       
   279 	pbFolder->PlaceFolderL(CFolderNodePb::NewL(*this)); //ownership passed
       
   280 	telecomFolder->AttachSubtree(pbFolder); //ownership passed
       
   281 
       
   282 	CleanupStack::Pop(pbFolder);
       
   283 	
       
   284 	// make sure that we successfully created a logeng client
       
   285 	if (iLogWrapper && (iLogWrapper->ClientAvailable()))
       
   286 		{
       
   287 		// create ich sub folder
       
   288 		CVirtualFolders* ichFolder = CVirtualFolders::NewLC();
       
   289 
       
   290 		ichFolder->PlaceFolderL(CFolderNodeIch::NewL(*this)); //ownership passed
       
   291 		telecomFolder->AttachSubtree(ichFolder); //ownership passed
       
   292 
       
   293 		CleanupStack::Pop(ichFolder);
       
   294 
       
   295 		//create och sub folder
       
   296 		CVirtualFolders* ochFolder = CVirtualFolders::NewLC();
       
   297 
       
   298 		ochFolder->PlaceFolderL(CFolderNodeOch::NewL(*this)); //ownership passed
       
   299 		telecomFolder->AttachSubtree(ochFolder); //ownership passed
       
   300 
       
   301 		CleanupStack::Pop(ochFolder);
       
   302 
       
   303 		// create mch sub folder
       
   304 		CVirtualFolders* mchFolder = CVirtualFolders::NewLC();
       
   305 
       
   306 		mchFolder->PlaceFolderL(CFolderNodeMch::NewL(*this)); //ownership passed
       
   307 		telecomFolder->AttachSubtree(mchFolder); //ownership passed
       
   308 
       
   309 		CleanupStack::Pop(mchFolder);
       
   310 
       
   311 		// create cch sub folder
       
   312 		CVirtualFolders* cchFolder = CVirtualFolders::NewLC();
       
   313 
       
   314 		cchFolder->PlaceFolderL(CFolderNodeCch::NewL(*this)); //ownership passed
       
   315 		telecomFolder->AttachSubtree(cchFolder); //ownership passed
       
   316 
       
   317 		CleanupStack::Pop(cchFolder);
       
   318 		}
       
   319 	
       
   320 	CleanupStack::Pop(telecomFolder);	
       
   321 	return telecomFolder;
       
   322 	}
       
   323 
       
   324 #ifdef __INCLUDE_SIM1_FOLDERS__
       
   325 CVirtualFolders* CPbapServer::SIMTelecomSubTreeL()
       
   326 	{
       
   327 	LOG_FUNC
       
   328 	
       
   329 	// create SIM1 telecom folder
       
   330 	CVirtualFolders* telecomFolder = CVirtualFolders::NewLC();
       
   331 
       
   332 	telecomFolder->PlaceFolderL(CFolderSIM1Telecom::NewL(*this)); //ownership passed
       
   333 
       
   334 	// create SIM1 pb sub folder
       
   335 	CVirtualFolders* pbFolder = CVirtualFolders::NewLC();
       
   336 
       
   337 	pbFolder->PlaceFolderL(CFolderSIM1NodePb::NewL(*this)); //ownership passed
       
   338 	telecomFolder->AttachSubtree(pbFolder); //ownership passed
       
   339 
       
   340 	CleanupStack::Pop(pbFolder);
       
   341 	
       
   342 	// create SIM1 ich sub folder
       
   343 	CVirtualFolders* ichFolder = CVirtualFolders::NewLC();
       
   344 
       
   345 	ichFolder->PlaceFolderL(CFolderSIM1NodeIch::NewL(*this)); //ownership passed
       
   346 	telecomFolder->AttachSubtree(ichFolder); //ownership passed
       
   347 
       
   348 	CleanupStack::Pop(ichFolder);
       
   349 	
       
   350 	// create SIM1 och sub folder
       
   351 	CVirtualFolders* ochFolder = CVirtualFolders::NewLC();
       
   352 
       
   353 	ochFolder->PlaceFolderL(CFolderSIM1NodeOch::NewL(*this)); //ownership passed
       
   354 	telecomFolder->AttachSubtree(ochFolder); //ownership passed
       
   355 
       
   356 	CleanupStack::Pop(ochFolder);
       
   357 	
       
   358 	// create SIM1 mch sub folder
       
   359 	CVirtualFolders* mchFolder = CVirtualFolders::NewLC();
       
   360 
       
   361 	mchFolder->PlaceFolderL(CFolderSIM1NodeMch::NewL(*this)); //ownership passed
       
   362 	telecomFolder->AttachSubtree(mchFolder); //ownership passed
       
   363 
       
   364 	CleanupStack::Pop(mchFolder);
       
   365 	
       
   366 	// create SIM1 cch sub folder
       
   367 	CVirtualFolders* cchFolder = CVirtualFolders::NewLC();
       
   368 
       
   369 	cchFolder->PlaceFolderL(CFolderSIM1NodeCch::NewL(*this)); //ownership passed
       
   370 	telecomFolder->AttachSubtree(cchFolder); //ownership passed
       
   371 
       
   372 	CleanupStack::Pop(cchFolder);
       
   373 	
       
   374 	CleanupStack::Pop(telecomFolder);
       
   375 	return telecomFolder;
       
   376 	}
       
   377 #endif // __INCLUDE_SIM1_FOLDERS__
       
   378 
       
   379 /*virtual*/ CContactDatabase& CPbapServer::ContactDB() const
       
   380 	{
       
   381 	LOG_FUNC
       
   382 	return *iContacts;
       
   383 	}
       
   384 
       
   385 
       
   386 /*virtual*/ CPbapContactDbViews& CPbapServer::ContactDbViews()
       
   387 	{
       
   388 	LOG_FUNC
       
   389 	return *iContactViews;
       
   390 	}
       
   391 
       
   392 /*virtual*/ CPbapLogWrapper& CPbapServer::LogClient() const
       
   393 	{
       
   394 	LOG_FUNC
       
   395 	return *iLogWrapper;
       
   396 	}
       
   397 	
       
   398 /*virtual*/ MPbapExporter& CPbapServer::Exporter()
       
   399 	{
       
   400 	LOG_FUNC
       
   401 	return *static_cast<MPbapExporter*>(this);
       
   402 	}
       
   403 
       
   404 
       
   405 /*virtual*/ MPbapErrorReporter& CPbapServer::ErrorReporter()
       
   406 	{
       
   407 	LOG_FUNC
       
   408 	return *static_cast<MPbapErrorReporter*>(this);
       
   409 	}
       
   410 
       
   411 
       
   412 /*virtual*/ void CPbapServer::StartExport()
       
   413 	{
       
   414 	LOG_FUNC
       
   415 	__ASSERT_ALWAYS(!iExportInProgress, Panic(EPbapServerPanicExportInProgress));
       
   416 	
       
   417 	// open the obex stream ready for export
       
   418 	iBufStreamer.Open(*iOutboundBuffer);
       
   419 	
       
   420 	// set flag to indicate export started
       
   421 	iExportInProgress=ETrue;
       
   422 	}
       
   423 
       
   424 
       
   425 /*virtual*/ void CPbapServer::ExportListingBeginL()
       
   426 	{
       
   427 	LOG_FUNC
       
   428 	if(iExportInProgress == EFalse)
       
   429 		{
       
   430 		__ASSERT_DEBUG(EFalse, Panic(EPbapServerPanicNotReadyForExport));
       
   431 		User::Leave(KErrNotReady);
       
   432 		}
       
   433 	if (iExportInProgress)
       
   434 		{	
       
   435 		// write the XML DTD header
       
   436 		PbapDTD::WriteBeginL(iBufStreamer);
       
   437 		}
       
   438 	}
       
   439 
       
   440 
       
   441 /*virtual*/ void CPbapServer::ExportListingEntryL(TInt aHandle, const TDesC& aName)
       
   442 	{
       
   443 	LOG_FUNC
       
   444 	if(iExportInProgress == EFalse)
       
   445 		{
       
   446 		__ASSERT_DEBUG(EFalse, Panic(EPbapServerPanicNotReadyForExport));
       
   447 		User::Leave(KErrNotReady);
       
   448 		}
       
   449 	if (iExportInProgress)
       
   450 		{
       
   451 		// write listing entry to stream
       
   452 		PbapDTD::WriteListingEntryL(iBufStreamer, aHandle, aName);
       
   453 		}
       
   454 	}
       
   455 
       
   456 	
       
   457 /*virtual*/ void CPbapServer::ExportListingEndL()
       
   458 	{
       
   459 	LOG_FUNC
       
   460 	if(iExportInProgress == EFalse)
       
   461 		{
       
   462 		__ASSERT_DEBUG(EFalse, Panic(EPbapServerPanicNotReadyForExport));
       
   463 		User::Leave(KErrNotReady);
       
   464 		}
       
   465 	if (iExportInProgress)
       
   466 		{
       
   467 		// write the XML DTD end tag
       
   468 		PbapDTD::WriteEndL(iBufStreamer);
       
   469 		}
       
   470 	}
       
   471 
       
   472 
       
   473 /*virtual*/ void CPbapServer::ExportCallHistoryL(const CLogEvent& aEvent, TVCardVersion aFormat, TUint64 aFilter)
       
   474 	{
       
   475 	LOG_FUNC
       
   476 	if(iExportInProgress == EFalse)
       
   477 		{
       
   478 		__ASSERT_DEBUG(EFalse, Panic(EPbapServerPanicNotReadyForExport));
       
   479 		User::Leave(KErrNotReady);
       
   480 		}
       
   481 	if (iExportInProgress)
       
   482 		{
       
   483 		// convert log event to a vCard and add to stream
       
   484 		iVCardExporter->ExportCallHistoryL(aEvent, iBufStreamer, aFormat, aFilter);
       
   485 		}
       
   486 	}
       
   487 
       
   488 		
       
   489 /*virtual*/ void CPbapServer::ExportContactL(TContactItemId aContactId, TVCardVersion aFormat, TUint64 aFilter)
       
   490 	{
       
   491 	LOG_FUNC
       
   492 	if(iExportInProgress == EFalse)
       
   493 		{
       
   494 		__ASSERT_DEBUG(EFalse, Panic(EPbapServerPanicNotReadyForExport));
       
   495 		User::Leave(KErrNotReady);
       
   496 		}
       
   497 	if (iExportInProgress)
       
   498 		{	
       
   499 		// convert contact to a vCard and add to stream
       
   500 		iVCardExporter->ExportContactL(aContactId, iBufStreamer, aFormat, aFilter);
       
   501 		}
       
   502 	}
       
   503 	
       
   504 
       
   505 /*virtual*/ void CPbapServer::ExportEmptyVCardL(TVCardVersion aFormat)
       
   506 	{
       
   507 	LOG_FUNC
       
   508 	if(iExportInProgress == EFalse)
       
   509 		{
       
   510 		__ASSERT_DEBUG(EFalse, Panic(EPbapServerPanicNotReadyForExport));
       
   511 		User::Leave(KErrNotReady);
       
   512 		}
       
   513 	if (iExportInProgress)
       
   514 		{	
       
   515 		// create empty vCard and add to stream
       
   516 		iVCardExporter->ExportEmptyVCardL(iBufStreamer, aFormat);
       
   517 		}	
       
   518 	}
       
   519 
       
   520 
       
   521 /*virtual*/ void CPbapServer::ExportPhonebookSizeL(TInt aCount)
       
   522 	{
       
   523 	LOG_FUNC
       
   524 	if(iExportInProgress == EFalse)
       
   525 		{
       
   526 		__ASSERT_DEBUG(EFalse, Panic(EPbapServerPanicNotReadyForExport));
       
   527 		User::Leave(KErrNotReady);
       
   528 		}
       
   529 	if (iExportInProgress)
       
   530 		{
       
   531 		// add phonebook size to obex header, total size is 4 bytes
       
   532 		TInt currentLength = iAppHeaderDetails.Length();
       
   533 		iAppHeaderDetails.ReAllocL(currentLength+4);
       
   534 		iAppHeaderDetails.SetMax();
       
   535 		
       
   536 		// add 1 byte tag id
       
   537 		iAppHeaderDetails[currentLength] = CPbapAppHeader::EPhonebookSize;
       
   538 		
       
   539 		// add length of arguments, 2 bytes
       
   540 		iAppHeaderDetails[currentLength+1] = 2;
       
   541 		
       
   542 		// add phonebook size, 2 bytes
       
   543 		BigEndian::Put16(&iAppHeaderDetails[currentLength+2], aCount);
       
   544 		}
       
   545 	}
       
   546 
       
   547 
       
   548 /*virtual*/ void CPbapServer::ExportNewMissedCallsL(TInt aCount)
       
   549 	{
       
   550 	LOG_FUNC
       
   551 	if(iExportInProgress == EFalse)
       
   552 		{
       
   553 		__ASSERT_DEBUG(EFalse, Panic(EPbapServerPanicNotReadyForExport));
       
   554 		User::Leave(KErrNotReady);
       
   555 		}
       
   556 	if (iExportInProgress)
       
   557 		{
       
   558 		// add new missed call count to obex header, total size is 3 bytes
       
   559 		TInt currentLength = iAppHeaderDetails.Length();
       
   560 		iAppHeaderDetails.ReAllocL(currentLength+3);
       
   561 		iAppHeaderDetails.SetMax();
       
   562 		
       
   563 		// add 1 byte tag id
       
   564 		iAppHeaderDetails[currentLength] = CPbapAppHeader::ENewMissedCalls;
       
   565 
       
   566 		// add length of arguments, 1 byte
       
   567 		iAppHeaderDetails[currentLength+1] = 1;
       
   568 		
       
   569 		// add missed call count, 1 byte
       
   570 		iAppHeaderDetails[currentLength+2] = aCount;
       
   571 		}
       
   572 	}
       
   573 
       
   574 		
       
   575 /*virtual*/ void CPbapServer::FinaliseExportL()
       
   576 	{
       
   577 	LOG_FUNC
       
   578 	if(iExportInProgress == EFalse)
       
   579 		{
       
   580 		__ASSERT_DEBUG(EFalse, Panic(EPbapServerPanicNotReadyForExport));
       
   581 		User::Leave(KErrNotReady);
       
   582 		}
       
   583 	// set flag to indicate no more writing to the stream
       
   584 	if (iExportInProgress)
       
   585 		{	
       
   586 		// close the stream
       
   587 		iBufStreamer.Close();
       
   588 	
       
   589 		// add header information
       
   590 		if (iAppHeaderDetails.Length())
       
   591 			{
       
   592 			iOutboundObject->SetAppParamL(iAppHeaderDetails);
       
   593 			}
       
   594 
       
   595 		// reset app header
       
   596 		iAppHeaderDetails.Zero();
       
   597 
       
   598 		// request active mode to improve sending if object is large enough
       
   599 		const TObexTransportInfo* transInfo = iObex->TransportInfo();
       
   600 		if (transInfo && (iOutboundObject->DataBuf()->Size() > transInfo->iTransmitMtu))
       
   601 			{
       
   602 			// ignore any error, the Open() may have failed
       
   603 			iPhysLinkAdaptor.ActivateActiveRequester();
       
   604 			}
       
   605 		
       
   606 		// send over obex
       
   607 		User::LeaveIfError(iObex->RequestIndicationCallback(iOutboundObject));
       
   608 		
       
   609 		iExportInProgress=EFalse;
       
   610 		}
       
   611 	}
       
   612 
       
   613 
       
   614 /*virtual*/ void CPbapServer::CancelExport()
       
   615 	{
       
   616 	LOG_FUNC
       
   617 	// set flag to indicate
       
   618 	iExportInProgress=EFalse;
       
   619 	iAppHeaderDetails.Zero();
       
   620 	
       
   621 	// cleanup the buffers used for the get requests
       
   622 	CleanupGetRequest();
       
   623 	}
       
   624 
       
   625 
       
   626 	
       
   627 /*virtual*/ void CPbapServer::SendServiceUnavailableError()
       
   628 	{
       
   629 	LOG_FUNC
       
   630 	ReportObexError(KErrGeneral);
       
   631 	}
       
   632 
       
   633 	
       
   634 /*virtual*/ void CPbapServer::SendPreconditionFailedError()
       
   635 	{
       
   636 	LOG_FUNC
       
   637 	ReportObexError(KErrArgument);		
       
   638 	}
       
   639 
       
   640 
       
   641 /*virtual*/ void CPbapServer::SendNotFoundError()
       
   642 	{
       
   643 	LOG_FUNC
       
   644 	ReportObexError(KErrNotFound);		
       
   645 	}
       
   646 
       
   647 
       
   648 /**
       
   649  create new session
       
   650  */		
       
   651 CSession2* CPbapServer::NewSessionL(const TVersion &aVersion, const RMessage2& /*aMessage*/) const
       
   652 	{
       
   653 	LOG_FUNC
       
   654 	TVersion v(KPbapServerMajorVersionNumber,KPbapServerMinorVersionNumber,KPbapServerBuildVersionNumber);
       
   655 	if (!User::QueryVersionSupported(v,aVersion))
       
   656 		{
       
   657 		User::Leave(KErrNotSupported);
       
   658 		}
       
   659 
       
   660 	// we only support one active session
       
   661 	if (iActiveSession)
       
   662 		{
       
   663 		User::Leave(KErrInUse);
       
   664 		}
       
   665 
       
   666 	return new(ELeave) CPbapSession();
       
   667 	}
       
   668 
       
   669 
       
   670 /**
       
   671  a new session is being created Cancel the shutdown timer if it was running
       
   672  */
       
   673 void CPbapServer::AddSession()
       
   674 	{
       
   675 	LOG_FUNC
       
   676 	iActiveSession = ETrue;
       
   677 	iShutdown->Cancel();
       
   678 	}
       
   679 
       
   680 
       
   681 /**
       
   682  a session is being destroyed. Start the shutdown timer if it is the last session.
       
   683  */
       
   684 void CPbapServer::DropSession()
       
   685 	{
       
   686 	LOG_FUNC
       
   687 	iActiveSession = EFalse;	
       
   688 	iShutdown->Start();
       
   689 	}
       
   690 	
       
   691 
       
   692 void CPbapServer::StartObexL()
       
   693 	{
       
   694 	LOG_FUNC
       
   695 
       
   696 	if (!iObex)
       
   697 		{
       
   698 		TBTServiceSecurity serv;
       
   699 		serv.SetUid(KPbapServerUid);
       
   700 
       
   701 		serv.SetAuthentication(ETrue); // note: this needs to be reconsidered in light of SSP.
       
   702 		serv.SetAuthorisation(ETrue);
       
   703 		serv.SetEncryption(ETrue);
       
   704 
       
   705 		// now set up Obex...
       
   706 		TObexBluetoothProtocolInfo info;
       
   707 		info.iTransport = KObexRfcommProtocol;
       
   708 		info.iAddr.SetPort(KRfcommPassiveAutoBind);
       
   709 		info.iAddr.SetSecurity(serv);
       
   710 
       
   711 		iObex = CObexServer::NewL(info);
       
   712 		iObex->SetLocalWho(KPBAPLocalWho);
       
   713 		iObex->SetTargetChecking(CObexServer::EAlways);	
       
   714 
       
   715 		// push self onto cleanup stack to ReleaseObex if a leave
       
   716 		CleanupPbapServerReleaseObexPushL(*this);
       
   717 		
       
   718 		// start accepting requests to obex server
       
   719 		TInt error = iObex->Start(this);
       
   720 		if (error != KErrNone)
       
   721 			{
       
   722 			LOG1(_L("Error %d starting Obex server"), error);
       
   723 			User::Leave(error);
       
   724 			}
       
   725 
       
   726 		if (iPassword)
       
   727 			{
       
   728 			// a password has been set so enable obex authentication
       
   729 			TRAP(error, iObex->SetChallengeL(*iPassword));
       
   730 			if (error != KErrNone)
       
   731 				{
       
   732 				LOG1(_L("Error %d setting authentication challenge"), error);
       
   733 				User::Leave(error);
       
   734 				}		
       
   735 			}
       
   736 	
       
   737 		// obex started succesfully, retrieve assigned RFCOMM channel
       
   738 		const TObexBtTransportInfo* transportInfo = static_cast<const TObexBtTransportInfo*>(iObex->TransportInfo());
       
   739 		TUint rfcommChannel = transportInfo->iAddr.Port();
       
   740 
       
   741 		// now the RFCOMM channel is known register the SDP record to allow bluetooth connections
       
   742 		TRAP(error, RegisterWithSdpL(rfcommChannel));
       
   743 		if (error != KErrNone)
       
   744 			{
       
   745 			LOG1(_L("Error %d registering SDP record"), error);
       
   746 			User::Leave(error);
       
   747 			}
       
   748 		
       
   749 		// enable client authentication challenge handling
       
   750 		iObex->SetCallBack(*this);		
       
   751 		CleanupStack::Pop(this);
       
   752 		}
       
   753 	}
       
   754 
       
   755 
       
   756 void CPbapServer::ReleaseObex()
       
   757 	{
       
   758 	LOG_FUNC
       
   759 	
       
   760 	// stop all connections to the obex server (we need to delete the server rather
       
   761 	// than just call Stop() otherwise the rfcomm channel will not be assigned
       
   762 	// a new value when starting it again)
       
   763 	delete iObex;
       
   764 	iObex = NULL;
       
   765 		
       
   766 	// delete the stored password
       
   767 	delete iPassword;
       
   768 	iPassword = NULL;
       
   769 	
       
   770 	// release the SDP record
       
   771 	ReleaseSdpRegistration();
       
   772 	}
       
   773 	
       
   774 /*static*/ TInt CPbapServer::RestartObex(TAny* aAny)
       
   775 	{
       
   776 	LOG_STATIC_FUNC
       
   777 	CPbapServer* self = static_cast<CPbapServer*>(aAny);
       
   778 	self->DoRestartObex();
       
   779 	return KErrNone;
       
   780 	}
       
   781 	
       
   782 void CPbapServer::DoRestartObex()
       
   783 	{
       
   784 	LOG_FUNC
       
   785 
       
   786 	// We need to keep the authentication password as this re-start was not initiated
       
   787 	// by the Client side application.
       
   788 	HBufC* currentPassword = iPassword;
       
   789 	iPassword = NULL;
       
   790 	ReleaseObex();
       
   791 	
       
   792 	iPassword = currentPassword;
       
   793 	TRAPD(err, StartObexL());
       
   794 
       
   795 	if (err != KErrNone)
       
   796 		{
       
   797 		LOG1(_L("Error %d restarting Obex server"), err);
       
   798 		
       
   799 		// nothing left to do, panic server to inform client
       
   800 		Panic(EPbapServerPanicUnrecoverableObexError);
       
   801 		}
       
   802 	}
       
   803 
       
   804 #ifdef _DEBUG
       
   805 void CPbapServer::ErrorIndication(TInt aError)
       
   806 #else
       
   807 void CPbapServer::ErrorIndication(TInt /*aError*/)
       
   808 #endif
       
   809 	{
       
   810 	LOG_FUNC
       
   811 	LOG1(_L("Obex Error Indication: %d"), aError);
       
   812 
       
   813 	// this is a fatal OBEX error so reset our state...
       
   814 	CleanupOnDisconnect();
       
   815 	
       
   816 	// ...and re-start the obex server (needs to be done async from this error indication callback)
       
   817 	iAsyncRestartObex->CallBack();
       
   818 	}
       
   819 
       
   820 
       
   821 void CPbapServer::TransportUpIndication()
       
   822 	{
       
   823 	LOG_FUNC
       
   824 	// Availablity is updated here in a deviation from the specification which 
       
   825 	// defines the Pbap session as existing from the time the OBEX connection is 
       
   826 	// established. Since OBEX can only maintain one connection over BT in the 
       
   827 	// current implemenation it is more practical for us to set our availablity now
       
   828 	// instead of waiting for the OBEX connection as the RFComm channel is already 
       
   829 	// closed effectively making our service unavailable
       
   830 	UpdateAvailability(EPbapUnavailable);
       
   831 	}
       
   832 
       
   833 	
       
   834 void CPbapServer::TransportDownIndication()
       
   835 	{
       
   836 	LOG_FUNC
       
   837 	// underlying transport has disconnected
       
   838 	UpdateAvailability(EPbapAvailable);
       
   839 	CleanupOnDisconnect();
       
   840 	}
       
   841 
       
   842 	
       
   843 void CPbapServer::ObexConnectIndication(const TObexConnectInfo& aRemoteInfo, const TDesC8& /*aInfo*/)
       
   844 	{
       
   845 	LOG_FUNC
       
   846 	LOG(_L("Connect packet target header:"));
       
   847 	LOGHEXDESC(aRemoteInfo.iTargetHeader);
       
   848 
       
   849 	if (aRemoteInfo.iTargetHeader!=KPBAPLocalWho)
       
   850 		{
       
   851 		__ASSERT_DEBUG(EFalse, Panic(EPbapServerPanicInvalidTargetHeader));
       
   852 		}
       
   853 
       
   854 	else
       
   855 		{
       
   856 		// build the virtual folder tree at the start of the session. Failure to build
       
   857 		// the folder tree is handled later with error respones to get/set path requests
       
   858 		TRAP_IGNORE(BuildVirtualFolderTreeL());
       
   859 		
       
   860 		// get remote address
       
   861 		TSockAddr sockAddr;
       
   862 		iObex->RemoteAddr(sockAddr);
       
   863 		TBTDevAddr devAddr = static_cast<TBTSockAddr>(sockAddr).BTAddr();
       
   864 		
       
   865 		// create a physical links adaptor
       
   866 		if (iSocketServ.Connect() == KErrNone)
       
   867 			{
       
   868 			// don't store the error from Open, any further sniff/active requests will not
       
   869 			// succeed but this will not stop any functionality
       
   870 			if (iPhysLinkAdaptor.Open(iSocketServ, devAddr) == KErrNone)
       
   871 				{
       
   872 				// request sniff straight away as we will request active mode when it is
       
   873 				// required
       
   874 				iPhysLinkAdaptor.ActivateSniffRequester();
       
   875 				}
       
   876 			}
       
   877   		}
       
   878 	}
       
   879 
       
   880 
       
   881 void CPbapServer::ObexDisconnectIndication(const TDesC8& /*aInfo*/)
       
   882 	{
       
   883 	LOG_FUNC
       
   884 	CleanupOnDisconnect();
       
   885 	}
       
   886 
       
   887 
       
   888 void CPbapServer::PutRequestIndication()
       
   889 	{
       
   890 	LOG_FUNC
       
   891 	// Always return a Bad Request error in response to PUT requests
       
   892 	ReportObexError(KErrCorrupt);
       
   893 	}
       
   894 
       
   895 
       
   896 TInt CPbapServer::PutPacketIndication()
       
   897 	{
       
   898 	LOG_FUNC
       
   899 	// the remote device should have handled the PUT request error and not sent
       
   900 	// any data. If not then just respond to each packet with another error
       
   901 	return KErrIrObexRespForbidden;
       
   902 	}
       
   903 
       
   904 	
       
   905 void CPbapServer::PutCompleteIndication()
       
   906 	{
       
   907 	LOG_FUNC
       
   908 	// the remote device should have handled the PUT request error and not sent
       
   909 	// any data. If not then just respond with an error 
       
   910 	ReportObexError(KErrAccessDenied);
       
   911 	}
       
   912 
       
   913 
       
   914 // report an OBEX error based on a Symbian global error code
       
   915 void CPbapServer::ReportObexError(TInt aSymbianError)
       
   916 	{
       
   917 	TObexResponse obexErr = ERespSuccess;
       
   918 	
       
   919 	switch (aSymbianError)
       
   920 		{
       
   921 		case KErrAccessDenied: // the request is barred
       
   922 			obexErr = ERespForbidden;
       
   923 			break;
       
   924 			
       
   925 		case KErrNotFound: // the requested folder doesnot exist
       
   926 			obexErr = ERespNotFound;
       
   927 			break;
       
   928 
       
   929 		case KErrNotSupported: // the folder does not support get requests (e.g SIM repositories not implemented)
       
   930 			obexErr = ERespNotImplemented;
       
   931 			break;
       
   932 
       
   933 		case KErrArgument: // invalid parameter value in header
       
   934 			obexErr = ERespPreCondFailed;
       
   935 			break;
       
   936 
       
   937 		case KErrCorrupt: // badly formatted header
       
   938 			obexErr = ERespBadRequest;
       
   939 			break;
       
   940 
       
   941 		case KErrGeneral:
       
   942 		default: // another error stopped request completing (e.g out of memory)
       
   943 			obexErr = ERespServiceUnavailable;
       
   944 			break;			
       
   945 		}
       
   946 	iObex->RequestIndicationCallbackWithError(obexErr);
       
   947 	
       
   948 	// get request failed so clean up for the next one
       
   949 	CleanupGetRequest();
       
   950 	}
       
   951 		
       
   952 void CPbapServer::GetRequestIndication(CObexBaseObject* aRequiredObject)
       
   953 	{
       
   954 	LOG_FUNC
       
   955 	TRAPD(error, DoGetRequestIndicationL(aRequiredObject));
       
   956 	if (error != KErrNone)
       
   957 		{
       
   958 		ReportObexError(error);
       
   959 		}
       
   960 	}
       
   961 
       
   962 		
       
   963 void CPbapServer::DoGetRequestIndicationL(CObexBaseObject* aRequiredObject)
       
   964 	{
       
   965 	LOG_FUNC
       
   966 	CPbapAppHeader* appHeader = CPbapAppHeader::NewL();
       
   967 	CleanupStack::PushL(appHeader);
       
   968 	
       
   969 	// parse the application parameters
       
   970 	appHeader->ParseL(aRequiredObject->AppParam());
       
   971 		
       
   972 	// determine the operation from the object type and parsed application params	
       
   973 	TPbapOperation operation = appHeader->DeterminePBAPOperationL(aRequiredObject->Type());
       
   974 	
       
   975 	// we only allow one get operation at a time
       
   976 	if (iGetRequestFolder)
       
   977 		{
       
   978 		// get operation in progress
       
   979 		User::Leave(KErrInUse);
       
   980 		}
       
   981 		
       
   982 	// check name for .vcf extension
       
   983 	TPtrC name = aRequiredObject->Name();		
       
   984 	if (name.Right(KMimeVCardExtension().Length())==KMimeVCardExtension())
       
   985 		{
       
   986 		if (operation == EPullVCardListing)
       
   987 			{
       
   988 			// we found a .vcf extension but shouldn't have
       
   989 			User::Leave(KErrArgument);
       
   990 			}
       
   991 			
       
   992 		// trim extension
       
   993 		name.Set(name.Left(name.Length()-KMimeVCardExtension().Length()));
       
   994 		}
       
   995 	else if ((operation == EPullPhoneBook) || (operation == EPullVCard))
       
   996 		{
       
   997 		// we didn't find a .vcf extension but should have
       
   998 		User::Leave(KErrArgument);		
       
   999 		}
       
  1000 	
       
  1001 	// create a copy of the trimmed name so that it can be modified to remove the path
       
  1002 	// information when we set iGetRequestFolder below
       
  1003 	RBuf objectName;
       
  1004 	objectName.CleanupClosePushL();
       
  1005 	objectName.CreateL(name);
       
  1006 
       
  1007 	// navigate to folder (the path is always absolute for x-bt/phonebook type requests)
       
  1008 	iGetRequestFolder = ResolvePath(objectName, appHeader->IsAbsolutePathOp());
       
  1009 
       
  1010 	// the remaining object name might be a file representation of a phonebook
       
  1011 	// (e.g pb.vcf) if so it should have a matching folder representation. If this
       
  1012 	// is true then route the get request to this folder
       
  1013 	if (iGetRequestFolder && objectName.Length() && operation != EPullVCard)
       
  1014 		{
       
  1015 		LOG(_L("Re-routing Get request from file representation to folder representation"));
       
  1016 		CVirtualFolders* subFolder = iGetRequestFolder->NavigateFolder(objectName);
       
  1017 		if (subFolder)
       
  1018 			{
       
  1019 			iGetRequestFolder = subFolder;
       
  1020 			objectName.Zero(); // no more information so set length of objectName to zero
       
  1021 			}
       
  1022 		}
       
  1023 
       
  1024 	// let the folder handle the get request. The request is completed asynchronously
       
  1025 	// so it is the folders responsibilty to notify obex when processing is complete	
       
  1026 	if (iGetRequestFolder)
       
  1027 		{
       
  1028 		// To supress false positive coverity error for alias and double_free from cleanup stack for appHeader.
       
  1029 		// The function Get takes ownership of appHeader by aliasing and does its own destruction of it either immediately on error                    
       
  1030 		// or when finnished with the object. 
       
  1031 		// coverity[double_free]
       
  1032 		TInt error = iGetRequestFolder->Folder().Get(objectName, appHeader);
       
  1033 		if (error != KErrNone)
       
  1034 			{
       
  1035 			LOG1(_L("Error %d from issuing Get to folder object"), error);
       
  1036 			ReportObexError(error);
       
  1037 			}
       
  1038 			
       
  1039 		// ownership of appHeader passed so don't destroy it
       
  1040 		CleanupStack::PopAndDestroy(); //objectName
       
  1041 		CleanupStack::Pop(); //appHeader
       
  1042 		}
       
  1043 	else
       
  1044 		{
       
  1045 		CleanupStack::PopAndDestroy(2); //appHeader, objectName
       
  1046 		ReportObexError(KErrNotFound);
       
  1047 		}
       
  1048 	}
       
  1049 
       
  1050 
       
  1051 /**
       
  1052 Return folder which request will be operating on, and modify passed in path
       
  1053 descriptor to contain only the file name
       
  1054 */
       
  1055 CVirtualFolders* CPbapServer::ResolvePath(TDes& aPath, TBool aAbsolute) const
       
  1056 	{
       
  1057 	LOG_FUNC
       
  1058 	LOG2(_L("Resolving path %S, [absolute=%d]"), &aPath, aAbsolute);
       
  1059 
       
  1060 	const TChar KSlash('/');
       
  1061 	TInt index = 0;
       
  1062 	
       
  1063 	// it is ok to have a NULL iFolderTree as we ignore any problems we had when
       
  1064 	// building it so just return NULL
       
  1065 	if (!iFolderTree)
       
  1066 		{
       
  1067 		return NULL;
       
  1068 		}
       
  1069 	
       
  1070 	// if we have a iFolderTree then we must have a iCurrentFolder
       
  1071 	if(!iCurrentFolder)
       
  1072 		{
       
  1073 		__ASSERT_DEBUG(EFalse, Panic(EPbapServerPanicNoCurrentFolder));
       
  1074 		return NULL;
       
  1075 		}
       
  1076 		
       
  1077 	// start at root if absolute path or the current folder if relative path
       
  1078 	CVirtualFolders* nextTree = aAbsolute ? iFolderTree : iCurrentFolder;
       
  1079 
       
  1080 	if (aPath.Length()>=1) // blank means dont change folder
       
  1081 		{
       
  1082 		if (aPath[index]==KSlash)
       
  1083 			{
       
  1084 			aPath.Delete(index,1);
       
  1085 			nextTree = iFolderTree;
       
  1086 			}
       
  1087 
       
  1088 		do
       
  1089 			{
       
  1090 			index = aPath.Locate(KSlash);
       
  1091 			if (index!=KErrNotFound)
       
  1092 				{
       
  1093 				// try to enter subfolder
       
  1094 				TPtrC folder(aPath.Left(index));
       
  1095 				nextTree = nextTree->NavigateFolder(folder);
       
  1096 				if (!nextTree)
       
  1097 					{
       
  1098 					// faulty path spec
       
  1099 					nextTree = NULL;
       
  1100 					break;
       
  1101 					}
       
  1102 				else
       
  1103 					{
       
  1104 					// trim off this bit of path AND the '/'!
       
  1105 					aPath.Delete(0, index+1);
       
  1106 					}
       
  1107 				}
       
  1108 			} while (index!=KErrNotFound);
       
  1109 		}
       
  1110 						
       
  1111 	return nextTree;
       
  1112 	}
       
  1113 
       
  1114 
       
  1115 TInt CPbapServer::GetPacketIndication()
       
  1116 	{
       
  1117 	LOG_FUNC
       
  1118 	// do nothing (the PSE doesnot support a UI with progress updates)
       
  1119 	return KErrNone;
       
  1120 	}
       
  1121 
       
  1122 	
       
  1123 void CPbapServer::GetCompleteIndication()
       
  1124 	{
       
  1125 	LOG_FUNC
       
  1126 
       
  1127 	TInt err = iObex->RequestCompleteIndicationCallback(KErrNone);
       
  1128 	__ASSERT_DEBUG(err==KErrNone, Panic(EPbapServerPanicUnexpectedError));
       
  1129 
       
  1130 	// prepare for next request
       
  1131 	CleanupGetRequest();
       
  1132 	}
       
  1133 
       
  1134 	
       
  1135 void CPbapServer::SetPathIndication(const CObex::TSetPathInfo& aPathInfo, const TDesC8& /*aInfo*/)
       
  1136 	{
       
  1137 	LOG_FUNC
       
  1138 	
       
  1139 	TInt err = KErrNone;
       
  1140 
       
  1141 	// it is ok to have a NULL iFolderTree as we ignore any problems we had when
       
  1142 	// building it
       
  1143 	if (!iFolderTree)
       
  1144 		{
       
  1145 		LOG(_L("Folder tree not created"));
       
  1146 		err = KErrNotFound;
       
  1147 		}
       
  1148 	else if (aPathInfo.Parent())
       
  1149 		{
       
  1150 		LOG(_L("Set folder to parent"));
       
  1151 
       
  1152 		// if we have a iFolderTree then we must have a iCurrentFolder
       
  1153 		if(!iCurrentFolder)
       
  1154 			{
       
  1155 			__ASSERT_DEBUG(EFalse, Panic(EPbapServerPanicNoCurrentFolder));
       
  1156 			err = KErrNotFound;
       
  1157 			}
       
  1158 		else
       
  1159 			{
       
  1160 			// move to parent folder if it exists (it will not if already at root)
       
  1161 			CVirtualFolders* folder = iCurrentFolder->ParentFolder();
       
  1162 			if (folder)
       
  1163 				{
       
  1164 				iCurrentFolder = folder;
       
  1165 				}
       
  1166 			else
       
  1167 				{
       
  1168 				err = KErrNotFound;
       
  1169 				}
       
  1170 			}
       
  1171 		}
       
  1172 	else if (aPathInfo.iNamePresent)
       
  1173 		{
       
  1174 		if (aPathInfo.iName!=KNullDesC)
       
  1175 			{
       
  1176 			LOG1(_L("Set folder to child [%S]"), &aPathInfo.iName);
       
  1177 
       
  1178 			// if we have a iFolderTree then we must have a iCurrentFolder
       
  1179 			if(!iCurrentFolder)
       
  1180 				{
       
  1181 				__ASSERT_DEBUG(EFalse, Panic(EPbapServerPanicNoCurrentFolder));
       
  1182 				err = KErrNotFound;
       
  1183 				}
       
  1184 			else
       
  1185 				{
       
  1186 				CVirtualFolders* folder = iCurrentFolder->NavigateFolder(aPathInfo.iName);
       
  1187 				if (folder)
       
  1188 					{
       
  1189 					iCurrentFolder = folder;
       
  1190 					}
       
  1191 				else
       
  1192 					{
       
  1193 					err = KErrNotFound;
       
  1194 					}
       
  1195 				}
       
  1196 			}
       
  1197 		else
       
  1198 			{
       
  1199 			LOG(_L("Set folder to root"));
       
  1200 
       
  1201 			// if we have a iFolderTree then we must have a iCurrentFolder
       
  1202 			if(!iCurrentFolder)
       
  1203 				{
       
  1204 				__ASSERT_DEBUG(EFalse, Panic(EPbapServerPanicNoCurrentFolder));
       
  1205 				err = KErrNotFound;
       
  1206 				}
       
  1207 
       
  1208 			iCurrentFolder = iFolderTree;
       
  1209 			}
       
  1210 		}
       
  1211 	else
       
  1212 		{
       
  1213 		// this is not a request to change to the parent folder therefore we should have a name
       
  1214 		// header but we don't, return error
       
  1215 		LOG(_L("No Name header present"));
       
  1216 		err = KErrArgument;
       
  1217 		}
       
  1218 	
       
  1219 	// return any obex errors
       
  1220 	if (err == KErrNotFound)
       
  1221 		{
       
  1222 		LOG(_L("Error folder does not exist"));
       
  1223 		iObex->RequestCompleteIndicationCallback(ERespNotFound);	
       
  1224 		}
       
  1225 	else if (err == KErrArgument)
       
  1226 		{
       
  1227 		LOG(_L("Error invalid argument"));
       
  1228 		iObex->RequestCompleteIndicationCallback(ERespPreCondFailed);	
       
  1229 		}
       
  1230 	else
       
  1231 		{		
       
  1232 		iObex->RequestCompleteIndicationCallback(KErrNone);	
       
  1233 		}
       
  1234 	}
       
  1235 
       
  1236 	
       
  1237 void CPbapServer::AbortIndication()
       
  1238 	{
       
  1239 	LOG_FUNC
       
  1240 	
       
  1241 	// the get request was aborted during the obex transfer (i.e. after processing
       
  1242 	// the request had completed). So just clean up the obex buffers
       
  1243 	CleanupGetRequest();
       
  1244 	}
       
  1245 
       
  1246 
       
  1247 void CPbapServer::CancelIndicationCallback()
       
  1248 	{
       
  1249 	LOG_FUNC
       
  1250 	// the get request was cancelled before sending any data.
       
  1251 	// so cancel any ongoing asynchronous processing and cleanup obex buffers
       
  1252 	if (iGetRequestFolder)
       
  1253 		{
       
  1254 		iGetRequestFolder->Folder().CancelGet();
       
  1255 		}
       
  1256 	
       
  1257 	CleanupGetRequest();
       
  1258 	}
       
  1259 
       
  1260 void CPbapServer::GetUserPasswordL(const TDesC& aRealm)
       
  1261 	{
       
  1262 	LOG_FUNC
       
  1263 	LOG1(_L("Authentication challenge [Realm = %S]"), &aRealm);
       
  1264 
       
  1265 	delete iPasswordGetter;
       
  1266 	iPasswordGetter = NULL;
       
  1267 	iPasswordGetter = CPbapAuthPasswordGetter::NewL(*this);
       
  1268 
       
  1269 	// get the Bluetooth device address of the client making the authentication challenge
       
  1270 	TSockAddr sockAddr;
       
  1271 	iObex->RemoteAddr(sockAddr);
       
  1272 	TBTDevAddr devAddr = static_cast<TBTSockAddr>(sockAddr).BTAddr();
       
  1273 
       
  1274 	// start async password request
       
  1275 	iPasswordGetter->GetPassword(aRealm, devAddr);
       
  1276 	}
       
  1277 
       
  1278 void CPbapServer::HandlePasswordRetrieved(TInt aError, const TDesC& aPassword)
       
  1279 	{
       
  1280 	LOG_FUNC
       
  1281 	
       
  1282 	if (aError == KErrNone)
       
  1283 		{
       
  1284 		// if we successfully got a password, pass it to obex
       
  1285 		TRAP(aError, iObex->UserPasswordL(aPassword));
       
  1286 		}
       
  1287 		
       
  1288 	if (aError != KErrNone)
       
  1289 		{
       
  1290 		LOG1(_L("Error %d creating response to authentication challenge"), aError);
       
  1291 		// creating the challenge response has failed. Since there is no way to report
       
  1292 		// the error to the obex server the only option is to force a reset of the
       
  1293 		// connection state by restarting the server
       
  1294 		iObex->Stop();
       
  1295 		aError = iObex->Start(this);
       
  1296 		if (aError != KErrNone)
       
  1297 			{
       
  1298 			LOG1(_L("Error %d restarting Obex server"), aError);
       
  1299 			ReleaseObex();
       
  1300 			
       
  1301 			// nothing left to do, panic server to inform client
       
  1302 			Panic(EPbapServerPanicUnrecoverableObexError);
       
  1303 			}
       
  1304 		}
       
  1305 	}
       
  1306 
       
  1307 void CPbapServer::SetPasswordL(HBufC* aPassword)
       
  1308 	{
       
  1309 	LOG_FUNC
       
  1310 	if (iObex)
       
  1311 		{
       
  1312 		// the obex server exists so set its challenge now
       
  1313 		iObex->SetChallengeL(*aPassword);
       
  1314 		}
       
  1315 	// store the password (transfers ownership)
       
  1316 	delete iPassword;
       
  1317 	iPassword = aPassword;
       
  1318 	}
       
  1319 
       
  1320 void CPbapServer::CleanupGetRequest()
       
  1321 	{
       
  1322 	LOG_FUNC
       
  1323 
       
  1324 	// request sniff mode again as get request finished, ignore errors
       
  1325 	iPhysLinkAdaptor.ActivateSniffRequester();
       
  1326 
       
  1327 	// clean the exporter
       
  1328 	if (iGetRequestFolder)
       
  1329 		{
       
  1330 		iGetRequestFolder->Folder().GetComplete();
       
  1331 		}
       
  1332 	
       
  1333 	iGetRequestFolder = NULL;
       
  1334 	iOutboundBuffer->Reset();
       
  1335 	iOutboundObject->Reset();
       
  1336 	iBufStreamer.Close();
       
  1337 	}
       
  1338 
       
  1339 
       
  1340 void CPbapServer::CleanupOnDisconnect()
       
  1341 	{
       
  1342 	LOG_FUNC
       
  1343 	
       
  1344 	CleanupGetRequest();
       
  1345 	
       
  1346 	// close physical links adaptor
       
  1347 	iPhysLinkAdaptor.Close();
       
  1348 	iSocketServ.Close();
       
  1349 	
       
  1350 	// destroy the virtual folder tree when the session ends
       
  1351 	delete iFolderTree;
       
  1352 	iFolderTree = NULL;
       
  1353 	iCurrentFolder = NULL;
       
  1354 		
       
  1355 	// close contacts views to save memory (this will also cancel any current requests to sort and search views)
       
  1356  	iContactViews->CloseAllViews();
       
  1357 
       
  1358 	// make sure the authentication notifier is cancelled by deleting its handler
       
  1359 	delete iPasswordGetter;
       
  1360 	iPasswordGetter = NULL;
       
  1361 	}
       
  1362 
       
  1363 
       
  1364 void Panic(TPbapServerPanicCode aPanic)
       
  1365 	{
       
  1366 	LOG_STATIC_FUNC
       
  1367 	User::Panic(KPbapServerPanic, aPanic);
       
  1368 	}
       
  1369 
       
  1370 
       
  1371 /**
       
  1372  Perform all server initialisation, in particular creation of the
       
  1373  scheduler and server and then run the scheduler
       
  1374  */
       
  1375 static void RunServerL()
       
  1376 	{
       
  1377 	LOG_STATIC_FUNC
       
  1378 
       
  1379 	// naming the server thread after the server helps to debug panics	
       
  1380 	User::RenameThread(KPbapServerName); 
       
  1381 			
       
  1382 	// create and install the active scheduler we need
       
  1383 	CActiveScheduler* scheduler=new(ELeave) CActiveScheduler;
       
  1384 	CleanupStack::PushL(scheduler);
       
  1385 	CActiveScheduler::Install(scheduler);
       
  1386 
       
  1387 	// create the server (leave it on the cleanup stack)
       
  1388 	CPbapServer* server = CPbapServer::NewL();
       
  1389 	CleanupStack::PushL(server);
       
  1390 
       
  1391 	// initialisation complete, now signal the client thread
       
  1392 	RProcess::Rendezvous(KErrNone);
       
  1393 
       
  1394 	// ready to run
       
  1395 	CActiveScheduler::Start();
       
  1396 
       
  1397 	// cleanup the server and scheduler
       
  1398 	CleanupStack::PopAndDestroy(2, scheduler);
       
  1399 	}
       
  1400 
       
  1401 
       
  1402 /**
       
  1403  Server process entry-point.
       
  1404  @return  KErrNone or a standard Symbian error code.
       
  1405  */
       
  1406 TInt E32Main()
       
  1407 	{
       
  1408 	__UHEAP_MARK;
       
  1409 
       
  1410 #ifdef __FLOG_ACTIVE
       
  1411 	// connect to logger
       
  1412 	(void)CBtLog::Connect();
       
  1413 #endif
       
  1414 
       
  1415 	CTrapCleanup* cleanup=CTrapCleanup::New();
       
  1416 	TInt r=KErrNoMemory;
       
  1417 	if (cleanup)
       
  1418 		{
       
  1419 		TRAP(r, RunServerL());
       
  1420 		delete cleanup;
       
  1421 		}
       
  1422 
       
  1423 #ifdef __FLOG_ACTIVE
       
  1424 	// close logger connection
       
  1425 	CBtLog::Close();
       
  1426 #endif
       
  1427 
       
  1428 	__UHEAP_MARKEND;
       
  1429 	return r;
       
  1430 	}