/***********************************************************************
 * 
 *  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.
 * 
 ***********************************************************************/

#include<stdio.h>
#include <kapp.h>
#include <kcmdlineargs.h>
#include<kwallet.h>
#include <dcopclient.h>
#include<iostream.h>

#define MAX_LENGTH 256

using namespace KWallet;
using namespace std;

#include "casakwallet.h"
#include "casakwallet.moc"
//#include "mytest.h"


//	char *applName="dcopifacedemo";
	char *applName="casaconsole";
	QStringList walletList;

	DCOPCASAConnector *win = new DCOPCASAConnector();

	DCOPCASAConnector::DCOPCASAConnector()
	{

                    int ret = 0;
		    kapp->dcopClient()->isRegistered() ;
                    if (!ret)
                    {
                       if(kapp->dcopClient()->registerAs( "casaconsole" ).isEmpty())
                       {
                                kapp->startKdeinit();
                                kapp->dcopClient()->isRegistered() ;
                                if (!ret)
                                {
                                        if (kapp->dcopClient()->registerAs( "casaconsole" ).isEmpty())
                                        {
                                                printf("Cannot setup DCOP communication. Start kdeinit manually\n");
                                                return;
                                        }
                               }
                        }
                    }

/*		    if ( !kapp->dcopClient()->isRegistered() ) {
		        kapp->dcopClient()->registerAs( "casaconsole" );
		    }
*/
	}

	DCOPCASAConnector::~DCOPCASAConnector()
	{

		for ( QStringList::Iterator walletIter = walletList.begin(); walletIter != walletList.end(); ++walletIter ) 
	        {
        		QString walletName = (*walletIter);
		        Wallet::disconnectApplication(walletName,applName);

	    	}
	}






       int DCOPCASAConnector::ReadKey(Wallet *wallet,QString key, QByteArray *secretVal)
	{

		// Read the secret from the entry
	         QByteArray value;
                 //printf("kwallet: Read Key entered\n");

 		if (wallet->readEntry(key, value)==0)
 		{

 		       if (value)
			{

		        	*secretVal = value;
            			QDataStream convert(*secretVal, IO_ReadOnly);


		               if (wallet->entryType(key) == 1 ) 
				{

                                     //Commented by Austin
 		               	    /*	// Convert the ByteArray to QString
			                QString passwd;
                                	printf("In read Entry Convert Final before success\n");
			                convert >> passwd;
                                	printf("In read Entry Convert Final success\n");
                                    */

			        } else if (wallet->entryType(key) == 3) 
				{

			               // If the entry is of type "map"
			                // Convert the ByteArray to QMap
			                QMap<QString,QString> mapSecret;
			                convert >> mapSecret;

			                // Iterate through each map entry.
        			        QMap<QString,QString>::Iterator mapIter;
			                QString tempSecret = QString::fromLatin1("");

			                for ( mapIter = mapSecret.begin(); mapIter != mapSecret.end(); ++mapIter ) 
					{
			                    // This logic has to be improved
			                    tempSecret.append(mapIter.key().latin1());
			                    tempSecret.append(":");
			                    tempSecret.append(mapIter.data().latin1());

			                    if ((++mapIter) != mapSecret.end())
			                       tempSecret.append(";");

			                    --mapIter;
			                }

               				 // Convert the QString to QByteArray
			                QDataStream stream(*secretVal, IO_WriteOnly);
			                stream << tempSecret ;

			         }

        	      } else
            	      {
		                //printf("Could not read the entry..inner IF\n");
		                return -1;
		      }

    	} else
    	{
       		//printf("Could not read the entry Inside wallet->readkey\n");
	        return -1;
	}

    return 0;

}


                  





















extern "C" 
{
        static struct EnumSecretList *tempEnumSecrets = NULL;

	//void MyTest(struct EnumSecretList *enumWalletSecrets)
	void Aggregate(struct EnumSecretList *enumWalletSecrets)
	{

    //printf("inside natiove agg");
         int retVal = 0;
         tempEnumSecrets = NULL;
         retVal = win->ReadAllWalletSecrets(&tempEnumSecrets);

         struct EnumSecretList *iter = tempEnumSecrets;
         //struct EnumSecretList *head = tempEnumSecrets;
/*
        if (iter == NULL)
        {

            printf("Native has given NULLLL\n");   
            enumWalletSecrets = NULL;
            return;
        }
*/
         while (iter != NULL)
         {

                 /*
         	 printf("\n\n**Wallet Name : %s\n",iter->walletName);
	         printf("\t**Folder Name : %s\n",iter->folderName);
	         printf("\t\t**Secret Type : %d\n",iter->entryType);
	         printf("\t\t\t**Secret Value : %s\n",iter->secretVal);
                 */ 

		enumWalletSecrets->walletName = iter->walletName;
	        enumWalletSecrets->folderName = iter->folderName;
	        enumWalletSecrets->secretVal = iter->secretVal;
	        enumWalletSecrets->entryType =  iter->entryType;
	        enumWalletSecrets->next = iter->next;
  
 	        iter = iter->next;
        	if (iter != NULL)
        	{
           		enumWalletSecrets =  enumWalletSecrets->next ;
	        }
	        else
	        {
	          enumWalletSecrets = NULL;
	        }

         }
/*
          // Free the list
          struct EnumSecretList *temp;
          while (head != NULL)
          {
		free(head->walletName);
		free(head->folderName);
		free(head->secretVal);
		//free(head->entryType);
		temp = head->next;
                free(head);
                head = temp;  
          }  
          
           
  */         

	}
	
	char * GetDefaultWallet()
	{
		char *homedir = NULL;
		char *defaultwallet = NULL; 
		char *str1 = "Default Wallet=";
		char  str[MAX_LENGTH];
		FILE *fs = NULL;
		int i,j,k;	

		defaultwallet = (char *)malloc(MAX_LENGTH);
		homedir = (char *)malloc(MAX_LENGTH);	

		strcpy(homedir, getenv("HOME"));		
		strcat(homedir, "/.kde/share/config/kwalletrc");
		strcat(homedir,"\0");

		fs = fopen(homedir,"r");
		if(fs == NULL)
		{
			free (homedir);
			free (defaultwallet);
			return "kdewallet";
		}
		while(!feof(fs))
   		{
			fgets(str,MAX_LENGTH,fs);
			for(i=0; str[i] && str1[i]; i++)
			{
				if(str[i] == str1[i])
					continue;
				else
					break;
			}
			if(i==strlen(str1))
			{
				for(j=i,k=0;j<strlen(str);j++,k++)	
					defaultwallet[k] = str[j];
				defaultwallet[k-1] = '\0';
				free(homedir);
				return defaultwallet;
			}
			else	
				continue;
		}
		free(homedir);
		return "kdewallet";
	}	
	
	int RemoveEntry(char *name, char *foldername, char *keyname)
	{
		DCOPCASAConnector kw;
                return(kw.RemoveEntry(name,foldername,keyname));
        }
        int SetEntry(char *name, char *foldername, int entryType, char *keyname, char *value, int valueLen ) 
        {
		char *dwallet = NULL;
		dwallet = (char *)malloc(MAX_LENGTH);
		dwallet = GetDefaultWallet(); //function called here
		DCOPCASAConnector kw;
                //printf("kwallet : In Set Entry\n");
         	return(kw.SetEntry(dwallet,foldername,entryType,keyname,value,valueLen)); 
        }
        int SetMapEntry(char *name, char *foldername, char *keyname, char **value, int eleCount ) 
        {
		char *dwallet = NULL;
		dwallet = (char *)malloc(MAX_LENGTH);
		dwallet = GetDefaultWallet(); //function called here
		DCOPCASAConnector kw;
                //printf("kwallet: SetMapEntry\n");
         	return(kw.SetMap(dwallet,foldername,keyname,value,eleCount)); 
        }
	
	
	



        void FreeList()
        {
           
          struct EnumSecretList *head = tempEnumSecrets;

           // Free the list
          struct EnumSecretList *temp;
          while (head != NULL)
          {
                free(head->walletName);
                free(head->folderName);
                free(head->secretVal);
                //free(head->entryType);
                temp = head->next;
                free(head);
                head = temp;
          }
	 tempEnumSecrets = NULL;

        }
	
	
	
}




	int DCOPCASAConnector::ReadAllWalletSecrets(struct EnumSecretList **enumWalletSecrets) 
        {

		walletList = Wallet::walletList();
		for ( QStringList::Iterator walletIter = walletList.begin(); walletIter != walletList.end(); ++walletIter ) 
		{
                	QString walletName = (*walletIter);
                      //  printf("The wallet name is  %s\n",(*walletIter).latin1());

                        
	                // Open the wallet
        		Wallet *wallet = NULL;
		        wallet = Wallet::openWallet(walletName,0,Wallet::Synchronous);

	                if (wallet == NULL)
        	        {
                	        //printf("Could not open the wallet\n");
	                        return -1;
	                }

	                // Get the folder list of the wallet
        	        QStringList folderList = wallet->folderList();

	                for ( QStringList::Iterator folderIter = folderList.begin(); folderIter != folderList.end(); ++folderIter) 
			{

	                        // printf("\t%s\n",(*folderIter).latin1());
	                        QString folderName = (*folderIter);

	                        // Set the current folder
        	                if (!(wallet->setFolder(folderName)))
		                {
                		        //printf("Could not set the folder\n");
		                        return -1;
		                }

                	        // Get the list of entries in the folder
	                        QStringList entryList = wallet->entryList();

	                        for ( QStringList::Iterator entryIter  = entryList.begin(); entryIter != entryList.end(); ++entryIter) 
				{
                                	//printf("Entry Name : \t\t%s\n",(*entryIter).latin1());

	                                // Read the secret from the entry
	                                QString key = (*entryIter);

        	                        QByteArray *secretVal = new QByteArray();
        	                        if (ReadKey(wallet,key,secretVal) != 0)
	                                {
                	                        //printf("Could not read \"%s\"\n",key.latin1());
                        	                break; 
                                               //FIXME
	                                }

 	                               struct EnumSecretList *tempWalletSecrets = (struct EnumSecretList*)malloc(sizeof(struct EnumSecretList));

        	                        if (tempWalletSecrets == NULL) {
                	                        //printf("Memory Allocation failure\n");
                        	                return -1;
	                                }

        	                        tempWalletSecrets->walletName = (char*)malloc(512);

                	                if (tempWalletSecrets->walletName == NULL) 
					{
			                    //printf("Memory Allocation failure\n");
			                    return -1;
				         }
             
             		                 //printf("Wallet Name is %s\n",walletName.latin1());
                               		strcpy(tempWalletSecrets->walletName, walletName.latin1());
                                	tempWalletSecrets->folderName = (char*)malloc(512);
		
                	                if (tempWalletSecrets->folderName == NULL) 
					{
	                                 	//printf("Memory Allocation failure\n");
        				        return -1;
 				         }
	
        	                       // printf("Folder Name is %s\n",folderName.latin1());

	                                strcpy(tempWalletSecrets->folderName, folderName.latin1());
        	                        tempWalletSecrets->entryType = wallet->entryType(key);
                	               // printf("EntryType is %d\n",wallet->entryType(key));


 	                              if (*enumWalletSecrets == NULL)
                                      {
        	                     	      *enumWalletSecrets = tempWalletSecrets;
                                      }
	                              else
	                              {
  	                                      struct EnumSecretList *iter;
                                              for(iter=*enumWalletSecrets; iter->next!=NULL; iter=iter->next);
                                       	      iter->next = tempWalletSecrets;
	                              }

	                              tempWalletSecrets->next = NULL;



				      //Commented by Austin
		                      QDataStream convert(*secretVal, IO_ReadOnly);
                		      QString passwd;
		                      convert >> passwd;
                                      //QString passwd(*secretVal);
                	              //printf("kwallet : ReadAll key %s value %s \n",key.latin1(), passwd.latin1());
 			              tempWalletSecrets->secretVal = (char*)malloc(512);

 	                               if (tempWalletSecrets->secretVal == NULL)
        	                       {
                                       		//printf("Memory Allocation failure\n");
				                return -1;
			               }

 	                               strcpy(tempWalletSecrets->secretVal,key.latin1());
        	                       //printf("After strcpy - 1 - key is %s\n",key.latin1());
 	                               strcat(tempWalletSecrets->secretVal,"=");
        	                       //printf("After strcat = \n");
                	                if(passwd)
                        	        {
                                		//printf("Passwd is %s\n",passwd.latin1());
	        		                strcat(tempWalletSecrets->secretVal,passwd.latin1());
        	                        }

                               		// Free memory
	                                free(secretVal);
        	                       // printf("After free\n");
	
                        	}

                }


               // Print all the secrets
/*
 	       struct EnumSecretList *iter = *enumWalletSecrets;
	       while (iter != NULL)
	       {
	       		printf("\n\nWallet Name : %s\n",iter->walletName);
		        printf("\tFolder Name : %s\n",iter->folderName);
	        	printf("\t\tSecret Type : %d\n",iter->entryType);
		        printf("\t\t\t Secret Value : %s\n",iter->secretVal);
        		iter = iter->next;
	        }

*/

        }
          
    return(0);

}

int DCOPCASAConnector::SetEntry(char *name, char *foldername, int entryType, char *keyname, char *value, int valueLen ) 
        {
		
		QString qWalletName(name);
		QString qKey(keyname);
		QString qFolderName(foldername);

                QString &refQKey = qKey;
                        
                // Open the wallet
       		Wallet *wallet = NULL;
	        wallet = Wallet::openWallet(qWalletName,0,Wallet::Synchronous);
                if (wallet == NULL)
       	        {
               	        //printf("Could not open the wallet %s \n", qWalletName.latin1());
                        return  KWALLET_RESULT_CANNOT_OPEN_WALLET;
                }
                if (wallet->setFolder(qFolderName) == false)
		{
               	        //printf("Could not open the folder %s \n", qFolderName.latin1());
			return KWALLET_RESULT_CANNOT_OPEN_FOLDER;
		}
                QString unicodeValue = tr(value);
	        // Read the secret from the entry
		//QByteArray secretVal(valueLen *2 );
                
		QByteArray secretVal;
		QDataStream ds(secretVal, IO_WriteOnly);
		ds << unicodeValue;

                /*for(int i=0; i< valueLen; i++)
                {
		        secretVal[i] = 0;
			secretVal[i+1] = value[i];
                }
                */
                //secretVal[valueLen] = '\0';
                
               // secretVal.fill('a');
                //secretVal.setRawData(value,valueLen);
                QByteArray &refSecretVal = secretVal;

		//QDataStream convert( secretVal, IO_WriteOnly );
  	        //convert.readBytes( value, (uint)valueLen);
//                Wallet::EntryType MyEntryType = 3;
		if (wallet->entryType(qKey) != 3) 
		{	
		        //printf("kwallet : SetEntry : Before setting Entry key %s value = %s  EntryType =%d \n" , qKey.latin1() , value, entryType );
			if (wallet->writeEntry(refQKey, refSecretVal , (Wallet::EntryType) entryType ) != 0)
                        {
				return KWALLET_RESULT_CANNOT_WRITE_ENTRY;
			}
		}
		// Free memory
                wallet->sync();
	        return KWALLET_RESULT_OK;	
	}


int DCOPCASAConnector::SetMap(char *name, char *foldername, char *keyname, char **value, int numOfKeys ) 
        {
	  	QString qWalletName(name);
		QString qKey(keyname);
		QString qFolderName(foldername);
                //printf("kwallet : SetMap :  Wallet %s  Folder  %s Key =%s\n", name, foldername, keyname);
              
              
                // Open the wallet
       		Wallet *wallet = NULL;
	        wallet = Wallet::openWallet(qWalletName,0,Wallet::Synchronous);
                if (wallet == NULL)
       	        {
               	        //printf("Could not open the wallet\n");
                        return  KWALLET_RESULT_CANNOT_OPEN_WALLET;
                }


                if (wallet->hasFolder(qFolderName) == false)
                {
		 	if(wallet->createFolder(qFolderName) == false)
                        {
				return KWALLET_RESULT_CANNOT_CREATE_FOLDER;
                        }
                }
                
                if (wallet->setFolder(qFolderName) == false)
		{
			return KWALLET_RESULT_CANNOT_OPEN_FOLDER;
		}
		
		QMap<QString,QString> mapSecret;
		for (int i=0; i < numOfKeys * 2; i+=2)
		{
			QString mapelekey((char *)value[i]);
			QString mapelevalue((char *)value[i+1]);
			mapSecret.insert(mapelekey,mapelevalue);
		}
		if (wallet->writeMap(qKey,mapSecret) != 0 )
                {
			return KWALLET_RESULT_CANNOT_WRITE_ENTRY;
                }
                wallet->sync();
                return KWALLET_RESULT_OK;
}
	
	
	
int DCOPCASAConnector::RemoveEntry(char *name, char *foldername, char *keyname )
{
	
		QString qWalletName(name);
		QString qKey(keyname);
		QString qFolderName(foldername);
                //printf("In DCOPCASAConnector:RemoveEntry\n");
                //printf("In DCOPCASAConnector:False %d\n",false);
                //printf("In DCOPCASAConnector:False %d\n",FALSE);
                        
                // Open the wallet
       		Wallet *wallet = NULL;
	        wallet = Wallet::openWallet(qWalletName,0,Wallet::Synchronous);
                if (wallet == NULL)
       	        {
               	        //printf("Could not open the wallet %s \n", qWalletName.latin1());
                        return  KWALLET_RESULT_CANNOT_OPEN_WALLET;
                }
                if (wallet->setFolder(qFolderName) ==  false)
		{
                        //printf("Could not set the folder %s \n", qFolderName.latin1());
			return KWALLET_RESULT_CANNOT_OPEN_FOLDER;
		}
		if (wallet->removeEntry(qKey) != 0)
		{
                        //printf("Could not remove Entry  %s \n", qKey.latin1());
			return KWALLET_RESULT_CANNOT_REMOVE_ENTRY;
		}
                wallet->sync();
                //printf("In DCOPCASAConnector:RemoveEntry Exit\n");
		return KWALLET_RESULT_OK;
}