Added support for options in favorite identities.
authorAlexandra Ellwood <lxs@mit.edu>
Wed, 17 Sep 2008 21:29:35 +0000 (21:29 +0000)
committerAlexandra Ellwood <lxs@mit.edu>
Wed, 17 Sep 2008 21:29:35 +0000 (21:29 +0000)
Fixed KLL preference reading support to not read keys
from the wrong locations.  Updated prompter function
prototype.

Updated tests to reflect these changes.

ticket: 6055

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@20727 dc483132-0cff-0310-8789-dd5450dbe970

src/include/kim/kim_options.h
src/kim/lib/kim-lite.exports
src/kim/lib/kim_options.c
src/kim/lib/kim_options_private.h
src/kim/lib/kim_preferences.c
src/kim/lib/kim_preferences_private.h
src/kim/lib/mac/kim_os_preferences.c
src/kim/test/main.c
src/kim/test/test_kim_preferences.c
src/kim/test/test_kim_preferences.h

index fd6efdf478ca1f1bd4bb2fde9a0d205999807eed..f5b975cf3e41fd0ff15e63e96d38cd003c9ed29d 100644 (file)
@@ -62,45 +62,41 @@ enum kim_prompt_type_enum {
  * The prompt callback used to display a prompt to the user.
  * See \ref kim_options_custom_prompt_callback for more information.
  */
-typedef kim_error (*kim_prompt_callback) (kim_options       *io_options, 
-                                          kim_prompt_type    in_type,
+typedef kim_error (*kim_prompt_callback) (kim_prompt_type    in_type,
                                           kim_string         in_title,
                                           kim_string         in_message,
                                           kim_string         in_description,
-                                          void               **out_reply);
+                                          char              **out_reply);
 
 /*!
  * The default prompt callback.
  * See \ref kim_options_custom_prompt_callback for more information.
  */
-kim_error kim_prompt_callback_default (kim_options       *io_options, 
-                                       kim_prompt_type    in_type,
+kim_error kim_prompt_callback_default (kim_prompt_type    in_type,
                                        kim_string         in_title,
                                        kim_string         in_message,
                                        kim_string         in_description,
-                                       void             **out_reply);
+                                       char              **out_reply);
     
 /*!
  * The graphical prompt callback.
  * See \ref kim_options_custom_prompt_callback for more information.
  */
-kim_error kim_prompt_callback_gui (kim_options       *io_options, 
-                                   kim_prompt_type    in_type,
+kim_error kim_prompt_callback_gui (kim_prompt_type    in_type,
                                    kim_string         in_title,
                                    kim_string         in_message,
                                    kim_string         in_description,
-                                   void             **out_reply);
+                                   char              **out_reply);
 
 /*!
  * The command line prompt callback.
  * See \ref kim_options_custom_prompt_callback for more information.
  */
-kim_error kim_prompt_callback_cli (kim_options       *io_options, 
-                                   kim_prompt_type    in_type,
+kim_error kim_prompt_callback_cli (kim_prompt_type    in_type,
                                    kim_string         in_title,
                                    kim_string         in_message,
                                    kim_string         in_description,
-                                   void             **out_reply);
+                                   char              **out_reply);
 
 /*!
  * The prompt callback which always returns an error.
@@ -108,12 +104,11 @@ kim_error kim_prompt_callback_cli (kim_options       *io_options,
  * \note Using this callback may prevent the user from authenicating.
  * See \ref kim_options_custom_prompt_callback for more information.
  */
-kim_error kim_prompt_callback_none (kim_options       *io_options, 
-                                    kim_prompt_type    in_type,
+kim_error kim_prompt_callback_none (kim_prompt_type    in_type,
                                     kim_string         in_title,
                                     kim_string         in_message,
                                     kim_string         in_description,
-                                    void             **out_reply);
+                                    char              **out_reply);
 
 /*! @} */
 
@@ -143,7 +138,7 @@ kim_error kim_prompt_callback_none (kim_options       *io_options,
  * \subsection kim_options_custom_prompt_callback Providing a Custom Prompt Callback
  *
  * All secrets are obtained from the user through a #kim_prompt_callback_t.  By default, 
- * options use #kim_prompt_callback_default, which presents an expanding dialog to request
+ * options use #kim_prompt_callback_default, which presents a dialog to request
  * information from the user, or if no graphical access is available, a command line prompt.
  * 
  * KIM also provides three other callbacks: #kim_prompt_callback_gui only presents
@@ -154,28 +149,11 @@ kim_error kim_prompt_callback_none (kim_options       *io_options,
  * Using #kim_options_set_prompt_callback(), you can change the prompt callback to one of 
  * the above callbacks or a callback you have defined yourself.  Callbacks are called in a
  * loop, one for each prompt.  Because network traffic may occur between calls to the prompt
- * callback, your prompt interface should support time passing between calls to the prompter.  
+ * callback, your prompt interface should support time passing between calls to the prompter.
  * If you are defining a callback yourself, you should also set your own options data with 
  * #kim_options_set_data() for storing state between calls.  Options data is a caller
  * defined pointer value -- the Kerberos libaries make no use of it.
  *
- * \subsection kim_options_preset_prompts Prefetching Prompt Responses
- * 
- * Sometimes you may have already collected some of the information needed to acquire 
- * Kerberos credentials.  Rather than creating a prompt callback, you may also prefetch 
- * responses to the options directly with #kim_options_set_prompt_response().  Once you 
- * have associated your response with a given prompt type, the Kerberos libraries will 
- * use this response for the first prompt of that type rather than calling the prompt 
- * callback to obtain it.
- *
- * Note that even if you prefetch responses, the prompt callback may still be called if
- * you did not provide all the information required for the identity.  You may specify 
- * the #kim_prompt_callback_none prompt callback to prevent prompting from occuring entirely,
- * however, doing so will tie your application to a particular Kerberos configuration.  
- * For example, if your application assumes that all identities only require a password, 
- * it will not be able to acquire credentials at sites using SecurID pins.  
- *
- * 
  * \section kim_options_credential_properties Options for Controlling Credential Properties
  *
  * Kerberos credentials have a number of different properties which can be requested
@@ -362,44 +340,6 @@ kim_error kim_options_set_data (kim_options  io_options,
 kim_error kim_options_get_data (kim_options   in_options,
                                 const void  **out_data);
 
-/*!
- * \param io_options     an options object to modify.
- * \param in_prompt_type a type of prompt.
- * \param in_response    a response to prompts of \a in_prompt_type.
- * \return On success, #KIM_NO_ERROR.  On failure, an error code representing the failure.
- * \brief Set a response for a prompt for use when acquiring credentials.
- * \note Each response only overrides the first prompt of a given prompt type.  If multiple
- * prompts of the same type are required, or if a prompt of a different type is requested, 
- * the prompt callback will be called to obtain user input.  If you want to turn off prompting 
- * entirely, call #kim_options_set_prompt_callback() with #kim_prompt_callback_none.
- * \par Default value
- * NULL (no response is set by default)
- * \sa kim_options_get_prompt_response()
- */
-kim_error kim_options_set_prompt_response (kim_options      io_options,
-                                           kim_prompt_type  in_prompt_type,
-                                           void            *in_response);
-
-/*!
- * \param in_options     an options object.
- * \param in_prompt_type a type of prompt.
- * \param out_response   on exit, the response to prompts of type \a in_prompt_type specified 
- *                       by \a in_options.  Does not need to be freed but may become invalid
- *                       when \a in_options is freed.
- * \return On success, #KIM_NO_ERROR.  On failure, an error code representing the failure.
- * \brief Get the response for a prompt for use when acquiring credentials.
- * \note Each response only overrides the first prompt of a given prompt type.  If multiple
- * prompts of the same type are required, or if a prompt of a different type is requested, 
- * the prompt callback will be called to obtain user input.  If you want to turn off prompting 
- * entirely, call #kim_options_set_prompt_callback() with #kim_prompt_callback_none.
- * \par Default value
- * NULL (no response is set by default)
- * \sa kim_options_set_prompt_response()
- */
-kim_error kim_options_get_prompt_response (kim_options       in_options,
-                                           kim_prompt_type   in_prompt_type,
-                                           void            **out_response);
-
 /*!
  * \param io_options    an options object to modify.
  * \param in_start_time a start date (in seconds since January 1, 1970).  Set to  
index d9b277c27fa195d3f841067d6e7dc3df36c8503e..44a428dac55820a83a036d26cabcb10272ba67b5 100644 (file)
@@ -31,8 +31,6 @@ kim_options_set_prompt_callback
 kim_options_get_prompt_callback
 kim_options_set_data
 kim_options_get_data
-kim_options_set_prompt_response
-kim_options_get_prompt_response
 kim_options_set_start_time
 kim_options_get_start_time
 kim_options_set_lifetime
index f210bb4fa81439cbb4591b8c9e23af74767ee73b..dbb024c2d5333c63ce6dc660da9b38bc69ec96a1 100644 (file)
@@ -31,7 +31,6 @@
 struct kim_options_opaque {
     kim_prompt_callback prompt_callback;
     const void *prompt_callback_data;
-#warning add prompt responses here
     kim_time start_time;
     kim_lifetime lifetime;
     kim_boolean renewable;
@@ -80,25 +79,9 @@ static inline kim_error kim_options_allocate (kim_options *out_options)
 
 /* ------------------------------------------------------------------------ */
 
-kim_error kim_options_create_from_defaults (kim_options *out_options)
+kim_error kim_options_create_empty (kim_options *out_options)
 {
-    kim_error err = KIM_NO_ERROR;
-    kim_options options = NULL;
-    
-    if (!err && !out_options) { err = check_error (KIM_NULL_PARAMETER_ERR); }
-    
-    if (!err) {
-        err = kim_options_allocate (&options);
-    }
-    
-    if (!err) {
-        *out_options = options;
-        options = NULL;
-    }
-    
-    kim_options_free (&options);
-    
-    return check_error (err);
+    return check_error (kim_options_allocate (out_options));
 }
 
 /* ------------------------------------------------------------------------ */
@@ -140,7 +123,6 @@ kim_error kim_options_copy (kim_options *out_options,
         if (!err) {
             options->prompt_callback = in_options->prompt_callback;
             options->prompt_callback_data = in_options->prompt_callback_data;
-#warning copy prompt responses here
         }
         
         if (!err) {
@@ -238,42 +220,6 @@ kim_error kim_options_get_data (kim_options   in_options,
 
 /* ------------------------------------------------------------------------ */
 
-kim_error kim_options_set_prompt_response (kim_options      io_options,
-                                           kim_prompt_type  in_prompt_type,
-                                           void            *in_response)
-{
-    kim_error err = KIM_NO_ERROR;
-    
-    if (!err && !io_options ) { err = check_error (KIM_NULL_PARAMETER_ERR); }
-    if (!err && !in_response) { err = check_error (KIM_NULL_PARAMETER_ERR); }
-    
-    if (!err) {
-#warning kim_options_set_prompt_response unimplemented
-    }
-    
-    return check_error (err);
-}
-
-/* ------------------------------------------------------------------------ */
-
-kim_error kim_options_get_prompt_response (kim_options       in_options,
-                                           kim_prompt_type   in_prompt_type,
-                                           void            **out_response)
-{
-    kim_error err = KIM_NO_ERROR;
-    
-    if (!err && !in_options  ) { err = check_error (KIM_NULL_PARAMETER_ERR); }
-    if (!err && !out_response) { err = check_error (KIM_NULL_PARAMETER_ERR); }
-    
-    if (!err) {
-#warning kim_options_get_prompt_response unimplemented
-    }
-    
-    return check_error (err);
-}
-
-/* ------------------------------------------------------------------------ */
-
 kim_error kim_options_set_start_time (kim_options io_options,
                                       kim_time    in_start_time)
 {
@@ -514,7 +460,7 @@ kim_error kim_options_set_service_name (kim_options  io_options,
     if (!err && !io_options     ) { err = check_error (KIM_NULL_PARAMETER_ERR); }
     if (!err && !in_service_name) { err = check_error (KIM_NULL_PARAMETER_ERR); }
     
-    if (!err) {
+    if (!err && in_service_name) {
         err = kim_string_copy (&service_name, in_service_name);
     }
     
@@ -537,7 +483,11 @@ kim_error kim_options_get_service_name (kim_options  in_options,
     if (!err && !out_service_name) { err = check_error (KIM_NULL_PARAMETER_ERR); }
     
     if (!err) {
-        err = kim_string_copy (out_service_name, in_options->service_name);
+        if (in_options->service_name) {
+            err = kim_string_copy (out_service_name, in_options->service_name);
+        } else {
+            *out_service_name = NULL;
+        }
     }
     
     return check_error (err);
@@ -616,17 +566,15 @@ void kim_options_free (kim_options *io_options)
 
 /* ------------------------------------------------------------------------ */
 
-kim_error kim_prompt_callback_default (kim_options       *io_options, 
-                                       kim_prompt_type    in_type,
+kim_error kim_prompt_callback_default (kim_prompt_type    in_type,
                                        kim_string         in_title,
                                        kim_string         in_message,
                                        kim_string         in_description,
-                                       void               **out_reply)
+                                       char              **out_reply)
 {
     kim_error err = KIM_NO_ERROR;
     
-    if (!err && !io_options) { err = check_error (KIM_NULL_PARAMETER_ERR); }
-    if (!err && !out_reply ) { err = check_error (KIM_NULL_PARAMETER_ERR); }
+    if (!err && !out_reply) { err = check_error (KIM_NULL_PARAMETER_ERR); }
     
     if (!err) {
     }
@@ -636,17 +584,15 @@ kim_error kim_prompt_callback_default (kim_options       *io_options,
 
 /* ------------------------------------------------------------------------ */
 
-kim_error kim_prompt_callback_gui (kim_options       *io_options, 
-                                   kim_prompt_type    in_type,
+kim_error kim_prompt_callback_gui (kim_prompt_type    in_type,
                                    kim_string         in_title,
                                    kim_string         in_message,
                                    kim_string         in_description,
-                                   void               **out_reply)
+                                   char              **out_reply)
 {
     kim_error err = KIM_NO_ERROR;
     
-    if (!err && !io_options) { err = check_error (KIM_NULL_PARAMETER_ERR); }
-    if (!err && !out_reply ) { err = check_error (KIM_NULL_PARAMETER_ERR); }
+    if (!err && !out_reply) { err = check_error (KIM_NULL_PARAMETER_ERR); }
     
     if (!err) {
     }
@@ -656,17 +602,15 @@ kim_error kim_prompt_callback_gui (kim_options       *io_options,
 
 /* ------------------------------------------------------------------------ */
 
-kim_error kim_prompt_callback_cli (kim_options       *io_options, 
-                                   kim_prompt_type    in_type,
+kim_error kim_prompt_callback_cli (kim_prompt_type    in_type,
                                    kim_string         in_title,
                                    kim_string         in_message,
                                    kim_string         in_description,
-                                   void               **out_reply)
+                                   char              **out_reply)
 {
     kim_error err = KIM_NO_ERROR;
     
-    if (!err && !io_options) { err = check_error (KIM_NULL_PARAMETER_ERR); }
-    if (!err && !out_reply ) { err = check_error (KIM_NULL_PARAMETER_ERR); }
+    if (!err && !out_reply) { err = check_error (KIM_NULL_PARAMETER_ERR); }
     
     if (!err) {
     }
@@ -676,12 +620,11 @@ kim_error kim_prompt_callback_cli (kim_options       *io_options,
 
 /* ------------------------------------------------------------------------ */
 
-kim_error kim_prompt_callback_none (kim_options       *io_options, 
-                                    kim_prompt_type    in_type,
+kim_error kim_prompt_callback_none (kim_prompt_type    in_type,
                                     kim_string         in_title,
                                     kim_string         in_message,
                                     kim_string         in_description,
-                                    void               **out_reply)
+                                    char              **out_reply)
 {
     return KIM_USER_CANCELED_ERR;
 }
index 8dbe0a30e849c3ceb8b51f0c73f99f77c8bc869a..f11d414ef33901b7440975d276e65d4beaa64b67 100644 (file)
@@ -29,7 +29,7 @@
 
 #include <kim/kim.h>
 
-kim_error kim_options_create_from_defaults (kim_options *out_options);
+kim_error kim_options_create_empty (kim_options *out_options);
 
 kim_error kim_options_get_init_cred_options (kim_options               in_options, 
                                              krb5_context              in_context,
index 6b1fb5cc99c892bf7137f6c9c6c8db74584a0d4c..8ec5fd16c68f38977643d245599113042e2121b0 100644 (file)
@@ -54,7 +54,7 @@ struct kim_preferences_opaque {
 const struct kim_favorites_opaque kim_default_favorites = { 0, NULL, NULL };
 
 struct kim_preferences_opaque kim_preferences_initializer = { 
-NULL
+KIM_OPTIONS_DEFAULT
 FALSE,
 kim_default_remember_options, 
 FALSE,
@@ -184,6 +184,8 @@ kim_error kim_favorites_get_identity_at_index (kim_favorites  in_favorites,
                                                kim_options   *out_options)
 {
     kim_error err = KIM_NO_ERROR;
+    kim_identity identity = NULL;
+    kim_options options = KIM_OPTIONS_DEFAULT;
     
     if (!err && !in_favorites) { err = check_error (KIM_NULL_PARAMETER_ERR); }
     if (!err && !out_identity) { err = check_error (KIM_NULL_PARAMETER_ERR); }
@@ -197,10 +199,26 @@ kim_error kim_favorites_get_identity_at_index (kim_favorites  in_favorites,
     }
     
     if (!err) {
-        err = kim_identity_copy (out_identity, 
-                                 in_favorites->identities[in_index]);
+        err = kim_identity_copy (&identity, in_favorites->identities[in_index]);
+    }
+    
+    if (!err && in_favorites->options[in_index]) {
+        err = kim_options_copy (&options, in_favorites->options[in_index]);
+    }
+    
+    if (!err) {
+        *out_identity = identity;
+        identity = NULL;
+        
+        if (out_options) {
+            *out_options = options;
+            options = NULL;
+        }
     }
     
+    kim_identity_free (&identity);
+    kim_options_free (&options);
+    
     return check_error (err);
 }
 
@@ -233,13 +251,14 @@ kim_error kim_favorites_add_identity (kim_favorites io_favorites,
         for (i = 0; !err && i < io_favorites->count; i++) {
             kim_comparison identity_comparison = 0;
             
-            err = kim_identity_compare (in_identity, 
-                                        io_favorites->identities[i]
+            err = kim_identity_compare (io_favorites->identities[i],
+                                        in_identity
                                         &identity_comparison);
             
             if (!err) {
                 if (kim_comparison_is_greater_than (identity_comparison)) {
-                    break; /* found the first greater one so insert here */
+                    /* insert before the first entry that is greater than us */
+                    break; 
                     
                 } else if (kim_comparison_is_equal_to (identity_comparison)) {
                     /* already in list */
@@ -396,74 +415,14 @@ static kim_error kim_preferences_read (kim_preferences in_preferences)
     if (!err && !in_preferences) { err = check_error (KIM_NULL_PARAMETER_ERR); }
     
     if (!err) {
-        kim_lifetime lifetime = kim_default_lifetime;
-        
-        err = kim_os_preferences_get_lifetime_for_key (kim_preference_key_lifetime,
-                                                       kim_default_lifetime,
-                                                       &lifetime);
-        
-        if (!err) {
-            err = kim_options_set_lifetime (in_preferences->options, lifetime);
-        }
-    }
-    
-    if (!err) {
-        kim_boolean renewable = kim_default_renewable;
-        
-        err = kim_os_preferences_get_boolean_for_key (kim_preference_key_renewable,
-                                                      kim_default_renewable,
-                                                      &renewable);
-        
-        if (!err) {
-            err = kim_options_set_renewable (in_preferences->options, renewable);
-        }
-    }
-    
-    if (!err) {
-        kim_lifetime renewal_lifetime = kim_default_renewal_lifetime;
-        
-        err = kim_os_preferences_get_lifetime_for_key (kim_preference_key_renewal_lifetime,
-                                                       kim_default_renewal_lifetime,
-                                                       &renewal_lifetime);
-        
-        if (!err) {
-            err = kim_options_set_renewal_lifetime (in_preferences->options, renewal_lifetime);
-        }
-    }
-    
-    if (!err) {
-        kim_boolean forwardable = kim_default_forwardable;
-        
-        err = kim_os_preferences_get_boolean_for_key (kim_preference_key_forwardable,
-                                                      kim_default_forwardable,
-                                                      &forwardable);
-        
-        if (!err) {
-            err = kim_options_set_forwardable (in_preferences->options, forwardable);
-        }
-    }
-    
-    if (!err) {
-        kim_boolean proxiable = kim_default_proxiable;
-        
-        err = kim_os_preferences_get_boolean_for_key (kim_preference_key_proxiable,
-                                                      kim_default_proxiable,
-                                                      &proxiable);
-        
-        if (!err) {
-            err = kim_options_set_proxiable (in_preferences->options, proxiable);
-        }
-    }
-    
-    if (!err) {
-        kim_boolean addressless = kim_default_addressless;
+        kim_options options = NULL;
         
-        err = kim_os_preferences_get_boolean_for_key (kim_preference_key_addressless,
-                                                      kim_default_addressless,
-                                                      &addressless);
+        err = kim_os_preferences_get_options_for_key (kim_preference_key_options,
+                                                      &options);
         
         if (!err) {
-            err = kim_options_set_addressless (in_preferences->options, addressless);
+            kim_options_free (&in_preferences->options);
+            in_preferences->options = options;
         }
     }
     
@@ -545,69 +504,8 @@ static kim_error kim_preferences_write (kim_preferences in_preferences)
     if (!err && !in_preferences) { err = check_error (KIM_NULL_PARAMETER_ERR); }
     
     if (!err && in_preferences->remember_options && in_preferences->options_changed) {
-        kim_lifetime lifetime = kim_default_lifetime;
-        
-        err = kim_options_get_lifetime (in_preferences->options, &lifetime);
-        
-        if (!err) {
-            err = kim_os_preferences_set_lifetime_for_key (kim_preference_key_lifetime, 
-                                                           lifetime);
-        }
-        
-        if (!err) {
-            kim_boolean renewable = kim_default_renewable;
-            
-            err = kim_options_get_renewable (in_preferences->options, &renewable);
-            
-            if (!err) {
-                err = kim_os_preferences_set_boolean_for_key (kim_preference_key_renewable, 
-                                                              renewable);
-            }
-        }
-        
-        if (!err) {
-            kim_lifetime renewal_lifetime = kim_default_renewal_lifetime;
-            
-            err = kim_options_get_renewal_lifetime (in_preferences->options, &renewal_lifetime);
-            
-            if (!err) {
-                err = kim_os_preferences_set_lifetime_for_key (kim_preference_key_renewal_lifetime, 
-                                                               renewal_lifetime);
-            }
-        }
-        
-        if (!err) {
-            kim_boolean forwardable = kim_default_forwardable;
-            
-            err = kim_options_get_forwardable (in_preferences->options, &forwardable);
-            
-            if (!err) {
-                err = kim_os_preferences_set_boolean_for_key (kim_preference_key_forwardable, 
-                                                              forwardable);
-            }
-        }
-        
-        if (!err) {
-            kim_boolean proxiable = kim_default_proxiable;
-            
-            err = kim_options_get_proxiable (in_preferences->options, &proxiable);
-            
-            if (!err) {
-                err = kim_os_preferences_set_boolean_for_key (kim_preference_key_proxiable, 
-                                                              proxiable);
-            }
-        }
-        
-        if (!err) {
-            kim_boolean addressless = kim_default_addressless;
-            
-            err = kim_options_get_addressless (in_preferences->options, &addressless);
-            
-            if (!err) {
-                err = kim_os_preferences_set_boolean_for_key (kim_preference_key_addressless, 
-                                                              addressless);
-            }
-        }
+        err = kim_os_preferences_set_options_for_key (kim_preference_key_options,
+                                                      in_preferences->options);        
     }
     
     if (!err && in_preferences->remember_options_changed) {
@@ -709,10 +607,6 @@ kim_error kim_preferences_create (kim_preferences *out_preferences)
         err = kim_preferences_allocate (&preferences);
     }
     
-    if (!err) {
-        err = kim_options_create_from_defaults (&preferences->options);
-    }
-    
     if (!err) {
         err = kim_preferences_read (preferences);
     }
index 831fba452017522c073b16727d7a3b2cbd1f97a6..23909882967727b01878f1e9bf55c513d9cc5cc0 100644 (file)
@@ -32,6 +32,7 @@
 typedef struct kim_favorites_opaque *kim_favorites;
 
 typedef enum kim_preference_key_enum {
+    kim_preference_key_options,
     kim_preference_key_lifetime,
     kim_preference_key_renewable,
     kim_preference_key_renewal_lifetime,
@@ -89,6 +90,12 @@ kim_error kim_favorites_remove_all_identities (kim_favorites io_favorites);
 
 /* OS-specific functions to be implemented per-platform */
 
+kim_error kim_os_preferences_get_options_for_key (kim_preference_key  in_key, 
+                                                   kim_options       *out_options);
+
+kim_error kim_os_preferences_set_options_for_key (kim_preference_key in_key, 
+                                                  kim_options        in_options);
+
 kim_error kim_os_preferences_get_identity_for_key (kim_preference_key  in_key, 
                                                    kim_identity        in_hardcoded_default,
                                                    kim_identity       *out_identity);
@@ -102,13 +109,6 @@ kim_error kim_os_preferences_get_favorites_for_key (kim_preference_key in_key,
 kim_error kim_os_preferences_set_favorites_for_key (kim_preference_key in_key, 
                                                     kim_favorites      in_favorites);
 
-kim_error kim_os_preferences_get_time_for_key (kim_preference_key  in_key, 
-                                               kim_time            in_hardcoded_default,
-                                               kim_time           *out_time);
-
-kim_error kim_os_preferences_set_time_for_key (kim_preference_key in_key, 
-                                               kim_time           in_time);
-
 kim_error kim_os_preferences_get_lifetime_for_key (kim_preference_key  in_key, 
                                                    kim_lifetime        in_hardcoded_default,
                                                    kim_lifetime       *out_lifetime);
index fac8cf6448c730b1cbd222456c716178567faaa2..a915046a3c950f9a7a572bcb3cf4f9f41f887764 100644 (file)
 
 #define kim_os_preference_any_identity "KIM_IDENTITY_ANY"
 
+#pragma mark -
+
 /* ------------------------------------------------------------------------ */
 
-static kim_error kim_os_preferences_cfstring_for_key (kim_preference_key  in_key,
-                                                      CFStringRef        *out_kim_string_key,
-                                                      CFStringRef        *out_kll_string_key)
+static CFStringRef kim_os_preferences_cfstring_for_key (kim_preference_key in_key)
 {
-    kim_error err = KIM_NO_ERROR;
-    
-    if (!err && !out_kim_string_key) { err = check_error (KIM_NULL_PARAMETER_ERR); }
-    if (!err && !out_kll_string_key) { err = check_error (KIM_NULL_PARAMETER_ERR); }
+    if (in_key == kim_preference_key_options) {
+        return CFSTR ("CredentialOptions");
+        
+    } else if (in_key == kim_preference_key_lifetime) {
+        return CFSTR ("CredentialLifetime");
+        
+    } else if (in_key == kim_preference_key_renewable) {
+        return CFSTR ("RenewableCredentials");
+        
+    } else if (in_key == kim_preference_key_renewal_lifetime) {
+        return CFSTR ("CredentialRenewalLifetime");
+        
+    } else if (in_key == kim_preference_key_forwardable) {
+        return CFSTR ("ForwardableCredentials");
+        
+    } else if (in_key == kim_preference_key_proxiable) {
+        return CFSTR ("ProxiableCredentials");
+        
+    } else if (in_key == kim_preference_key_addressless) {
+        return CFSTR ("AddresslessCredentials");
+        
+    } else if (in_key == kim_preference_key_remember_options) {
+        return CFSTR ("RememberCredentialAttributes");
+        
+    } else if (in_key == kim_preference_key_client_identity) {
+        return CFSTR ("ClientIdentity");
+        
+    } else if (in_key == kim_preference_key_remember_client_identity) {
+        return CFSTR ("RememberClientIdentity");
+        
+    } else if (in_key == kim_preference_key_favorites) {
+        return CFSTR ("FavoriteIdentities");
+        
+    } else if (in_key == kim_preference_key_minimum_lifetime) {
+        return CFSTR ("MinimumLifetime");
+        
+    } else if (in_key == kim_preference_key_maximum_lifetime) {
+        return CFSTR ("MaximumLifetime");
+        
+    } else if (in_key == kim_preference_key_minimum_renewal_lifetime) {
+        return CFSTR ("MinimumRenewalLifetime");
+        
+    } else if (in_key == kim_preference_key_maximum_renewal_lifetime) {
+        return CFSTR ("MaximumRenewalLifetime");
+        
+    }
     
-    if (!err) {
-        if (in_key == kim_preference_key_lifetime) {
-            *out_kim_string_key = CFSTR ("CredentialLifetime");
-            *out_kll_string_key = CFSTR ("KLDefaultTicketLifetime");
-            
-        } else if (in_key == kim_preference_key_renewable) {
-            *out_kim_string_key = CFSTR ("RenewableCredentials");
-            *out_kll_string_key = CFSTR ("KLGetRenewableTickets");
-            
-        } else if (in_key == kim_preference_key_renewal_lifetime) {
-            *out_kim_string_key = CFSTR ("CredentialRenewalLifetime");
-            *out_kll_string_key = CFSTR ("KLDefaultRenewableLifetime");
-            
-        } else if (in_key == kim_preference_key_forwardable) {
-            *out_kim_string_key = CFSTR ("ForwardableCredentials");
-            *out_kll_string_key = CFSTR ("KLDefaultForwardableTicket");
-            
-        } else if (in_key == kim_preference_key_proxiable) {
-            *out_kim_string_key = CFSTR ("ProxiableCredentials");
-            *out_kll_string_key = CFSTR ("KLGetProxiableTickets");
-            
-        } else if (in_key == kim_preference_key_addressless) {
-            *out_kim_string_key = CFSTR ("AddresslessCredentials");
-            *out_kll_string_key = CFSTR ("KLGetAddresslessTickets");
-            
-        } else if (in_key == kim_preference_key_remember_options) {
-            *out_kim_string_key = CFSTR ("RememberCredentialAttributes");
-            *out_kll_string_key = CFSTR ("KLRememberExtras");
-            
-        } else if (in_key == kim_preference_key_client_identity) {
-            *out_kim_string_key = CFSTR ("ClientIdentity");
-            *out_kll_string_key = CFSTR ("KLName");
-            
-        } else if (in_key == kim_preference_key_remember_client_identity) {
-            *out_kim_string_key = CFSTR ("RememberClientIdentity");
-            *out_kll_string_key = CFSTR ("KLRememberPrincipal");
-            
-        } else if (in_key == kim_preference_key_favorites) {
-            *out_kim_string_key = CFSTR ("FavoriteIdentities");
-            *out_kll_string_key = CFSTR ("KLFavoriteIdentities");
-            
-        } else if (in_key == kim_preference_key_minimum_lifetime) {
-            *out_kim_string_key = CFSTR ("MinimumLifetime");
-            *out_kll_string_key = CFSTR ("KLMinimumTicketLifetime");
-            
-        } else if (in_key == kim_preference_key_maximum_lifetime) {
-            *out_kim_string_key = CFSTR ("MaximumLifetime");
-            *out_kll_string_key = CFSTR ("KLMaximumTicketLifetime");
-            
-        } else if (in_key == kim_preference_key_minimum_renewal_lifetime) {
-            *out_kim_string_key = CFSTR ("MinimumRenewalLifetime");
-            *out_kll_string_key = CFSTR ("KLMinimumRenewableLifetime");
-            
-        } else if (in_key == kim_preference_key_maximum_renewal_lifetime) {
-            *out_kim_string_key = CFSTR ("MaximumRenewalLifetime");
-            *out_kll_string_key = CFSTR ("KLMaximumRenewableLifetime");
-            
-        } else {
-            /* ignore unsupported keys */
-            kim_debug_printf ("Unsupported preference key %d", in_key);
-            *out_kim_string_key = NULL;
-            *out_kll_string_key = NULL;
-        }
+    return NULL; /* ignore unsupported keys */
+}
+
+/* ------------------------------------------------------------------------ */
+
+static CFStringRef kim_os_preferences_compat_cfstring_for_key (kim_preference_key in_key)
+{
+    if (in_key == kim_preference_key_lifetime) {
+        return CFSTR ("KLDefaultTicketLifetime");
+        
+    } else if (in_key == kim_preference_key_renewable) {
+        return CFSTR ("KLGetRenewableTickets");
+        
+    } else if (in_key == kim_preference_key_renewal_lifetime) {
+        return CFSTR ("KLDefaultRenewableLifetime");
+        
+    } else if (in_key == kim_preference_key_forwardable) {
+        return CFSTR ("KLDefaultForwardableTicket");
+        
+    } else if (in_key == kim_preference_key_proxiable) {
+        return CFSTR ("KLGetProxiableTickets");
+        
+    } else if (in_key == kim_preference_key_addressless) {
+        return CFSTR ("KLGetAddresslessTickets");
+        
+    } else if (in_key == kim_preference_key_remember_options) {
+        return CFSTR ("KLRememberExtras");
+        
+    } else if (in_key == kim_preference_key_client_identity) {
+        return CFSTR ("KLName");
+        
+    } else if (in_key == kim_preference_key_remember_client_identity) {
+        return CFSTR ("KLRememberPrincipal");
+        
+    } else if (in_key == kim_preference_key_favorites) {
+        return CFSTR ("KLFavoriteIdentities");
+        
+    } else if (in_key == kim_preference_key_minimum_lifetime) {
+        return CFSTR ("KLMinimumTicketLifetime");
+        
+    } else if (in_key == kim_preference_key_maximum_lifetime) {
+        return CFSTR ("KLMaximumTicketLifetime");
+        
+    } else if (in_key == kim_preference_key_minimum_renewal_lifetime) {
+        return CFSTR ("KLMinimumRenewableLifetime");
+        
+    } else if (in_key == kim_preference_key_maximum_renewal_lifetime) {
+        return CFSTR ("KLMaximumRenewableLifetime");
+        
     }
     
-    return check_error (err);
+    return NULL; /* ignore unsupported keys */
 }
 
 /* ------------------------------------------------------------------------ */
 
-static kim_error kim_os_preferences_get_value (kim_preference_key  in_key, 
-                                               CFTypeID            in_type, 
-                                               CFPropertyListRef  *out_value)
+static kim_error kim_os_preferences_copy_value_for_file (CFStringRef         in_key, 
+                                                         CFTypeID            in_type, 
+                                                         CFStringRef         in_file,
+                                                         CFPropertyListRef  *out_value)
 {
     
     kim_error err = KIM_NO_ERROR;
     CFPropertyListRef value = NULL;
     CFStringRef users[] = { kCFPreferencesCurrentUser, kCFPreferencesAnyUser, NULL };
-    CFStringRef files[] = { KIM_PREFERENCES_FILE, KLL_PREFERENCES_FILE, NULL };
     CFStringRef hosts[] = { kCFPreferencesCurrentHost, kCFPreferencesAnyHost, NULL };
-    CFStringRef keys[] = { NULL, NULL, NULL };
     
+    if (!err && !in_key   ) { err = check_error (KIM_NULL_PARAMETER_ERR); }
+    if (!err && !in_file  ) { err = check_error (KIM_NULL_PARAMETER_ERR); }
     if (!err && !out_value) { err = check_error (KIM_NULL_PARAMETER_ERR); }
     
     if (!err) {
-        /* Index must correspond to the appropriate file */
-        err = kim_os_preferences_cfstring_for_key (in_key, &keys[0], &keys[1]);
-    }
-    
-    if (!err) {
-        kim_count u, f, h;
+        kim_count u, h;
         
         if (!kim_library_allow_home_directory_access()) {
             users[0] = kCFPreferencesAnyUser;
@@ -142,10 +166,8 @@ static kim_error kim_os_preferences_get_value (kim_preference_key  in_key,
         }
         
         for (u = 0; !value && users[u]; u++) {
-            for (f = 0; !value && files[f] && keys[f]; f++) {
-                for (h = 0; !value && hosts[h]; h++) {
-                    value = CFPreferencesCopyValue (keys[f], files[f], users[u], hosts[h]);
-                }
+            for (h = 0; !value && hosts[h]; h++) {
+                value = CFPreferencesCopyValue (in_key, in_file, users[u], hosts[h]);
             }
         }        
         
@@ -165,27 +187,60 @@ static kim_error kim_os_preferences_get_value (kim_preference_key  in_key,
     return check_error (err);
 }
 
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+static kim_error kim_os_preferences_copy_value (kim_preference_key  in_key, 
+                                                CFTypeID            in_type, 
+                                                CFPropertyListRef  *out_value)
+{
+    kim_error err = KIM_NO_ERROR;
+    CFStringRef key = kim_os_preferences_cfstring_for_key (in_key);
+    
+    err = kim_os_preferences_copy_value_for_file (key, in_type,
+                                                  KIM_PREFERENCES_FILE,
+                                                  out_value);
+    
+    return check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static kim_error kim_os_preferences_copy_value_compat (kim_preference_key  in_key, 
+                                                       CFTypeID            in_type, 
+                                                       CFPropertyListRef  *out_value)
+{
+    kim_error err = KIM_NO_ERROR;
+    CFStringRef key = kim_os_preferences_compat_cfstring_for_key (in_key);
+    
+    err = kim_os_preferences_copy_value_for_file (key, in_type,
+                                                  KLL_PREFERENCES_FILE,
+                                                  out_value);
+    
+    return check_error (err);
+}
+
 /* ------------------------------------------------------------------------ */
 
 static kim_error kim_os_preferences_set_value (kim_preference_key in_key, 
-                                               CFPropertyListRef    in_value)
+                                               CFPropertyListRef  in_value)
 {
     kim_error err = KIM_NO_ERROR;
-    CFStringRef kim_key = NULL;
-    CFStringRef kll_key = NULL;
+    CFStringRef key = NULL;
     
     if (!err && !in_value) { err = check_error (KIM_NULL_PARAMETER_ERR); }
     
     if (!err) {
-        err = kim_os_preferences_cfstring_for_key (in_key, &kim_key, &kll_key);
+        key = kim_os_preferences_cfstring_for_key (in_key);
     }
     
-    if (!err && kim_key) {
+    if (!err && key) {
         kim_boolean homedir_ok = kim_library_allow_home_directory_access();
         CFStringRef user = homedir_ok ? kCFPreferencesCurrentUser : kCFPreferencesAnyUser;
         CFStringRef host = homedir_ok ? kCFPreferencesAnyHost : kCFPreferencesCurrentHost;
         
-        CFPreferencesSetValue (kim_key, in_value, KIM_PREFERENCES_FILE, user, host);
+        CFPreferencesSetValue (key, in_value, KIM_PREFERENCES_FILE, user, host);
         if (!CFPreferencesSynchronize (KIM_PREFERENCES_FILE, user, host)) {
             err = check_error (KIM_PREFERENCES_WRITE_ERR);
         }
@@ -209,8 +264,14 @@ kim_error kim_os_preferences_get_identity_for_key (kim_preference_key  in_key,
     if (!err && !out_identity) { err = check_error (KIM_NULL_PARAMETER_ERR); }
     
     if (!err) {
-        err = kim_os_preferences_get_value (in_key, CFStringGetTypeID (), 
-                                            (CFPropertyListRef *) &value);
+        err = kim_os_preferences_copy_value (in_key, CFStringGetTypeID (), 
+                                             (CFPropertyListRef *) &value);
+        
+    }
+    
+    if (!err && !value) {
+        err = kim_os_preferences_copy_value_compat (in_key, CFStringGetTypeID (), 
+                                                    (CFPropertyListRef *) &value);
     }
     
     if (!err) {
@@ -272,117 +333,57 @@ kim_error kim_os_preferences_set_identity_for_key (kim_preference_key in_key,
 
 /* ------------------------------------------------------------------------ */
 
-kim_error kim_os_preferences_get_favorites_for_key (kim_preference_key in_key, 
-                                                    kim_favorites      io_favorites)
+kim_error kim_os_preferences_get_lifetime_for_key (kim_preference_key  in_key, 
+                                                   kim_lifetime        in_hardcoded_default,
+                                                   kim_lifetime       *out_lifetime)
 {
     kim_error err = KIM_NO_ERROR;
-    CFArrayRef value = NULL;
+    CFNumberRef value = NULL;
     
-    if (!err && !io_favorites) { err = check_error (KIM_NULL_PARAMETER_ERR); }
+    if (!err && !out_lifetime) { err = check_error (KIM_NULL_PARAMETER_ERR); }
     
     if (!err) {
-        err = kim_os_preferences_get_value (in_key, CFArrayGetTypeID (), 
-                                            (CFPropertyListRef *) &value);
+        err = kim_os_preferences_copy_value (in_key, CFNumberGetTypeID (), 
+                                             (CFPropertyListRef *) &value);
+    }
+    
+    if (!err && !value) {
+        err = kim_os_preferences_copy_value_compat (in_key, CFNumberGetTypeID (), 
+                                                    (CFPropertyListRef *) &value);
     }
     
     if (!err) {
-        if (!value || CFArrayGetCount (value) < 1) {
-            err =  kim_favorites_remove_all_identities (io_favorites);
-            
-        } else {
-            CFIndex count = CFArrayGetCount (value);
-            CFIndex i;
-            
-            for (i = 0; !err && i < count; i++) {
-                CFStringRef cfstring = NULL;
-                kim_string string = NULL;
-                kim_identity identity = NULL;
-                
-                cfstring = (CFStringRef) CFArrayGetValueAtIndex (value, i);
-                if (!cfstring || CFGetTypeID (cfstring) != CFStringGetTypeID ()) {
-                    err = check_error (KIM_PREFERENCES_READ_ERR);
-                }
-                
-                if (!err) {
-                    err = kim_os_string_create_from_cfstring (&string, cfstring);
-                }
-                
-                if (!err) {
-                    err = kim_identity_create_from_string (&identity, string);
-                }
-                
-                if (!err) {
-                    err = kim_favorites_add_identity (io_favorites, identity,
-                                                      KIM_OPTIONS_DEFAULT);
-                }
-                
-                kim_identity_free (&identity);
-                kim_string_free (&string);
+        if (value) {
+            SInt32 number; // CFNumbers are signed so we need to cast
+            if (CFNumberGetValue (value, kCFNumberSInt32Type, &number) != TRUE) {
+                err = KIM_OUT_OF_MEMORY_ERR;
+            } else {
+                *out_lifetime = number;
             }
+        } else {
+            *out_lifetime = in_hardcoded_default;
         }
     }
     
-    if (err) {
-        kim_favorites_remove_all_identities (io_favorites);
-    }
-    
     if (value) { CFRelease (value); }
     
     return check_error (err);
 }
 
 /* ------------------------------------------------------------------------ */
-kim_error kim_os_preferences_set_favorites_for_key (kim_preference_key in_key, 
-                                                    kim_favorites      in_favorites)
+
+kim_error kim_os_preferences_set_lifetime_for_key (kim_preference_key in_key, 
+                                                   kim_lifetime       in_lifetime)
 {
     kim_error err = KIM_NO_ERROR;
-    kim_count count = 0;
-    CFMutableArrayRef value = NULL;
-    
-    if (!err && !in_favorites) { err = check_error (KIM_NULL_PARAMETER_ERR); }
-    
-    if (!err) {
-        err = kim_favorites_get_number_of_identities (in_favorites, &count);
-    }
+    CFNumberRef value = NULL;
+    SInt32 number = (SInt32) in_lifetime;
     
     if (!err) {
-        value = CFArrayCreateMutable (kCFAllocatorDefault, count, 
-                                      &kCFTypeArrayCallBacks);
+        value = CFNumberCreate (kCFAllocatorDefault, kCFNumberSInt32Type, &number);
         if (!value) { err = KIM_OUT_OF_MEMORY_ERR; }
     }
     
-    if (!err) {
-        kim_count i;
-        
-        for (i = 0; !err && i < count; i++) {
-            kim_identity identity = NULL;
-            kim_options options = NULL;
-            kim_string string = NULL;
-            CFStringRef cfstring = NULL;
-            
-            err = kim_favorites_get_identity_at_index (in_favorites, i, 
-                                                       &identity,
-                                                       &options);
-            
-            if (!err) {
-                err = kim_identity_get_string (identity, &string);
-            }
-            
-            if (!err) {
-                err = kim_os_string_get_cfstring (string, &cfstring);
-            }
-            
-            if (!err) {
-                CFArrayAppendValue (value, cfstring);
-            }
-            
-            if (cfstring) { CFRelease (cfstring); }
-            kim_string_free (&string);
-            kim_options_free (&options);
-            kim_identity_free (&identity);
-        }
-    }
-    
     if (!err) {
         err = kim_os_preferences_set_value (in_key, value);
     }
@@ -394,30 +395,30 @@ kim_error kim_os_preferences_set_favorites_for_key (kim_preference_key in_key,
 
 /* ------------------------------------------------------------------------ */
 
-kim_error kim_os_preferences_get_time_for_key (kim_preference_key  in_key,  
-                                               kim_time            in_hardcoded_default,
-                                               kim_time           *out_time)
+kim_error kim_os_preferences_get_boolean_for_key (kim_preference_key  in_key, 
+                                                  kim_boolean         in_hardcoded_default,
+                                                  kim_boolean        *out_boolean)
 {
     kim_error err = KIM_NO_ERROR;
-    CFNumberRef value = NULL;
+    CFBooleanRef value = NULL;
     
-    if (!err && !out_time) { err = check_error (KIM_NULL_PARAMETER_ERR); }
+    if (!err && !out_boolean) { err = check_error (KIM_NULL_PARAMETER_ERR); }
     
     if (!err) {
-        err = kim_os_preferences_get_value (in_key, CFNumberGetTypeID (), 
-                                            (CFPropertyListRef *) &value);
+        err = kim_os_preferences_copy_value (in_key, CFBooleanGetTypeID (), 
+                                             (CFPropertyListRef *) &value);
+    }
+    
+    if (!err && !value) {
+        err = kim_os_preferences_copy_value_compat (in_key, CFBooleanGetTypeID (), 
+                                                    (CFPropertyListRef *) &value);
     }
     
     if (!err) {
         if (value) {
-            SInt32 number; // CFNumbers are signed so we need to cast
-            if (CFNumberGetValue (value, kCFNumberSInt32Type, &number) != TRUE) {
-                err = KIM_OUT_OF_MEMORY_ERR;
-            } else {
-                *out_time = number;
-            }
+            *out_boolean = CFBooleanGetValue (value);
         } else {
-            *out_time = in_hardcoded_default;
+            *out_boolean = in_hardcoded_default;
         }
     }
     
@@ -428,126 +429,647 @@ kim_error kim_os_preferences_get_time_for_key (kim_preference_key  in_key,
 
 /* ------------------------------------------------------------------------ */
 
-kim_error kim_os_preferences_set_time_for_key (kim_preference_key in_key, 
-                                               kim_time           in_time)
+kim_error kim_os_preferences_set_boolean_for_key (kim_preference_key in_key, 
+                                                  kim_boolean        in_boolean)
 {
     kim_error err = KIM_NO_ERROR;
-    CFNumberRef value = NULL;
-    SInt32 number = (SInt32) in_time;
-    
-    if (!err) {
-        value = CFNumberCreate (kCFAllocatorDefault, kCFNumberSInt32Type, &number);
-        if (!value) { err = KIM_OUT_OF_MEMORY_ERR; }
-    }
+    CFBooleanRef value = in_boolean ? kCFBooleanTrue : kCFBooleanFalse;
     
     if (!err) {
         err = kim_os_preferences_set_value (in_key, value);
     }
     
-    if (value) { CFRelease (value); }
-    
     return check_error (err);
 }
 
+#pragma mark -
+
 /* ------------------------------------------------------------------------ */
 
-kim_error kim_os_preferences_get_lifetime_for_key (kim_preference_key  in_key, 
-                                                   kim_lifetime        in_hardcoded_default,
-                                                   kim_lifetime       *out_lifetime)
+static kim_error kim_os_preferences_copy_value_for_dict_key (CFDictionaryRef     in_dictionary,
+                                                             kim_preference_key  in_key, 
+                                                             CFTypeID            in_type, 
+                                                             CFPropertyListRef  *out_value)
 {
     kim_error err = KIM_NO_ERROR;
-    CFNumberRef value = NULL;
+    CFPropertyListRef value = NULL;
     
-    if (!err && !out_lifetime) { err = check_error (KIM_NULL_PARAMETER_ERR); }
+    if (!err && !in_dictionary) { err = check_error (KIM_NULL_PARAMETER_ERR); }
+    if (!err && !out_value    ) { err = check_error (KIM_NULL_PARAMETER_ERR); }
     
     if (!err) {
-        err = kim_os_preferences_get_value (in_key, CFNumberGetTypeID (), 
-                                            (CFPropertyListRef *) &value);
+        CFStringRef key = kim_os_preferences_cfstring_for_key (in_key);
+        
+        value = CFDictionaryGetValue (in_dictionary, key);
+        if (value && CFGetTypeID (value) != in_type) {
+            err = check_error (KIM_PREFERENCES_READ_ERR);
+        }
     }
     
     if (!err) {
-        if (value) {
-            SInt32 number; // CFNumbers are signed so we need to cast
-            if (CFNumberGetValue (value, kCFNumberSInt32Type, &number) != TRUE) {
-                err = KIM_OUT_OF_MEMORY_ERR;
-            } else {
-                *out_lifetime = number;
-            }
-        } else {
-            *out_lifetime = in_hardcoded_default;
-        }
+        *out_value = value;
     }
     
-    if (value) { CFRelease (value); }
-    
     return check_error (err);
 }
 
 /* ------------------------------------------------------------------------ */
 
-kim_error kim_os_preferences_set_lifetime_for_key (kim_preference_key in_key, 
-                                                   kim_lifetime       in_lifetime)
+static kim_error kim_os_preferences_set_value_for_dict_key (CFMutableDictionaryRef in_dictionary,
+                                                            kim_preference_key     in_key, 
+                                                            CFPropertyListRef      in_value)
 {
     kim_error err = KIM_NO_ERROR;
-    CFNumberRef value = NULL;
-    SInt32 number = (SInt32) in_lifetime;
     
-    if (!err) {
-        value = CFNumberCreate (kCFAllocatorDefault, kCFNumberSInt32Type, &number);
-        if (!value) { err = KIM_OUT_OF_MEMORY_ERR; }
-    }
+    if (!err && !in_dictionary) { err = check_error (KIM_NULL_PARAMETER_ERR); }
+    if (!err && !in_value     ) { err = check_error (KIM_NULL_PARAMETER_ERR); }
     
     if (!err) {
-        err = kim_os_preferences_set_value (in_key, value);
+        CFStringRef key = kim_os_preferences_cfstring_for_key (in_key);
+        
+        CFDictionarySetValue (in_dictionary, key, in_value);
     }
     
-    if (value) { CFRelease (value); }
-    
     return check_error (err);
 }
 
 /* ------------------------------------------------------------------------ */
 
-kim_error kim_os_preferences_get_boolean_for_key (kim_preference_key  in_key, 
-                                                  kim_boolean         in_hardcoded_default,
-                                                  kim_boolean        *out_boolean)
+static kim_error kim_os_preferences_dictionary_to_options (CFDictionaryRef  in_dictionary, 
+                                                           kim_options     *out_options)
 {
     kim_error err = KIM_NO_ERROR;
-    CFBooleanRef value = NULL;
+    kim_options options = KIM_OPTIONS_DEFAULT;
+    kim_boolean found_options = 0;
     
-    if (!err && !out_boolean) { err = check_error (KIM_NULL_PARAMETER_ERR); }
+    if (!err && !in_dictionary) { err = check_error (KIM_NULL_PARAMETER_ERR); }
+    if (!err && !out_options  ) { err = check_error (KIM_NULL_PARAMETER_ERR); }
     
     if (!err) {
-        err = kim_os_preferences_get_value (in_key, CFBooleanGetTypeID (), 
-                                            (CFPropertyListRef *) &value);
+        err = kim_options_create_empty (&options);
     }
     
     if (!err) {
-        if (value) {
-            *out_boolean = CFBooleanGetValue (value);
-        } else {
-            *out_boolean = in_hardcoded_default;
+        CFBooleanRef value = NULL;
+        
+        err = kim_os_preferences_copy_value_for_dict_key (in_dictionary,
+                                                          kim_preference_key_renewable, 
+                                                          CFBooleanGetTypeID (), 
+                                                          (CFPropertyListRef *) &value);
+        
+        if (!err && value) {
+            found_options = 1;
+            err = kim_options_set_renewable (options, CFBooleanGetValue (value));
         }
     }
     
-    if (value) { CFRelease (value); }
+    if (!err) {
+        CFNumberRef value = NULL;
+        SInt32 lifetime; // CFNumbers are signed so we need to cast
+        
+        err = kim_os_preferences_copy_value_for_dict_key (in_dictionary,
+                                                          kim_preference_key_lifetime, 
+                                                          CFNumberGetTypeID (), 
+                                                          (CFPropertyListRef *) &value);
+        
+        if (!err && value && CFNumberGetValue (value, kCFNumberSInt32Type, 
+                                               &lifetime)) {
+            found_options = 1;
+            err = kim_options_set_lifetime (options, lifetime);
+        }
+    }
     
-    return check_error (err);
-}
+    if (!err) {
+        CFNumberRef value = NULL;
+        SInt32 lifetime; // CFNumbers are signed so we need to cast
+        
+        err = kim_os_preferences_copy_value_for_dict_key (in_dictionary,
+                                                          kim_preference_key_renewal_lifetime, 
+                                                          CFNumberGetTypeID (), 
+                                                          (CFPropertyListRef *) &value);
+        
+        if (!err && value && CFNumberGetValue (value, kCFNumberSInt32Type, 
+                                               &lifetime)) {
+            found_options = 1;
+            err = kim_options_set_renewal_lifetime (options, lifetime);
+        }    }
+    
+    if (!err) {
+        CFBooleanRef value = NULL;
+        
+        err = kim_os_preferences_copy_value_for_dict_key (in_dictionary,
+                                                          kim_preference_key_forwardable, 
+                                                          CFBooleanGetTypeID (), 
+                                                          (CFPropertyListRef *) &value);
+        
+        if (!err && value) {
+            found_options = 1;
+            err = kim_options_set_forwardable (options, CFBooleanGetValue (value));
+        }
+    }
+    
+    if (!err) {
+        CFBooleanRef value = NULL;
+        
+        err = kim_os_preferences_copy_value_for_dict_key (in_dictionary,
+                                                          kim_preference_key_proxiable, 
+                                                          CFBooleanGetTypeID (), 
+                                                          (CFPropertyListRef *) &value);
+        
+        if (!err && value) {
+            found_options = 1;
+            err = kim_options_set_proxiable (options, CFBooleanGetValue (value));
+        }
+    }
+    
+    if (!err) {
+        CFBooleanRef value = NULL;
+        
+        err = kim_os_preferences_copy_value_for_dict_key (in_dictionary,
+                                                          kim_preference_key_addressless, 
+                                                          CFBooleanGetTypeID (), 
+                                                          (CFPropertyListRef *) &value);
+        
+        if (!err && value) {
+            found_options = 1;
+            err = kim_options_set_addressless (options, CFBooleanGetValue (value));
+        }
+    }
+    
+    if (!err && !found_options) {
+        kim_options_free (&options);
+        options = KIM_OPTIONS_DEFAULT;
+    }
+    
+    if (!err) {
+        *out_options = options;
+        options = NULL;
+    }
+    
+    kim_options_free (&options);
+    
+    return check_error (err);
+}
 
 /* ------------------------------------------------------------------------ */
 
-kim_error kim_os_preferences_set_boolean_for_key (kim_preference_key in_key, 
-                                                  kim_boolean        in_boolean)
+static kim_error kim_os_preferences_options_to_dictionary (kim_options            in_options,
+                                                           CFMutableDictionaryRef io_dictionary)
 {
     kim_error err = KIM_NO_ERROR;
-    CFBooleanRef value = in_boolean ? kCFBooleanTrue : kCFBooleanFalse;
+    
+    if (!err && !in_options   ) { err = check_error (KIM_NULL_PARAMETER_ERR); }
+    if (!err && !io_dictionary) { err = check_error (KIM_NULL_PARAMETER_ERR); }
     
     if (!err) {
-        err = kim_os_preferences_set_value (in_key, value);
+        CFNumberRef value = NULL;
+        kim_lifetime lifetime;
+        
+        err = kim_options_get_lifetime (in_options, &lifetime);
+        
+        if (!err) {
+            SInt32 number = (SInt32) lifetime;
+            
+            value = CFNumberCreate (kCFAllocatorDefault, 
+                                    kCFNumberSInt32Type, &number);
+            if (!value) { err = KIM_OUT_OF_MEMORY_ERR; }
+        }
+        
+        if (!err) {
+            err = kim_os_preferences_set_value_for_dict_key (io_dictionary, 
+                                                             kim_preference_key_lifetime, 
+                                                             value);
+        }
+        
+        if (value) { CFRelease (value); }        
+    }
+    
+    if (!err) {
+        kim_boolean boolean;
+        
+        err = kim_options_get_renewable (in_options, &boolean);
+        
+        if (!err) {
+            CFBooleanRef value = boolean ? kCFBooleanTrue : kCFBooleanFalse;
+            
+            err = kim_os_preferences_set_value_for_dict_key (io_dictionary, 
+                                                             kim_preference_key_renewable, 
+                                                             value);
+        }
+    }    
+    
+    if (!err) {
+        CFNumberRef value = NULL;
+        kim_lifetime lifetime;
+        
+        err = kim_options_get_renewal_lifetime (in_options, &lifetime);
+        
+        if (!err) {
+            SInt32 number = (SInt32) lifetime;
+            
+            value = CFNumberCreate (kCFAllocatorDefault, 
+                                    kCFNumberSInt32Type, &number);
+            if (!value) { err = KIM_OUT_OF_MEMORY_ERR; }
+        }
+        
+        if (!err) {
+            err = kim_os_preferences_set_value_for_dict_key (io_dictionary, 
+                                                             kim_preference_key_renewal_lifetime, 
+                                                             value);
+        }
+        
+        if (value) { CFRelease (value); }        
+    }
+    
+    if (!err) {
+        kim_boolean boolean;
+        
+        err = kim_options_get_forwardable (in_options, &boolean);
+        
+        if (!err) {
+            CFBooleanRef value = boolean ? kCFBooleanTrue : kCFBooleanFalse;
+            
+            err = kim_os_preferences_set_value_for_dict_key (io_dictionary, 
+                                                             kim_preference_key_forwardable, 
+                                                             value);
+        }
+    }    
+    
+    if (!err) {
+        kim_boolean boolean;
+        
+        err = kim_options_get_proxiable (in_options, &boolean);
+        
+        if (!err) {
+            CFBooleanRef value = boolean ? kCFBooleanTrue : kCFBooleanFalse;
+            
+            err = kim_os_preferences_set_value_for_dict_key (io_dictionary, 
+                                                             kim_preference_key_proxiable, 
+                                                             value);
+        }
+    }
+    
+    if (!err) {
+        kim_boolean boolean;
+        
+        err = kim_options_get_addressless (in_options, &boolean);
+        
+        if (!err) {
+            CFBooleanRef value = boolean ? kCFBooleanTrue : kCFBooleanFalse;
+            
+            err = kim_os_preferences_set_value_for_dict_key (io_dictionary, 
+                                                             kim_preference_key_addressless, 
+                                                             value);
+        }
+    }    
+    
+    return check_error (err);
+}
+
+
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+static kim_error kim_os_preferences_get_options_compat (kim_options *out_options)
+{
+    kim_error err = KIM_NO_ERROR;
+    kim_options options = KIM_OPTIONS_DEFAULT;
+    kim_boolean found_options = 0;
+    
+    if (!err && !out_options) { err = check_error (KIM_NULL_PARAMETER_ERR); }
+    
+    if (!err) {
+        err = kim_options_create_empty (&options);
+    }
+    
+    if (!err) { 
+        CFNumberRef value = NULL;
+        SInt32 lifetime; // CFNumbers are signed so we need to cast
+        
+        err = kim_os_preferences_copy_value_compat (kim_preference_key_lifetime, 
+                                                    CFNumberGetTypeID (), 
+                                                    (CFPropertyListRef *) &value);
+        
+        if (!err && value && CFNumberGetValue (value, kCFNumberSInt32Type, 
+                                               &lifetime)) {
+            found_options = 1;
+            err = kim_options_set_lifetime (options, lifetime);
+        }
+        
+        if (value) { CFRelease (value); }
+    }
+    
+    if (!err) {
+        CFBooleanRef value = NULL;
+        
+        err = kim_os_preferences_copy_value_compat (kim_preference_key_renewable, 
+                                                    CFBooleanGetTypeID (), 
+                                                    (CFPropertyListRef *) &value);
+        
+        if (!err && value) {
+            found_options = 1;
+            err = kim_options_set_renewable (options, CFBooleanGetValue (value));
+        }
+        
+        if (value) { CFRelease (value); }
+    }
+    
+    if (!err) {
+        CFNumberRef value = NULL;
+        SInt32 lifetime; // CFNumbers are signed so we need to cast
+        
+        err = kim_os_preferences_copy_value_compat (kim_preference_key_renewal_lifetime, 
+                                                    CFNumberGetTypeID (), 
+                                                    (CFPropertyListRef *) &value);
+        
+        if (!err && value && CFNumberGetValue (value, kCFNumberSInt32Type, 
+                                               &lifetime)) {
+            found_options = 1;
+            err = kim_options_set_renewal_lifetime (options, lifetime);
+        }
+        
+        if (value) { CFRelease (value); }
+    }
+    
+    if (!err) {
+        CFBooleanRef value = NULL;
+        
+        err = kim_os_preferences_copy_value_compat (kim_preference_key_forwardable, 
+                                                    CFBooleanGetTypeID (), 
+                                                    (CFPropertyListRef *) &value);
+        
+        if (!err && value) {
+            found_options = 1;
+            err = kim_options_set_forwardable (options, CFBooleanGetValue (value));
+        }
+        
+        if (value) { CFRelease (value); }
+    }
+    
+    if (!err) {
+        CFBooleanRef value = NULL;
+        
+        err = kim_os_preferences_copy_value_compat (kim_preference_key_proxiable, 
+                                                    CFBooleanGetTypeID (), 
+                                                    (CFPropertyListRef *) &value);
+        
+        if (!err && value) {
+            found_options = 1;
+            err = kim_options_set_proxiable (options, CFBooleanGetValue (value));
+        }
+        
+        if (value) { CFRelease (value); }
+    }
+    
+    if (!err) {
+        CFBooleanRef value = NULL;
+        
+        err = kim_os_preferences_copy_value_compat (kim_preference_key_addressless, 
+                                                    CFBooleanGetTypeID (), 
+                                                    (CFPropertyListRef *) &value);
+        
+        if (!err && value) {
+            found_options = 1;
+            err = kim_options_set_addressless (options, CFBooleanGetValue (value));
+        }
+        
+        if (value) { CFRelease (value); }
+    }
+    
+    if (!err && !found_options) {
+        kim_options_free (&options);
+        options = KIM_OPTIONS_DEFAULT;
+    }
+    
+    if (!err) {
+        *out_options = options;
+    }
+    
+    return check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+kim_error kim_os_preferences_get_options_for_key (kim_preference_key  in_key, 
+                                                  kim_options        *out_options)
+{
+    kim_error err = KIM_NO_ERROR;
+    CFDictionaryRef dictionary = NULL;
+    kim_options options = KIM_OPTIONS_DEFAULT;
+    
+    if (!err && !out_options) { err = check_error (KIM_NULL_PARAMETER_ERR); }
+    
+    if (!err) {
+        err = kim_os_preferences_copy_value (in_key, CFDictionaryGetTypeID (), 
+                                             (CFPropertyListRef *) &dictionary);
+        
+        if (!err && dictionary) {
+            err = kim_os_preferences_dictionary_to_options (dictionary, &options);
+        }
+    }
+    
+    if (!err && !dictionary) {
+        err = kim_os_preferences_get_options_compat (&options);
+    }
+    
+    if (!err) {
+        *out_options = options;
+    }
+    
+    if (dictionary) { CFRelease (dictionary); }
+    
+    return check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+kim_error kim_os_preferences_set_options_for_key (kim_preference_key in_key, 
+                                                  kim_options        in_options)
+{
+    kim_error err = KIM_NO_ERROR;
+    CFMutableDictionaryRef dictionary = NULL;
+    
+    if (!err && !in_options) { err = check_error (KIM_NULL_PARAMETER_ERR); }
+    
+    if (!err) {
+        dictionary = CFDictionaryCreateMutable (kCFAllocatorDefault, 0, 
+                                                &kCFTypeDictionaryKeyCallBacks,
+                                                &kCFTypeDictionaryValueCallBacks);
+        if (!dictionary) { err = check_error (KIM_OUT_OF_MEMORY_ERR); }
+    }
+    
+    if (!err) {
+        err = kim_os_preferences_options_to_dictionary (in_options, dictionary);
+    }
+    
+    if (!err) {
+        err = kim_os_preferences_set_value (in_key, dictionary);
+    }
+    
+    if (dictionary) { CFRelease (dictionary); }
+    
+    return check_error (err);
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+kim_error kim_os_preferences_get_favorites_for_key (kim_preference_key in_key, 
+                                                    kim_favorites      io_favorites)
+{
+    kim_error err = KIM_NO_ERROR;
+    CFArrayRef value = NULL;
+    
+    if (!err && !io_favorites) { err = check_error (KIM_NULL_PARAMETER_ERR); }
+    
+    if (!err) {
+        err = kim_os_preferences_copy_value (in_key, CFArrayGetTypeID (), 
+                                             (CFPropertyListRef *) &value);
+    }
+    
+    if (!err && value) {
+        if (!value || CFArrayGetCount (value) < 1) {
+            err =  kim_favorites_remove_all_identities (io_favorites);
+            
+        } else {
+            CFIndex count = CFArrayGetCount (value);
+            CFIndex i;
+            
+            for (i = 0; !err && i < count; i++) {
+                CFDictionaryRef dictionary = NULL;
+                kim_options options = KIM_OPTIONS_DEFAULT;
+                CFStringRef cfstring = NULL;
+                
+                dictionary = (CFDictionaryRef) CFArrayGetValueAtIndex (value, i);
+                if (!dictionary || CFGetTypeID (dictionary) != CFDictionaryGetTypeID ()) {
+                    err = check_error (KIM_PREFERENCES_READ_ERR);
+                }
+                
+                if (!err) {
+                    err = kim_os_preferences_copy_value_for_dict_key (dictionary,
+                                                                      kim_preference_key_client_identity,
+                                                                      CFStringGetTypeID (),
+                                                                      (CFPropertyListRef *) &cfstring);                    
+                }
+                
+                if (!err && cfstring) {
+                    kim_string string = NULL;
+                    kim_identity identity = NULL;
+                    
+                    err = kim_os_string_create_from_cfstring (&string, cfstring);
+                    
+                    if (!err) {
+                        err = kim_identity_create_from_string (&identity, string);
+                    }
+                    
+                    if (!err && (CFDictionaryGetCount (dictionary) > 1)) {
+                        err = kim_os_preferences_dictionary_to_options (dictionary, 
+                                                                        &options);
+                    }
+                    
+                    if (!err) {
+                        err = kim_favorites_add_identity (io_favorites, identity,
+                                                          options);
+                    }
+                    
+                    kim_string_free (&string);
+                    kim_options_free (&options);
+                    kim_identity_free (&identity);
+                }
+            }
+            
+            if (err) {
+                kim_favorites_remove_all_identities (io_favorites);
+            }
+        }
     }
     
+    if (value) { CFRelease (value); }
+    
     return check_error (err);
 }
 
 /* ------------------------------------------------------------------------ */
+kim_error kim_os_preferences_set_favorites_for_key (kim_preference_key in_key, 
+                                                    kim_favorites      in_favorites)
+{
+    kim_error err = KIM_NO_ERROR;
+    kim_count count = 0;
+    CFMutableArrayRef array = NULL;
+    
+    if (!err && !in_favorites) { err = check_error (KIM_NULL_PARAMETER_ERR); }
+    
+    if (!err) {
+        err = kim_favorites_get_number_of_identities (in_favorites, &count);
+    }
+    
+    if (!err) {
+        array = CFArrayCreateMutable (kCFAllocatorDefault, count, 
+                                      &kCFTypeArrayCallBacks);
+        if (!array) { err = KIM_OUT_OF_MEMORY_ERR; }
+    }
+    
+    if (!err) {
+        kim_count i;
+        
+        for (i = 0; !err && i < count; i++) {
+            kim_identity identity = NULL;
+            kim_options options = NULL;
+            kim_string string = NULL;
+            CFStringRef cfstring = NULL;
+            CFMutableDictionaryRef dictionary = NULL;
+            
+            err = kim_favorites_get_identity_at_index (in_favorites, i, 
+                                                       &identity,
+                                                       &options);
+            
+            if (!err) {
+                err = kim_identity_get_string (identity, &string);
+            }
+            
+            if (!err) {
+                err = kim_os_string_get_cfstring (string, &cfstring);
+            }
+            
+            if (!err) {
+                dictionary = CFDictionaryCreateMutable (kCFAllocatorDefault, 0, 
+                                                        &kCFTypeDictionaryKeyCallBacks,
+                                                        &kCFTypeDictionaryValueCallBacks);
+                if (!dictionary) { err = check_error (KIM_OUT_OF_MEMORY_ERR); }
+            }
+            
+            if (!err) {
+                err = kim_os_preferences_set_value_for_dict_key (dictionary,
+                                                                 kim_preference_key_client_identity,
+                                                                 cfstring);                    
+            }
+            
+            if (!err && options) {
+                err = kim_os_preferences_options_to_dictionary (options, 
+                                                                dictionary);
+            }
+            
+            if (!err) {
+                CFArrayAppendValue (array, dictionary);
+            }
+            
+            if (dictionary) { CFRelease (dictionary); }
+            if (cfstring  ) { CFRelease (cfstring); }
+            kim_string_free (&string);
+            kim_options_free (&options);
+            kim_identity_free (&identity);
+        }
+    }
+    
+    if (!err) {
+        err = kim_os_preferences_set_value (in_key, array);
+    }
+    
+    if (array) { CFRelease (array); }
+    
+    return check_error (err);
+}
+
index 03194bf1ce037fae3c14ef9a9bd67767e137c73e..55846e7ae0e165a9a670504459905ae48dbba008 100644 (file)
@@ -68,5 +68,7 @@ int main (int argc, const char * argv[])
     
     test_kim_selection_hints_remember_identity (state);
     
+    test_kim_preferences_add_favorite_identity (state);
+    
     return test_cleanup (state);
 }
index 8ce61fe081044293714c351186f1444aff125ecb..5811912128834051d28bcffecd0a322470e30fb5 100644 (file)
@@ -102,7 +102,7 @@ void test_kim_preferences_set_options (kim_test_state_t state)
         
         if (!err) {
             err = kim_options_set_lifetime (options, TEST_LIFETIME);
-            fail_if_error (state, "kim_options_set_data", err, 
+            fail_if_error (state, "kim_options_set_lifetime", err, 
                            "while setting the lifetime to %d", TEST_LIFETIME);            
         }
         
@@ -385,3 +385,188 @@ void test_kim_preferences_set_client_identity (kim_test_state_t state)
 
     end_test (state);
 }
+
+
+struct favorite_identity {
+    kim_string identity;
+    kim_lifetime lifetime;
+    kim_lifetime renewal_lifetime;
+};
+
+struct favorite_identity fids[] = {
+{ "bob@EXAMPLE.COM", 7777, 8888 },
+{ "alice@UNIVERSITY.EDU", 12345, 54321 },
+{ "bob@COMPANY.COM", 5555, 6666 },
+{ "alice/admin@EXAMPLE.COM", 2222, 3333 },
+{ NULL, 0, 0 }
+};
+
+/* ------------------------------------------------------------------------ */
+
+void test_kim_preferences_add_favorite_identity (kim_test_state_t state)
+{
+    kim_error err = KIM_NO_ERROR;
+    
+    start_test (state, "kim_preferences_add_favorite_identity");
+    
+    if (!err) {
+        kim_preferences prefs = NULL;
+        kim_options options = NULL;
+        kim_count i;
+        
+        err = kim_preferences_create (&prefs);
+        fail_if_error (state, "kim_preferences_create", err, 
+                       "while creating preferences");
+        
+        if (!err) {
+            err = kim_preferences_remove_all_favorite_identities (prefs);
+            fail_if_error (state, "kim_preferences_remove_all_favorite_identities", err, 
+                           "while removing all favorite identities");
+        }
+        
+        if (!err) {
+            err = kim_options_create (&options);
+            fail_if_error (state, "kim_options_create", err, 
+                           "while creating options");
+        }        
+        
+        for (i = 0; !err && fids[i].identity; i++) {
+            kim_identity identity = NULL;
+            
+            err = kim_identity_create_from_string (&identity, fids[i].identity);
+            fail_if_error (state, "kim_identity_create_from_string", err, 
+                           "while creating the identity for %s", 
+                           fids[i].identity);
+            
+            if (!err) {
+                err = kim_options_set_lifetime (options, fids[i].lifetime);
+                fail_if_error (state, "kim_options_set_lifetime", err, 
+                               "while setting the lifetime to %d", 
+                               (int) fids[i].lifetime);            
+            }
+            if (!err) {
+                err = kim_options_set_renewal_lifetime (options, fids[i].renewal_lifetime);
+                fail_if_error (state, "kim_options_set_renewal_lifetime", err, 
+                               "while setting the renewal lifetime to %d", 
+                               (int) fids[i].renewal_lifetime);            
+            }
+            
+            if (!err) {
+                err = kim_preferences_add_favorite_identity (prefs, identity, options);
+                fail_if_error (state, "kim_preferences_add_favorite_identity", err, 
+                               "while adding %s to the favorite identities", 
+                               fids[i].identity);            
+            }
+            
+            kim_identity_free (&identity);
+        }
+        
+        if (!err) {
+            err = kim_preferences_synchronize (prefs);
+            fail_if_error (state, "kim_preferences_synchronize", err, 
+                           "while setting the favorite identities");
+        }
+        
+        kim_options_free (&options);
+        kim_preferences_free (&prefs);
+    }
+    
+    if (!err) {
+        kim_preferences prefs = NULL;
+        kim_count count, i;
+        
+        err = kim_preferences_create (&prefs);
+        fail_if_error (state, "kim_preferences_create", err, 
+                       "while creating preferences");
+        
+        if (!err) {
+            err = kim_preferences_get_number_of_favorite_identities (prefs, &count);
+            fail_if_error (state, "kim_preferences_get_number_of_favorite_identities", err, 
+                           "while getting number of favorite identities");
+        }
+        
+        
+        for (i = 0; !err && fids[i].identity; i++) {
+            kim_identity identity = NULL;
+            kim_count j;
+            kim_boolean found = 0;
+            
+            err = kim_identity_create_from_string (&identity, fids[i].identity);
+            fail_if_error (state, "kim_identity_create_from_string", err, 
+                           "while creating the identity for %s", 
+                           fids[i].identity);
+
+            for (j = 0; j < count; j++) {
+                kim_identity compare_identity = NULL;
+                kim_options compare_options = NULL;
+                kim_comparison comparison;
+
+                err = kim_preferences_get_favorite_identity_at_index (prefs, j, 
+                                                                      &compare_identity, 
+                                                                      &compare_options);
+                fail_if_error (state, "kim_preferences_get_favorite_identity_at_index", err, 
+                               "while getting favorite identity %d", (int) j);
+            
+                if (!err) {
+                    err = kim_identity_compare (identity, compare_identity, 
+                                                &comparison);
+                    fail_if_error (state, "kim_identity_compare", err, 
+                                   "while comparing %s to favorite identity %d", 
+                                   fids[i].identity, (int) i);
+                }
+                
+                if (!err && kim_comparison_is_equal_to (comparison)) {
+                    kim_lifetime compare_lifetime;
+                    kim_lifetime compare_renewal_lifetime;
+                   
+                    found = 1;
+                    
+                    err = kim_options_get_lifetime (compare_options, &compare_lifetime);
+                    fail_if_error (state, "kim_options_get_lifetime", err, 
+                                   "while getting the lifetime for %s", 
+                                   fids[i].identity);            
+                    
+                    if (!err && fids[i].lifetime != compare_lifetime) {
+                        log_failure (state, "Unexpected lifetime for %s (got %d, expected %d)", 
+                                     fids[i].identity, (int) compare_lifetime,
+                                     (int) fids[i].lifetime);                
+                    }
+                    
+                    if (!err) {
+                        err = kim_options_get_renewal_lifetime (compare_options, 
+                                                                &compare_renewal_lifetime);
+                        fail_if_error (state, "kim_options_get_renewal_lifetime", err, 
+                                       "while getting the lifetime for %s", 
+                                       fids[i].identity);            
+                    }
+                    
+                    if (!err && fids[i].renewal_lifetime != compare_renewal_lifetime) {
+                        log_failure (state, "Unexpected renewal lifetime for %s (got %d, expected %d)", 
+                                     fids[i].identity, 
+                                     (int) compare_renewal_lifetime,
+                                     (int) fids[i].renewal_lifetime);                
+                    }
+                }
+                
+                kim_identity_free (&compare_identity);
+                kim_options_free (&compare_options);
+            }
+                
+            if (!err && !found) {
+                log_failure (state, "Favorite identity %s not found in favorite identities list", 
+                             fids[i].identity);
+            }
+        }
+        
+        if (!err && i != count) {
+            log_failure (state, "Unexpected number of favorite identities (got %d, expected %d)", 
+                         (int) count, (int) i);
+        }
+        
+        kim_preferences_free (&prefs);
+    }
+    
+    end_test (state);
+}
+
index e86f11f2fbf974ce24433ab14d815202b7bca958..275b291a48ac18c942c02d89ecb00c4dffd61469 100644 (file)
@@ -39,4 +39,6 @@ void test_kim_preferences_set_remember_options (kim_test_state_t state);
 
 void test_kim_preferences_set_client_identity (kim_test_state_t state);
 
+void test_kim_preferences_add_favorite_identity (kim_test_state_t state);
+
 #endif /* TEST_KIM_PREFERENCES_H */