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

using System;
using System.Runtime.InteropServices;
using System.Collections.Specialized;
using System.Collections;
using System.Threading;
using Gtk;
using GLib;


namespace Novell.CASA.DataEngines.GK
{
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public class KeyringInfo
    {
        public int lockOnIdle;
        public uint lockTimeout;
        public uint mTime;
        public uint cTime;
        public int isLocked;
    }
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public class NativeItemInfo
    {
        public int itemType;
        public IntPtr displayName;
        public IntPtr secret;
        public int mTime;
        public int cTime;
        public NativeItemInfo()
        {
	/* The GUI allows 256 as the max number of chars for these items */
            displayName = Marshal.AllocHGlobal(256);
            secret = Marshal.AllocHGlobal(256);
        }
        ~NativeItemInfo()
        {
            Marshal.FreeHGlobal(displayName);
            Marshal.FreeHGlobal(secret);
        }
    }

    public class ItemInfo
    {
        public string itemType;
        public string displayName;
        public string secret;
        public int mTime;
        public int cTime;
    }


    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public class NativeAttribute
    {
        public uint type;
        public IntPtr key;
        public IntPtr value;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public class Attribute
    {
        public uint type;
        public string key;
        public string value;
    
    }

    public class GnomeKeyring
    {
        [DllImport("libad_gk.so")]
        public static extern int GetKeyrings(out IntPtr list);
        [DllImport("libad_gk.so")]
        public static extern int GetKeyringInfo(string name,KeyringInfo info);
        [DllImport("libad_gk.so")]
        public static extern int GetItems(string keyring,out IntPtr list);
        [DllImport("libad_gk.so")]
        public static extern int GetItemInfo(string keyring,int itemId, NativeItemInfo info);
        [DllImport("libad_gk.so")]
        public static extern int GetAttributeList(string keyring,int itemId, out IntPtr attrList);
        [DllImport("libad_gk.so")]
        public static extern int FreeAttributeList(IntPtr attrList);
        [DllImport("libad_gk.so")]
	    public static extern int SetPassword (string keyring, int itemid, string password);
	    [DllImport("libad_gk.so")]
	    public static extern int RemoveItem (string keyring, int itemid);
	    [DllImport("libad_gk.so")]
	    public static extern int SetItemAttributes (string keyring, int itemid, IntPtr[] attrs, int length);
	    [DllImport("libad_gk.so")]
	    public static extern int CreateItem(string keyringName, int itemType, string displayName, string password, IntPtr[] arrptr, int attrCount);
	    [DllImport("libad_gk.so")]
	    public static extern int UnlockRing(string sKeyringName, string sPassword);
        [DllImport("libad_gk.so")]
        public static extern int LoadGnomeKeyringLibrary();
        [DllImport("libad_gk.so")]
        public static extern int ReleaseGnomeKeyringLibrary();

        public static bool IsGnomeKeyringInstalled()
        {
            if (0 == LoadGnomeKeyringLibrary())
                return true;
            else
                return false;
        }

        public static void ReleaseGnomeKeyringLib()
        {
            ReleaseGnomeKeyringLibrary();
        }

	public static void AttemptGKUnlock(string sPassword)
	{
		ArrayList alKeyRings = GKGetKeyrings();
		IEnumerator kEtor = alKeyRings.GetEnumerator();
		while (kEtor.MoveNext())
		{
			string sKeyring = (string)(kEtor.Current);
			try 
			{
				UnlockGnomeKeyring(sKeyring, sPassword);
			}
			catch {}
		}

	}

	public static int UnlockGnomeKeyring(string sKeyringName, string sPassword)
	{
		int rcode = UnlockRing(sKeyringName, sPassword);
		return rcode;
	}


	

        public static KeyringInfo GKGetKeyringInfo(string name)
        {
            KeyringInfo info = null;
            try
            {
                info = new KeyringInfo();
                int retVal = GetKeyringInfo(name,info);
                if( 0 != retVal )
                    info = null;
            }
            catch(Exception e)
            {
                //Console.WriteLine(e.ToString());
                info = null;
            }
            return info;
        }

        public static void PrintKeyringInfo(KeyringInfo info)
        {
            if( null == info )
                return;
            try
            {
                //Console.WriteLine("lockOnIdle = " + info.lockOnIdle);
                //Console.WriteLine("lockTimeout = " + info.lockTimeout);
                //Console.WriteLine("mTime = " + info.mTime);
                //Console.WriteLine("cTime = " + info.cTime);
                //Console.WriteLine("isLocked = " + info.isLocked);
            }
            catch(Exception e)
            {
                //Console.WriteLine(e.ToString());
            }
        }
    
        public static ItemInfo GKGetItemInfo(string keyring, int itemId)
        {
            ItemInfo info = null;
            try
            {
                NativeItemInfo nativeItemInfo = new NativeItemInfo();
                int retVal = GetItemInfo(keyring, itemId, nativeItemInfo);

                if( 0 != retVal )
                    info = null;
                else
                {
                    info = new ItemInfo();
                    if(nativeItemInfo.itemType == 0)
                        info.itemType = "Generic Secret";
                    else if(nativeItemInfo.itemType == 1)
                        info.itemType = "Network Password";
                    else if(nativeItemInfo.itemType == 2)
                        info.itemType = "Note";
                    else
                        info.itemType = "No Type"; // need to have a better name
                    
                    info.displayName = Marshal.PtrToStringAnsi(nativeItemInfo.displayName);
                    info.secret = Marshal.PtrToStringAnsi(nativeItemInfo.secret);
                    info.mTime = nativeItemInfo.mTime;
                    info.cTime = nativeItemInfo.cTime;
                }
            }
            catch(Exception e)
            {
                //Console.WriteLine(e.ToString());
                info = null;
            }
            return info;
        }

        public static void PrintItemInfo(ItemInfo info)
        {
            if( null == info )
                return;
            try
            {
                //Console.WriteLine("CS : itemType = " + info.itemType);
                //Console.WriteLine("CS : displayName = " + info.displayName);
                //Console.WriteLine("CS : secret = " + info.secret);
                //Console.WriteLine("CS : mTime = " + info.mTime);
                //Console.WriteLine("CS : cTime = " + info.cTime);
            }
            catch(Exception e)
            {
                //Console.WriteLine(e.ToString());
            }
        }

        public static ArrayList GKGetKeyrings()
        {
            ArrayList retList;
            try
            {
                retList = new ArrayList();
                IntPtr list = new IntPtr();
                int retVal = GetKeyrings(out list);
                if ( 0 != retVal )
                    retList = null;
                GLib.List keyringList = new List(list,typeof(string));
                IEnumerator etor = (IEnumerator)(keyringList.GetEnumerator());
                string name;
                while(etor.MoveNext())
                {
                    name = (string)etor.Current;
                    retList.Add(name);
                }
            }
            catch(Exception e)
            {
                //Console.WriteLine(e.ToString());
                retList = null;
            }
            return retList;
        }

        public static ArrayList GKGetItems(string keyring)
        {
            ArrayList retList = null;
            try
            {
                retList = new ArrayList();
                IntPtr list = new IntPtr();
                int retVal = GetItems(keyring,out list);
                if( 0 != retVal )
                    retList = null;
                GLib.List itemList = new List(list,typeof(int));
                IEnumerator etor = (IEnumerator)(itemList.GetEnumerator());
                int itemId;
                while(etor.MoveNext())
                {
                    itemId = (int)etor.Current;
                    retList.Add(itemId);
                }
            }
            catch(Exception e)
            {
                //Console.WriteLine(e.ToString());
                retList = null;
            }
            return retList;
        }

        public static ArrayList GKGetAttributeList(string keyring, int itemId)
        {
            ArrayList retList = null;
            try
            {
                retList = new ArrayList();
                IntPtr list = new IntPtr();
                int retVal = GetAttributeList(keyring, itemId,out list);
                if( 0 != retVal )
                    retList = null;
                GLib.List attrList = new List(list,typeof(int));
                IEnumerator etor = (IEnumerator)(attrList.GetEnumerator());
                while(etor.MoveNext())
                {
                    int test = (int)etor.Current;
                    IntPtr ptr = new IntPtr(test);
   
                    NativeAttribute attr = new NativeAttribute();
                    attr = (NativeAttribute)Marshal.PtrToStructure(ptr,typeof(NativeAttribute));
  
                    string key = Marshal.PtrToStringAnsi(attr.key);
                    string value = Marshal.PtrToStringAnsi(attr.value);

                    Attribute retAttr = new Attribute();
                    retAttr.type = attr.type;
                    retAttr.key = String.Copy(key);
                    retAttr.value = String.Copy(value);
                    retList.Add(retAttr);
                }
                if(retList.Count > 0)
                    FreeAttributeList(list);
            }
            catch(Exception e)
            {
                //Console.WriteLine(e.ToString());
                retList = null;
            }
            return retList;
        }

        public static void PrintAttrList(ArrayList attrList)
        {
            if( null == attrList )
                return;
            Attribute attr;
            try
            {
                IEnumerator etor = (IEnumerator)(attrList.GetEnumerator());
                while(etor.MoveNext())
                {
                    attr = (Attribute)(etor.Current);
                    //Console.WriteLine("CS : AttrType = " + attr.type);
                    //Console.WriteLine("CS : AttrKey = " + attr.key);
                    //Console.WriteLine("CS : AttrValue = " + attr.value);
                }
            }    
            catch(Exception e)
            {
                //Console.WriteLine(e.ToString());
            }
        }
	
	
	public static int SetAttributes(String keyringName, int itemId, NameValueCollection nvc)
	{
         	IntPtr[] arrptr = new IntPtr[nvc.Count];
	        for(int i=0; i < nvc.Count; i++)
        	{
                	string key = nvc.GetKey(i);
	                string value = nvc.Get(key);
        	        Attribute attr = new Attribute();
                	attr.type=0;
	                attr.key=key;
        	        attr.value=value;
                	IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(attr));
	                Marshal.StructureToPtr(attr,ptr,false);
        	        arrptr[i] = ptr;
         	}
         	int ret  = SetItemAttributes( keyringName,itemId,arrptr,nvc.Count);
	        FreeIntPtrArray(arrptr);
        	return ret;
       }
       
       
       public static int RemoveSecret(string keyringname, int itemid)
       {

		return(RemoveItem(keyringname,itemid));
       }
	
	public static int CreateSecret(String keyringName, string strItemType, string displayName, string password, NameValueCollection nvc)
	{
                //Console.WriteLine("In CreateSecret ");
                int itemType = 3; //No Type 
         	IntPtr[] arrptr = new IntPtr[nvc.Count];
                if(strItemType.CompareTo("Generic Secret") == 0 )
                {
                        itemType = 0;
                }
                else
	        if(strItemType.CompareTo("Network Password") == 0 )
                {
			itemType = 1;
                }
         	else
                if(strItemType.CompareTo("Note") == 0 )
                {
                       itemType =  2;
                }
                //Console.WriteLine("In CreateSecret ItemType = "+itemType);
	        for(int i=0; i < nvc.Count; i++)
        	{
                	string key = nvc.GetKey(i);
                        //Console.WriteLine("In CreateSecret Key "+i + " = " + key);
	                string value = nvc.Get(key);
                        //Console.WriteLine("In CreateSecret Value "+i + " = " + value);
        	        Attribute attr = new Attribute();
                	attr.type=0;
                	attr.key=key;
                	attr.value=value;
                	IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(attr));
                	Marshal.StructureToPtr(attr,ptr,false);
                	arrptr[i] = ptr;
                }
                //Console.WriteLine("Calling Create item ");         
		int ret = CreateItem(keyringName, itemType, displayName, password, arrptr, nvc.Count);
                FreeIntPtrArray(arrptr);
                return ret;
        }
       
       public static void FreeIntPtrArray(IntPtr[] arrptr)
       {
		for(int i=0; i < arrptr.Length; i++)
                {
			Marshal.FreeHGlobal(arrptr[i]);
                }
       }	
    }
}