/***********************************************************************
 * 
 *  Copyright (C) 2005-2006 Novell, Inc. All Rights Reserved.
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; version 2.1
 *  of the License.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Library Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, Novell, Inc.
 * 
 *  To contact Novell about this file by physical or electronic mail, 
 *  you may find current contact information at www.novell.com.
 * 
 ***********************************************************************/

namespace Novell.CASA.GUI {


	using System;		
	using System.IO;
	using System.Collections;
	using System.Xml;
	using System.Xml.XPath;
	using System.Xml.Xsl;
	using GLib;
	using Gtk;	
	using Novell.CASA.DataEngines;

	public class StoreDataInterface
	{
				
		private static XmlDocument ccfDoc;
		private static AD ad;
		
		private const string CCFXML_ELEMENT_MICASA_KEYCHAIN		= "Keychain",
							  CCFXML_ELEMENT_GKEYRING_KEYRING	= "Keyring",
							  CCFXML_ELEMENT_KWALLET_WALLET		= "Wallet",
							  CCFXML_ELEMENT_FIREFOX_PROFILE		= "Profile",
							  CCFXML_ELEMENT_SECRET				= "Secret",
							  CCFXML_ELEMENT_FOLDER				= "Folder",
							  CCFXML_ATTRIBUTE_FOLDERNAME		= "Name",
							  CCFXML_ELEMENT_TYPE 				= "Type",
							  CCFXML_ELEMENT_KEY					= "Key",
							  CCFXML_ELEMENT_VALUE				= "Value",
							  CCFXML_ELEMENT_TIME				= "Time",
							  CCFXML_ELEMENT_TIME_ZONE			= "Zone",
							  CCFXML_ELEMENT_TIME_CREATION		= "Creation",
							  CCFXML_ELEMENT_TIME_MODIFIED		= "Modified",
							  CCFXML_ELEMENT_TIME_ACCESSED		= "Accessed",
							  CCFXML_ATTRIBUTE_ID				= "ID",
							  CCFXML_ATTRIBUTE_MICASA_SYNCH		= "Synch",
							  CCFXML_ATTRIBUTE_GKEYRING_TYPE		= "Type",
							  CCFXML_ATTRIBUTE_WALLETLASTACCESSEDTIME = "LastAcctime";

		
		
		///#######################################################################
		/// INIT
				
		/// <summary>
		/// Initializes the CCF from miCASA-D
		/// </summary>
		public static int Init()
		{
			Logger.DbgLog("GUI:StoreDataInterface.StoreDataInterface() - BEGIN");
			
			try 
			{
				ccfDoc = new XmlDocument();
 				ad = new AD(); 	
			
				//Init CCF from a XML Document -FIXME: -Remove this 
				//ccfDoc.Load("ccfv3.xml");
			}
 			catch(Exception exp)
 			{ 				
 				Logger.DbgLog("GUI:StoreDataInterface.Init() - EXCEPTION" + exp.ToString());
 				//Common.ShowErrorDialog( exp );
 				return( Common.STATUS_STORE_ADINITFAILED );
 			}
 			
			Logger.DbgLog("GUI:StoreDataInterface.StoreDataInterface() - END");
			return( Common.STATUS_SUCCESS );
		}
		
	
		
		///#######################################################################
		/// AGGREGATE A SPECIFIC STORE
		
		/// <summary>
		/// Initializes the CCF from miCASA-D
		/// </summary>
		public static int AggregateStore(int storeIDentifier)
		{				
			Logger.DbgLog("GUI:StoreDataInterface.AggregateStore()");
			
			try
			{					
				return( ad.AggregateStore(ccfDoc, storeIDentifier) );				
			}
 			catch(Exception exp)
 			{ 				
 				Logger.DbgLog("GUI:StoreDataInterface.AggregateStore() - EXCEPTION" + exp.ToString());
 				return( Common.STATUS_STORE_AGGREGATEFAILED );
 			}
		}
		
		
		
		///#######################################################################
		/// REFRESH ALL STORES
				
		/// <summary>		
		/// Initializes the CCF from miCASA-D
		/// </summary>
		public static int RefreshAllStores()
		{
			Logger.DbgLog("GUI:StoreDataInterface.RefreshAllStores() - BEGIN");
			
			try
			{				
				ccfDoc = ad.Aggregate();					
			}
			catch(Exception exp)
 			{ 				
 				Logger.DbgLog("GUI:StoreDataInterface.RefreshAllStores() - EXCEPTION" + exp.ToString());
 				return( Common.STATUS_STORE_AGGREGATEFAILED );	
			}			
			Logger.DbgLog("GUI:StoreDataInterface.RefreshAllStores() - END");
			return( Common.STATUS_SUCCESS ); 
		}
		
		
		///#######################################################################
		/// MASTER PASSWORD				
		/// <summary>
		/// 
		/// </summary>
		public static bool IsMasterPasswordSet(int StoreID)
		{
			return( ad.IsMasterPasswordSet(StoreID) );		
		}
		
		public static bool VerifyMasterPassword(string masterPassword, int StoreID)
		{		
			return( ad.VerifyMasterPassword(masterPassword, StoreID) );
		}

		
		///#######################################################################
		/// READ STORE				
		/// <summary>
		/// Gets the GUI Data store
		/// </summary>
		public static int ReadStore(int storeIDentifier,ref Gtk.TreeStore ls)
		{
			Logger.DbgLog("GUI:StoreDataInterface.ReadStore()");
			
			//Common Keys
			string 	 storeChainKey 		 = CCFXML_ELEMENT_MICASA_KEYCHAIN;
			
			//TreeStore structure
			string 	 secretID 			 = null;
			string[] strKeyArray 		 = null;			
			string[] strValueArray 		 = null;
			string 	 storeID 			 = null;
			string[] strNativeKeyArray 	 = new string[Common.MAX_NATIVE_ELEMENTS];
			string[] strNativeValueArray = new string[Common.MAX_NATIVE_ELEMENTS];
			
			//Vars for ccf data
			string 	 folderName 		 = null;
			string 	 typeID 			 = null;
			string 	 modifiedTime 		 = null;
			string 	 synch 				 = null;
			string 	 synchType 			 = null;
			
			//Flags & Variables
			bool 	 bKey				 = false;
			bool 	 bEndOfSecret		 = false;
			
			//bool bEndOfTime=false;
			string 	 ccfPath			 = null;
			
			//Counters 
			int 	 noOfSecretsFound	 = 0;
			int 	 noOfKeys			 = 0;
			int 	 noOfKeysFound		 = 0;

			//Init Native Information TypeNames
			strNativeKeyArray[Common.INDEX_NATIVEINFO_FOLDERNAME] 	= Common.NATIVEINFO_FOLDERNAME;
			strNativeKeyArray[Common.INDEX_NATIVEINFO_TYPEID]		= Common.NATIVEINFO_TYPEID;
			strNativeKeyArray[Common.INDEX_NATIVEINFO_SYNC]		    = Common.NATIVEINFO_SYNC;
			strNativeKeyArray[Common.INDEX_NATIVEINFO_SYNCTYPE]	    = Common.NATIVEINFO_SYNCTYPE;
			strNativeKeyArray[Common.INDEX_NATIVEINFO_MODIFIEDTIME] = Common.NATIVEINFO_MODIFIEDTIME;
		
			//Form the XPATH Query definitions
			if( storeIDentifier == Common.STORE_MICASA )
			{				
				ccfPath = "//CCF/miCASA";
				storeChainKey = CCFXML_ELEMENT_MICASA_KEYCHAIN;
			}
			else if( storeIDentifier == Common.STORE_GNOMEKEYRING )
			{				
				ccfPath = "//CCF/GK";
				storeChainKey = CCFXML_ELEMENT_GKEYRING_KEYRING;
			}
			else if( storeIDentifier == Common.STORE_KDEWALLET )
			{				
				ccfPath = "//CCF/KWallet";
				storeChainKey = CCFXML_ELEMENT_KWALLET_WALLET;
			}
			else if( storeIDentifier == Common.STORE_FIREFOX )
			{				
				ccfPath = "//CCF/FireFox";
				storeChainKey = CCFXML_ELEMENT_FIREFOX_PROFILE;
			}
			else
				return( Common.STATUS_STORE_INVALIDSTOREID );

			try
			{
			
			XPathNavigator nav = ccfDoc.CreateNavigator();
			XPathNodeIterator iter = null;
			string ccfExtPath = null;

			//Query on the CCF and point to the store 
			iter = nav.Select(ccfPath);
			if( 0 == iter.Count )
				return( Common.STATUS_STORE_DATANOTFOUNDINSTORE );
								
			//Enumerate all store instances [storeID's-Keychain\Wallet\Profile\Keyring]
			while( iter.MoveNext() )
			{//Get Next Store instance. Ideally this should always be 1

				//Get all descendants of this store. Ideally this should always be keychains
				//So this should get all keychains of this store.				
				XPathNodeIterator iterSecret = iter.Current.SelectDescendants( XPathNodeType.Element,false );
				
				while( iterSecret.MoveNext() )
				{//Enumerate this Keychain\Wallet\Profile\Keyring
					
					if( true == iterSecret.Current.HasAttributes )
					{//Elements With attributes, get the attributes first before going to next sub element						
						
						if( iterSecret.Current.Name.Equals(storeChainKey) )
						{//miCASA-KeyChain //GK-Keyring //KWallet-Wallet
							
							iterSecret.Current.MoveToFirstAttribute();
							do
							{
								//Keychain\Wallet\Profile\Keyring ID
								if( iterSecret.Current.LocalName.Equals(CCFXML_ATTRIBUTE_ID) )
								{
									storeID = iterSecret.Current.Value;
								}
								
							}while( iterSecret.Current.MoveToNextAttribute() );
							
							iterSecret.Current.MoveToParent();
						}							
						else if( iterSecret.Current.Name.Equals(CCFXML_ELEMENT_SECRET) )
						{//miCASA-KeyChain-Secret:secretID
						
							noOfSecretsFound++;							
							iterSecret.Current.MoveToFirstAttribute();
							do 
							{
								if( iterSecret.Current.LocalName.Equals(CCFXML_ATTRIBUTE_ID) )
								{
									secretID = iterSecret.Current.Value;									
								}
								else if( iterSecret.Current.LocalName.Equals(CCFXML_ATTRIBUTE_MICASA_SYNCH) )
								{
									synch = iterSecret.Current.Value;
								}
								else if( iterSecret.Current.LocalName.Equals(CCFXML_ATTRIBUTE_GKEYRING_TYPE) )
								{
									//synchType = iterSecret.Current.Value;
									typeID = iterSecret.Current.Value;
								}
								
							}while( iterSecret.Current.MoveToNextAttribute() );
							
							iterSecret.Current.MoveToParent();

							//Now get more details about the secret
							//End of secret is after read of all keys of the secret
							{
								XPathNodeIterator secIter;
								ccfExtPath = "Key";
								secIter = iterSecret.Current.Select(ccfExtPath);
								noOfKeys = secIter.Count;
								
								//Reinit arrays to the no of keys for this secret
								strKeyArray	  = new string[noOfKeys];
								strValueArray = new string[noOfKeys];

								//Get Last Modified Time for the secret
								ccfExtPath = CCFXML_ELEMENT_TIME + "/" + CCFXML_ELEMENT_TIME_MODIFIED;
								secIter = iterSecret.Current.Select(ccfExtPath);
								
								if( 0 != secIter.Count )
								{
									while( secIter.MoveNext() )
									{//Enumerate the Time Nodes of this secret
										if( secIter.Current.Name.Equals(CCFXML_ELEMENT_TIME_MODIFIED) )
										{//miCASA-KeyChain-Secret-Key-Value-Time-modified
										     
											modifiedTime = secIter.Current.Value;
											
										}
									}
								}
							}


						}							
						else if( iterSecret.Current.Name.Equals(CCFXML_ELEMENT_KEY) )
						{//miCASA-KeyChain-Secret-Key:ID
							iterSecret.Current.MoveToFirstAttribute();
							do
							{
								if( (iterSecret.Current.LocalName.Equals(CCFXML_ATTRIBUTE_ID)) && (noOfKeysFound<=noOfKeys) )
								{
									bKey = true;
									strKeyArray[noOfKeysFound] = iterSecret.Current.Value; //KeyName									
								}
							}while( iterSecret.Current.MoveToNextAttribute() );
							iterSecret.Current.MoveToParent();

						}
						else if( iterSecret.Current.Name.Equals(CCFXML_ELEMENT_FOLDER) )
						{//Folder:
							iterSecret.Current.MoveToFirstAttribute();
							do
							{
								if( iterSecret.Current.LocalName.Equals(CCFXML_ATTRIBUTE_FOLDERNAME) )
								{//Folder:Name
									folderName = iterSecret.Current.Value;
								}
							}while( iterSecret.Current.MoveToNextAttribute() );
							iterSecret.Current.MoveToParent();

						}
						else if( iterSecret.Current.Name.Equals(CCFXML_ELEMENT_TYPE) )
						{//Type:
							iterSecret.Current.MoveToFirstAttribute();
							do
							{
								if( iterSecret.Current.LocalName.Equals(CCFXML_ATTRIBUTE_ID) )
								{//Type:ID
									typeID = iterSecret.Current.Value;
								}
							}while( iterSecret.Current.MoveToNextAttribute() );
							iterSecret.Current.MoveToParent();

						}
					}//Elements Without attributes,Get element values and then go to next subelement
					else if( iterSecret.Current.Name.Equals(CCFXML_ELEMENT_VALUE) )
					{//miCASA-KeyChain-Secret-Key-Value:<Value>
						if( true == bKey )
						{
							//Update Corresponding KeyValue
							strValueArray[noOfKeysFound++] = iterSecret.Current.Value; //KeyValue							
							bKey = false;

							//Are alll keys read? If so its the end of the secret
							if( noOfKeysFound == noOfKeys )
								bEndOfSecret = true;
						}
					}

					//Update this Secret to the GUI Store
					if( true == bEndOfSecret )
					{
						//Updating TreeStore Native Array structure
						strNativeValueArray = new string[Common.MAX_NATIVE_ELEMENTS];
						
						strNativeValueArray[Common.INDEX_NATIVEINFO_FOLDERNAME]   = folderName;
						strNativeValueArray[Common.INDEX_NATIVEINFO_TYPEID]		  = typeID;
						strNativeValueArray[Common.INDEX_NATIVEINFO_SYNC]		  = synch;
						strNativeValueArray[Common.INDEX_NATIVEINFO_SYNCTYPE]	  = synchType;
						strNativeValueArray[Common.INDEX_NATIVEINFO_MODIFIEDTIME] = modifiedTime;
						//Console.WriteLine("folderName="+folderName+"\n"+"typeID="+typeID+"\n"+"synch="+synch+"\n"+"synchType="+synchType+"\n"+"modifiedTime="+modifiedTime);
						
						ls.AppendValues(secretID,strKeyArray,strValueArray,storeID,strNativeKeyArray,strNativeValueArray);
					
						//Re-Initialize for next iteration
						secretID = "";
						noOfKeysFound = 0;
						noOfKeys = 0;
						bKey = false;
						//bTime=false;- For Use Later
						bEndOfSecret = false;
					}
				}
			}
			
			}
			catch(Exception exp)
 			{ 				
 				Logger.DbgLog("GUI:StoreDataInterface.ReadStore() - EXCEPTION" + exp.ToString());
 				return( Common.STATUS_STORE_READFAILED );	
			}
			//ShowDocOnConsole("READ STORE:");
			return( Common.STATUS_SUCCESS );
		}



		///#######################################################################
		/// UPDATE STORE: ADD NEW secret/keyvalue, MODIFY keyvalue, DELETE secret		
		
		/// <summary>
		/// Supported Update Functionalities - on miCASA Store only
		/// </summary>
		public static int UpdateStore(int storeIDentifier,int operation,string keyID,string valueToBeModfied,ref TreeModel model,ref TreeIter iter)
		{
			Logger.DbgLog("GUI:StoreDataInterface.UpdateStore()");
			
			//TreeStore row  elements
			string 	 storeChainKey 		 = null;
			string 	 SecretID 			  = null;
			string 	 keyChainID			  = null;
			string[] strKeyArray		  = new string[Common.MAX_ARRAY_ELEMENTS];
			string[] strValueArray		  = new string[Common.MAX_ARRAY_ELEMENTS];
			string[] strNativeValueArray  = new string[Common.MAX_NATIVE_ELEMENTS];
			
			//XPATH query strings
			string		ccfRootStorePath	= null;
			string 		ccfKeyChainPath		= null;
			string 		ccfSecretPath  		= null;
			
			//Intialization of New Secret\Key elements
			XmlElement newKeychainElement = ccfDoc.CreateElement(CCFXML_ELEMENT_MICASA_KEYCHAIN);
			XmlElement newSecretElement	  = ccfDoc.CreateElement(CCFXML_ELEMENT_SECRET);
			XmlElement newKeyElement	  = ccfDoc.CreateElement(CCFXML_ELEMENT_KEY);
			

			//Reading and Initialzing from the passed iter object			
			SecretID	  = (string)   model.GetValue (iter, 0);
			strKeyArray   = (string[]) model.GetValue (iter, 1);
			strValueArray = (string[]) model.GetValue (iter, 2);
			keyChainID	  = (string)   model.GetValue (iter, 3);
			strNativeValueArray	  = (string[])   model.GetValue (iter, 5);


			try
			{
			
			//Form the query to reach to an element for modify\delete\add
			if( Common.STORE_MICASA == storeIDentifier )
			{
				storeChainKey 		 = CCFXML_ELEMENT_MICASA_KEYCHAIN;
				ccfRootStorePath = "//CCF/miCASA";
				if( Common.OPERATION_MODIFY_KEY == operation || Common.OPERATION_DELETE_KEY == operation )
				{
					ccfSecretPath = "//CCF/miCASA/Keychain[@ID='" + keyChainID + "']/Secret[@ID='" + SecretID + "']/Key[@ID='" + keyID + "']";
				}
				else if( Common.OPERATION_DELETE_SECRET == operation )
				{
					ccfKeyChainPath = "//CCF/miCASA/Keychain[@ID='" + keyChainID + "']";
					ccfSecretPath = "Secret[@ID='" + SecretID + "']";
				}
				else if( Common.OPERATION_ADD_SECRET == operation )
				{
					ccfKeyChainPath = "//CCF/miCASA/Keychain[@ID='" + keyChainID + "']";
					ccfSecretPath = "//CCF/miCASA/Keychain[@ID='" + keyChainID + "']/Secret[@ID='" + SecretID + "']";
					
					//Create the Secret element
					newSecretElement = ccfDoc.CreateElement(CCFXML_ELEMENT_SECRET);
					newSecretElement.SetAttribute(CCFXML_ATTRIBUTE_ID,SecretID);
					newSecretElement.SetAttribute(CCFXML_ATTRIBUTE_MICASA_SYNCH,"NSL");

					//Add all keys from strKeyArray to the new secret
					for( int i=0; i< strKeyArray.Length; i++)
					{
						XmlElement newKey = ccfDoc.CreateElement(CCFXML_ELEMENT_KEY);
						newKey.SetAttribute(CCFXML_ATTRIBUTE_ID,strKeyArray[i]);
						XmlElement newValue = ccfDoc.CreateElement(CCFXML_ELEMENT_VALUE);
						newValue.InnerText = strValueArray[i];
						newKey.AppendChild(newValue);
						newSecretElement.AppendChild(newKey);
					}

					//Time
					XmlElement newTime = ccfDoc.CreateElement(CCFXML_ELEMENT_TIME);
					XmlElement newZone = ccfDoc.CreateElement(CCFXML_ELEMENT_TIME_ZONE);
					newZone.InnerText = "IST";
					newTime.AppendChild(newZone);
					XmlElement newCreateTime = ccfDoc.CreateElement(CCFXML_ELEMENT_TIME_CREATION);
					newCreateTime.InnerText = "1234";
					newTime.AppendChild(newCreateTime);
					XmlElement newModifiedTime = ccfDoc.CreateElement(CCFXML_ELEMENT_TIME_MODIFIED);
					newModifiedTime.InnerText = "5678";
					newTime.AppendChild(newModifiedTime);
					XmlElement newAccessedTime = ccfDoc.CreateElement(CCFXML_ELEMENT_TIME_ACCESSED);
					newAccessedTime.InnerText = "9012";
					newTime.AppendChild(newAccessedTime);					
					newSecretElement.AppendChild(newTime);
					//Create the keychain element
					newKeychainElement = ccfDoc.CreateElement(storeChainKey);
					newKeychainElement.SetAttribute(CCFXML_ATTRIBUTE_ID,keyChainID);
					newKeychainElement.AppendChild(newSecretElement);
				}
				else if( Common.OPERATION_ADD_KEY == operation )
				{
					ccfKeyChainPath = "//CCF/miCASA/Keychain[@ID='" + keyChainID + "']/Secret[@ID='" + SecretID + "']";
					ccfSecretPath = "";
										
					//Create the Key element
					newKeyElement = ccfDoc.CreateElement(CCFXML_ELEMENT_KEY);
					newKeyElement.SetAttribute(CCFXML_ATTRIBUTE_ID,keyID);
					XmlElement newValue = ccfDoc.CreateElement(CCFXML_ELEMENT_VALUE);
					newValue.InnerText = valueToBeModfied;
					newKeyElement.AppendChild(newValue);
				}
			}
			else if( Common.STORE_GNOMEKEYRING == storeIDentifier )
			{
				storeChainKey = CCFXML_ELEMENT_GKEYRING_KEYRING;
				ccfRootStorePath = "//CCF/GK";
				if( Common.OPERATION_MODIFY_KEY == operation || Common.OPERATION_DELETE_KEY == operation )
					{
						ccfSecretPath = "//CCF/GK/Keyring[@ID='" + keyChainID + "']/Secret[@ID='" + SecretID + "']/Key[@ID='" + keyID + "']";
						//Console.WriteLine("OPERATION_MODIFY_KEY-OR-OPERATION_DELETE_KEY:ccfSecretPath:"+ccfSecretPath);//FIXME:Remove this line
					}
					else if( Common.OPERATION_DELETE_SECRET == operation )
					{
						ccfKeyChainPath = "//CCF/GK/Keyring[@ID='" + keyChainID + "']";
						ccfSecretPath = "Secret[@ID='" + SecretID + "']";
						//Console.WriteLine("OPERATION_DELETE_SECRET:ccfKeyChainPath:"+ccfKeyChainPath);//FIXME:Remove this line
						//Console.WriteLine("OPERATION_DELETE_SECRET:ccfSecretPath:"+ccfSecretPath);//FIXME:Remove this line
					}
					else if( Common.OPERATION_ADD_SECRET == operation )
					{
						string 	 typeID = strNativeValueArray[Common.INDEX_NATIVEINFO_TYPEID];
						string 	 walletLastAccessedTime = strNativeValueArray[Common.INDEX_NATIVEINFO_WALLETLASTACCESSEDTIME];
						ccfKeyChainPath = "//CCF/GK/Keyring[@ID='" + keyChainID + "']";//Default keyChainID:CASAKeyring
						ccfSecretPath = "//CCF/GK/Keyring[@ID='" + keyChainID + "']/Secret[@ID='" + SecretID + "']";
						//Console.WriteLine("OPERATION_ADD_SECRET:ccfKeyChainPath:"+ccfKeyChainPath);//FIXME:Remove this line
						//Console.WriteLine("OPERATION_ADD_SECRET:ccfSecretPath:"+ccfSecretPath);//FIXME:Remove this line
					
						//Create the Secret element
						newSecretElement = ccfDoc.CreateElement(CCFXML_ELEMENT_SECRET);
						newSecretElement.SetAttribute(CCFXML_ATTRIBUTE_ID,SecretID);
						newSecretElement.SetAttribute(CCFXML_ATTRIBUTE_GKEYRING_TYPE,typeID); //Default typeID:Password

						//Add all keys from strKeyArray to the new secret
						for( int i=0; i< strKeyArray.Length; i++)
						{
							XmlElement newKey = ccfDoc.CreateElement(CCFXML_ELEMENT_KEY);
							newKey.SetAttribute(CCFXML_ATTRIBUTE_ID,strKeyArray[i]);
							XmlElement newValue = ccfDoc.CreateElement(CCFXML_ELEMENT_VALUE);
							newValue.InnerText = strValueArray[i];
							newKey.AppendChild(newValue);
							newSecretElement.AppendChild(newKey);
						}

						//Create the keychain element
						newKeychainElement = ccfDoc.CreateElement(storeChainKey);
						newKeychainElement.SetAttribute(CCFXML_ATTRIBUTE_ID,keyChainID);
						//newKeychainElement.SetAttribute(CCFXML_ATTRIBUTE_WALLETLASTACCESSEDTIME,walletLastAccessedTime);
						newKeychainElement.AppendChild(newSecretElement);
					}
					else if( Common.OPERATION_ADD_KEY == operation )
					{
						ccfKeyChainPath = "//CCF/GK/Keyring[@ID='" + keyChainID + "']/Secret[@ID='" + SecretID + "']";
						ccfSecretPath = "";
										
						//Create the Key element
						newKeyElement = ccfDoc.CreateElement(CCFXML_ELEMENT_KEY);
						newKeyElement.SetAttribute(CCFXML_ATTRIBUTE_ID,keyID);
						XmlElement newValue = ccfDoc.CreateElement(CCFXML_ELEMENT_VALUE);
						newValue.InnerText = valueToBeModfied;
						newKeyElement.AppendChild(newValue);
					}
				}
			else if( Common.STORE_KDEWALLET == storeIDentifier )
			{
				string 	 folderName 		 = strNativeValueArray[Common.INDEX_NATIVEINFO_FOLDERNAME];
				string 	 typeID 			 = strNativeValueArray[Common.INDEX_NATIVEINFO_TYPEID];
				storeChainKey = CCFXML_ELEMENT_KWALLET_WALLET;
				ccfRootStorePath = "//CCF/KWallet";

				if( Common.OPERATION_MODIFY_KEY == operation || Common.OPERATION_DELETE_KEY == operation )
				{
					ccfSecretPath = "//CCF/KWallet/Wallet[@ID='" + keyChainID + "']/Folder[@Name='" + folderName + "']/Type[@ID='" + typeID + "']/Secret[@ID='" + SecretID + "']/Key[@ID='" + keyID + "']";
					//Console.WriteLine("OPERATION_MODIFY_KEY-OR-OPERATION_DELETE_KEY:ccfSecretPath:"+ccfSecretPath);//FIXME:Remove this line
				}
				else if( Common.OPERATION_DELETE_SECRET == operation )
				{
					ccfKeyChainPath = "//CCF/KWallet/Wallet[@ID='" + keyChainID + "']/Folder[@Name='" + folderName + "']/Type[@ID='" + typeID + "']";
					ccfSecretPath = "Secret[@ID='" + SecretID + "']";
					//Console.WriteLine("OPERATION_DELETE_SECRET:ccfKeyChainPath:"+ccfKeyChainPath);//FIXME:Remove this line
					//Console.WriteLine("OPERATION_DELETE_SECRET:ccfSecretPath:"+ccfSecretPath);//FIXME:Remove this line
				}
				else if( Common.OPERATION_ADD_SECRET == operation )
				{
						ccfKeyChainPath = "//CCF/KWallet/Wallet[@ID='" + keyChainID + "']/Folder[@Name='" + folderName + "']/Type[@ID='" + typeID + "']";
						ccfSecretPath = "//CCF/KWallet/Wallet[@ID='" + keyChainID + "']/Folder[@Name='" + folderName + "']/Type[@ID='" + typeID + "']/Secret[@ID='" + SecretID + "']";
						//Console.WriteLine("OPERATION_ADD_SECRET:ccfKeyChainPath:"+ccfKeyChainPath);//FIXME:Remove this line
						//Console.WriteLine("OPERATION_ADD_SECRET:ccfSecretPath:"+ccfSecretPath);//FIXME:Remove this line

						//Create the Secret element
						newSecretElement = ccfDoc.CreateElement(CCFXML_ELEMENT_SECRET);
						newSecretElement.SetAttribute(CCFXML_ATTRIBUTE_ID,SecretID);

						//Add all keys from strKeyArray to the new secret
						for( int i=0; i< strKeyArray.Length; i++)
						{
							XmlElement newKey = ccfDoc.CreateElement(CCFXML_ELEMENT_KEY);
							newKey.SetAttribute(CCFXML_ATTRIBUTE_ID,strKeyArray[i]);
							XmlElement newValue = ccfDoc.CreateElement(CCFXML_ELEMENT_VALUE);
							newValue.InnerText = strValueArray[i];
							newKey.AppendChild(newValue);
							newSecretElement.AppendChild(newKey);
						}

				}
				else if( Common.OPERATION_ADD_KEY == operation )
				{
						ccfKeyChainPath = "//CCF/KWallet/Wallet[@ID='" + keyChainID + "']/Folder[@Name='" + folderName + "']/Type[@ID='" + typeID + "']/Secret[@ID='" + SecretID + "']";
						ccfSecretPath = "";
										
						//Create the Key element
						newKeyElement = ccfDoc.CreateElement(CCFXML_ELEMENT_KEY);
						newKeyElement.SetAttribute(CCFXML_ATTRIBUTE_ID,keyID);
						XmlElement newValue = ccfDoc.CreateElement(CCFXML_ELEMENT_VALUE);
						newValue.InnerText = valueToBeModfied;
						newKeyElement.AppendChild(newValue);
				}
			}
			else if( Common.STORE_FIREFOX == storeIDentifier )
			{
				storeChainKey = CCFXML_ELEMENT_FIREFOX_PROFILE;
				ccfRootStorePath = "//CCF/FireFox";
				if( Common.OPERATION_MODIFY_KEY == operation || Common.OPERATION_DELETE_KEY == operation )		
				{
					ccfSecretPath = "//CCF/FireFox/Profile[@ID='" + keyChainID + "']/Secret[@ID='" + SecretID + "']/Key[@ID='" + keyID + "']";
					//Console.WriteLine("OPERATION_MODIFY_KEY-OR-OPERATION_DELETE_KEY:ccfSecretPath:"+ccfSecretPath);//FIXME:Remove this line
				}
				else if( Common.OPERATION_DELETE_SECRET == operation )
				{
					ccfKeyChainPath = "//CCF/FireFox/Profile[@ID='" + keyChainID + "']";
					ccfSecretPath = "Secret[@ID='" + SecretID + "']";
					//Console.WriteLine("OPERATION_DELETE_SECRET:ccfKeyChainPath:"+ccfKeyChainPath);//FIXME:Remove this line
					//Console.WriteLine("OPERATION_DELETE_SECRET:ccfSecretPath:"+ccfSecretPath);//FIXME:Remove this line
				}
			}
			else
				return( Common.STATUS_STORE_UNSUPPORTEDOPERATION );



			//Execution of the query's
			if( Common.OPERATION_MODIFY_KEY == operation )
			{			 
			 	//For Modify operation get to the Node in the tree which needs to be modified
				XmlNode root = ccfDoc.DocumentElement;
				XmlNodeList keylist = root.SelectNodes(ccfSecretPath);								
				foreach ( XmlNode key in keylist )
				{					
					key.ChildNodes[0].InnerText=valueToBeModfied ;					
					//Console.WriteLine("EXECUTING OPERATION_MODIFY_KEY:Modifying"+ccfSecretPath);//FIXME:Remove this line
					ad.SetSecret(key.ParentNode,operation,storeIDentifier);
				}			
			}
			else if( Common.OPERATION_DELETE_SECRET == operation )
			{
				//Delete the specific secret from the keychain
				XmlNode root = ccfDoc.DocumentElement;
				XmlNodeList keychainNodeList = root.SelectNodes(ccfKeyChainPath);
				
				foreach( XmlNode keychain in keychainNodeList )
				{					
					XmlNodeList secretNodelist = keychain.SelectNodes(ccfSecretPath);					
					foreach ( XmlNode secret in secretNodelist )
					{
						//Console.WriteLine("EXECUTING OPERATION_DELETE_SECRET:Deleting"+ccfSecretPath);//FIXME:Remove this line
						ad.Remove(secret,storeIDentifier);						
					}
				}
			}
			else if( Common.OPERATION_DELETE_KEY == operation )
			{			 
			 	//For Modify operation get to the Node in the tree which needs to be modified
				XmlNode root = ccfDoc.DocumentElement;
				XmlNodeList keylist = root.SelectNodes(ccfSecretPath);								
				
				foreach ( XmlNode key in keylist )
				{					
					XmlNode keyParentNode = key.ParentNode;
					key.ParentNode.RemoveChild(key);
					//Console.WriteLine("EXECUTING OPERATION_DELETE_KEY:Deleting"+ccfSecretPath);//FIXME:Remove this line
					//ad.SetSecret(keyParentNode,storeIDentifier);
					ad.SetSecret(keyParentNode,Common.OPERATION_MODIFY_KEY,storeIDentifier);
				}			
			}
			else if( Common.OPERATION_ADD_SECRET == operation )
			{				
				//ShowDocOnConsole("BEFORE CALL TO SETSECRET");//FIXME:Remove this	

				if(( Common.STORE_MICASA == storeIDentifier )||( Common.STORE_GNOMEKEYRING == storeIDentifier ))
				{
					//Add a new secret to the keychain
					XmlNode root = ccfDoc.DocumentElement;				
					XmlNodeList keychainNodeList = root.SelectNodes(ccfKeyChainPath);
					//Console.WriteLine("ADD_SECRET:ccfKeyChainPath="+ccfKeyChainPath);//FIXME:Remove this line
												
					if( (null == keychainNodeList) || (0 == keychainNodeList.Count) )
					{//No root keychain path for this wallet. Hence New Keychain to be created
					//Expected path to be existing in CCF is eg://CCF/miCASA
						keychainNodeList = root.SelectNodes(ccfRootStorePath);					
						XmlNode miCASANode = keychainNodeList.Item(0);
					
						if( null != miCASANode )
						{
							//Console.WriteLine("ADD_SECRET:Appending to ccfRootStorePath="+ccfRootStorePath);//FIXME:Remove this line
							miCASANode.AppendChild(newKeychainElement);
							//ShowDocOnConsole("AFTER APENDING TO miCASANode");//FIXME:Remove this	
							//Console.WriteLine("ADD_SECRET:ccfSecretPath="+ccfSecretPath);//FIXME:Remove this line
							keychainNodeList = root.SelectNodes(ccfSecretPath);						
							XmlNode SecretNode = keychainNodeList.Item(0);												
							//Console.WriteLine("EXECUTING OPERATION_ADD_SECRET:Adding"+ccfSecretPath);//FIXME:Remove this line
							ad.SetSecret(SecretNode,operation,storeIDentifier);						
						}
					}
					else
					{//Root keychain path exists for this wallet
						//Console.WriteLine("ADD_SECRET:Appending to ccfKeyChainPath="+ccfKeyChainPath);//FIXME:Remove this line
						XmlNode keychain = keychainNodeList.Item(0);
						keychain.AppendChild(newSecretElement);
						XmlNode lastChild = keychain.LastChild;
						//ShowDocOnConsole("BEFORE CALL TO SETSECRET");//FIXME:Remove this	
						//Console.WriteLine("EXECUTING OPERATION_ADD_SECRET:Adding Secret to existing keychain");//FIXME:Remove this line
						int errCode=ad.SetSecret(lastChild,operation,storeIDentifier);
						//Console.WriteLine("OPERATION_ADD_SECRET Returned:errCode"+errCode);//FIXME:Remove this line
					}
				}//Common.STORE_MICASA \ STORE_GNOMEKEYRING
				else
				if( Common.STORE_KDEWALLET == storeIDentifier )
				{
					string 	 folderName 		 = strNativeValueArray[Common.INDEX_NATIVEINFO_FOLDERNAME];
					string 	 typeID 			 = strNativeValueArray[Common.INDEX_NATIVEINFO_TYPEID];
					XmlNode root = ccfDoc.DocumentElement;				
					ccfKeyChainPath = "//CCF/KWallet/Wallet[@ID='" + keyChainID + "']"; //CASAwallet
					XmlNodeList keychainNodeList = root.SelectNodes(ccfKeyChainPath);
					if( (null == keychainNodeList) || (0 == keychainNodeList.Count) )
					{//Wallet:CASAwallet does not exist. Hence create all
						XmlElement folder;
						XmlElement type;
						newKeychainElement = ccfDoc.CreateElement(storeChainKey);//Wallet
						newKeychainElement.SetAttribute(CCFXML_ATTRIBUTE_ID,keyChainID);
						folder = ccfDoc.CreateElement(CCFXML_ELEMENT_FOLDER);
						folder.SetAttribute(CCFXML_ATTRIBUTE_FOLDERNAME,folderName);
						type = ccfDoc.CreateElement(CCFXML_ELEMENT_TYPE);
						type.SetAttribute(CCFXML_ATTRIBUTE_ID,typeID);
						
						//Join all of them
						type.AppendChild(newSecretElement);
						folder.AppendChild(type);
						newKeychainElement.AppendChild(folder);
						//Append the keychain to the root
						keychainNodeList = root.SelectNodes(ccfRootStorePath);					
						XmlNode rootNode = keychainNodeList.Item(0);					
						if( null != rootNode )
							rootNode.AppendChild(newKeychainElement);

					}
					else
					{//Wallet:CASAwallet exists. Hence check for folder
						ccfKeyChainPath = "//CCF/KWallet/Wallet[@ID='" + keyChainID + "']/Folder[@Name='" + folderName + "']"; //Passwords
						XmlNodeList keychainFolderNodeList = root.SelectNodes(ccfKeyChainPath);
						if( (null == keychainFolderNodeList) || (0 == keychainFolderNodeList.Count) )
						{//folderName:Password does not exist. Hence create folder & type
							XmlElement folder;
							XmlElement type;
							folder = ccfDoc.CreateElement(CCFXML_ELEMENT_FOLDER);
							folder.SetAttribute(CCFXML_ATTRIBUTE_FOLDERNAME,folderName);
							type = ccfDoc.CreateElement(CCFXML_ELEMENT_TYPE);
							type.SetAttribute(CCFXML_ATTRIBUTE_ID,typeID);
						
							//Append secret to type
							type.AppendChild(newSecretElement);
							//Append type to folder
							folder.AppendChild(type);
							//Append folder to the existing keychainNodeList
							XmlNode keychainNode = keychainNodeList.Item(0);					
							if( null != keychainNode )
								keychainNode.AppendChild(folder);
						}
						else
						{//Wallet:CASAwallet & folder exists. Hence check for type
							ccfKeyChainPath = "//CCF/KWallet/Wallet[@ID='" + keyChainID + "']/Folder[@Name='" + folderName + "']/Type[@ID='" + typeID + "']"; //Maps
							XmlNodeList keychainTypeNodeList = root.SelectNodes(ccfKeyChainPath);
							if( (null == keychainTypeNodeList) || (0 == keychainTypeNodeList.Count) )
							{//type:Maps does not exist. Hence create folder & type
								XmlElement type;
								type = ccfDoc.CreateElement(CCFXML_ELEMENT_TYPE);
								type.SetAttribute(CCFXML_ATTRIBUTE_ID,typeID);
								//Append Secret to type
								type.AppendChild(newSecretElement);
								//Append type to the existing keychainFolderNodeList
								XmlNode keychainFolderNode = keychainFolderNodeList.Item(0);					
								if( null != keychainFolderNode )
									keychainFolderNode.AppendChild(type);
							}
						}

					}

					//Invoke setsecret 
					//ShowDocOnConsole("AFTER ADD to CCF");//FIXME:Remove this	
					ccfKeyChainPath = "//CCF/KWallet/Wallet[@ID='" + keyChainID + "']/Folder[@Name='" + folderName + "']/Type[@ID='" + typeID + "']";
					root = ccfDoc.DocumentElement;				
					//Console.WriteLine("ADD_SECRET:ccfSecretPath="+ccfSecretPath);//FIXME:Remove this line
					//Console.WriteLine("ADD_SECRET:ccfKeyChainPath="+ccfKeyChainPath);//FIXME:Remove this line
					XmlNodeList secretNodeList = root.SelectNodes(ccfKeyChainPath);						
					XmlNode SecretNode = secretNodeList.Item(0);
					SecretNode.AppendChild(newSecretElement); //Add the new Secret
					XmlNode lastChild = SecretNode.LastChild; //Get The newly added secret
					if(lastChild!=null)
					{												
						//Console.WriteLine("EXECUTING OPERATION_ADD_SECRET:Adding"+ccfSecretPath);//FIXME:Remove this line
						ad.SetSecret(lastChild,operation,storeIDentifier);	//and set it					
					}
				}//STORE_KDEWALLET

			
			}
			else if( Common.OPERATION_ADD_KEY == operation )
			{
				//Add a new KN\KV to the keychain-Secret
				//Console.WriteLine("EXECUTING OPERATION_ADD_KEY:Adding"+ccfKeyChainPath);//FIXME:Remove this line
				XmlNode root = ccfDoc.DocumentElement;
				XmlNodeList keyNodeList = root.SelectNodes(ccfKeyChainPath);
				XmlNode keyNode=keyNodeList.Item(0);
				XmlNode lastChild = keyNode.LastChild;
				keyNode.InsertBefore(newKeyElement,lastChild);
				//ShowDocOnConsole("JUST BEFORE CALL TO SETSECRET-ADDKEY");//FIXME:Remove this	
				//int errcode=ad.SetSecret(keyNode,Common.OPERATION_ADD_SECRET,storeIDentifier);
				int errcode=ad.SetSecret(keyNode,Common.OPERATION_MODIFY_KEY,storeIDentifier);
				//ShowDocOnConsole("SetSecret returned errcode="+errcode);//FIXME:Remove this	
			}			
			
			}
			catch(Exception exp)
			{
				//Console.WriteLine("Exception"+exp.ToString());//FIXME:Remove this line
				Logger.DbgLog("GUI:StoreDataInterface.UpdateStore() - EXCEPTION" + exp.ToString());
				return( Common.STATUS_STORE_UPDATEFAILED );
			}
			
			return( Common.STATUS_SUCCESS );
		}


		///#######################################################################
		/// DUMP THE XML CCF ON CONSOLE
		
		/// <summary>
		/// Print Doc to the console for verification
		/// </summary>
		public static void ShowDocOnConsole(string str)
		{
#if DEBUG
			Console.WriteLine("\n#######################################################");
			Console.WriteLine("   "+str);
			Console.WriteLine("\n#######################################################");
			ccfDoc.Save(Console.Out);
			Console.WriteLine("\n#######################################################");
#endif
		}

	}
}
///###########################################################################
///								END OF FILE
///###########################################################################