src/moonshot-webp-parser.vala \
src/moonshot-id.vala
-src_moonshot_VALAFLAGS = --pkg gtk+-2.0 $(AM_VALAFLAGS)
+src_moonshot_VALAFLAGS = --pkg gdk-2.0 --pkg gtk+-2.0 $(AM_VALAFLAGS)
src_moonshot_CPPFLAGS = $(moonshot_CFLAGS) $(AM_CPPFLAGS)
src_moonshot_LDADD = $(moonshot_LIBS)
-src_moonshot_webp_VALAFLAGS = --vapidir=$(top_srcdir)/libmoonshot --pkg libmoonshot $(AM_VALAFLAGS)
+src_moonshot_webp_VALAFLAGS = --vapidir=$(top_srcdir)/libmoonshot --pkg gdk-2.0 --pkg libmoonshot $(AM_VALAFLAGS)
src_moonshot_webp_CPPFLAGS = $(moonshot_CFLAGS) $(AM_CPPFLAGS)
src_moonshot_webp_LDADD = $(moonshot_LIBS) ${top_builddir}/libmoonshot/libmoonshot.la
noinst_PROGRAMS = \
examples/client \
+ examples/service-selection \
tests/basic
+examples_service_selection_SOURCES = examples/service-selection.c
+examples_service_selection_CPPFLAGS = $(libmoonshot_CFLAGS) $(AM_CPPFLAGS)
+examples_service_selection_LDADD = ${top_builddir}/libmoonshot/libmoonshot.la
+
examples_client_SOURCES = examples/client.c
examples_client_CPPFLAGS = $(libmoonshot_CFLAGS) $(AM_CPPFLAGS)
examples_client_LDADD = ${top_builddir}/libmoonshot/libmoonshot.la
--- /dev/null
+#include <glib.h>
+#include "libmoonshot.h"
+
+int main (int argc, char *argv[])
+{
+ MoonshotError *error;
+ gboolean success;
+
+ char *nai,
+ *password,
+ *server_certificate_hash,
+ *ca_certificate,
+ *subject_name_constraint,
+ *subject_alt_name_constraint;
+
+ success = moonshot_get_identity ("",
+ "",
+ "email@project-moonshot.org",
+ &nai,
+ &password,
+ &server_certificate_hash,
+ &ca_certificate,
+ &subject_name_constraint,
+ &subject_alt_name_constraint,
+ &error);
+
+ if (success)
+ g_debug ("Got id: %s %s\n", nai, password);
+
+
+ moonshot_free (nai);
+ moonshot_free (password);
+ moonshot_free (server_certificate_hash);
+ moonshot_free (ca_certificate);
+ moonshot_free (subject_name_constraint);
+ moonshot_free (subject_alt_name_constraint);
+}
public class TrustAnchor : Object
{
- public string ca_cert {get; set; default = null;}
- public string subject {get; set; default = null;}
- public string subject_alt {get; set; default = null;}
- public string server_cert {get; set; default = null;}
+ public string ca_cert {get; set; default = "";}
+ public string subject {get; set; default = "";}
+ public string subject_alt {get; set; default = "";}
+ public string server_cert {get; set; default = "";}
}
public struct Rule
{
private string _nai;
- public string display_name { get; set; default = null; }
+ public string display_name { get; set; default = ""; }
- public string username { get; set; default = null; }
+ public string username { get; set; default = ""; }
public string password { get; set; default = null; }
- public string issuer { get; set; default = null; }
+ public string issuer { get; set; default = ""; }
public Rule[] rules {get; set; default = {};}
public string[] services { get; set; default = {}; }
-
public TrustAnchor trust_anchor { get; set; default = new TrustAnchor (); }
- //TODO: Set the getter and remove the setter/default
- public unowned string nai { get { _nai = username + "@" + password; return _nai;}}
+ public Gdk.Pixbuf pixbuf { get; set; default = null; }
+
+ public unowned string nai { get { _nai = username + "@" + issuer; return _nai;}}
}
id_card.services = key_file.get_string_list (identity, "Services");
id_card.display_name = key_file.get_string (identity, "DisplayName");
id_card.set_data ("pixbuf", find_icon ("avatar-default", 48));
+
+
+ if (key_file.has_key (identity, "Rules-Patterns") &&
+ key_file.has_key (identity, "Rules-AlwaysConfirm"))
+ {
+ string [] rules_patterns = key_file.get_string_list (identity, "Rules-Patterns");
+ string [] rules_always_conf = key_file.get_string_list (identity, "Rules-AlwaysConfirm");
+
+ if (rules_patterns.length == rules_always_conf.length)
+ {
+ Rule[] rules = new Rule[rules_patterns.length];
+ for (int i = 0; i < rules_patterns.length; i++)
+ {
+ rules[i] = {rules_patterns[i], rules_always_conf[i]};
+ }
+ id_card.rules = rules;
+ }
+ }
+ // Trust anchor
+ id_card.trust_anchor.ca_cert = key_file.get_string (identity, "CA-Cert");
+ id_card.trust_anchor.subject = key_file.get_string (identity, "Subject");
+ id_card.trust_anchor.subject_alt = key_file.get_string (identity, "SubjectAlt");
+ id_card.trust_anchor.server_cert = key_file.get_string (identity, "ServerCert");
id_card_list.prepend (id_card);
}
public bool select_default = false;
private MainWindow main_window;
- private string nai;
- private string password;
- private string certificate;
+ public string nai;
+ public string password;
+ public string service;
ReturnIdentityCallback callback = null;
public IdentityRequest (MainWindow main_window,
string nai,
string password,
- string certificate)
+ string service)
{
this.main_window = main_window;
this.nai = nai;
this.password = password;
- this.certificate = certificate;
+ this.service = service;
}
public IdentityRequest.default (MainWindow main_window)
nai_out = id_card.nai;
password_out = id_card.password;
- server_certificate_hash = "certificate";
-
- // User should have been prompted if there was no p/w.
- return_if_fail (nai_out != null);
- return_if_fail (password_out != null);
+ server_certificate_hash = id_card.trust_anchor.server_cert;
+ ca_certificate = id_card.trust_anchor.ca_cert;
+ subject_name_constraint = id_card.trust_anchor.subject;
+ subject_alt_name_constraint = id_card.trust_anchor.subject_alt;
+
+ if (nai_out == null)
+ nai_out = "";
+ if (password_out == null)
+ password_out = "";
+ if (server_certificate_hash == null)
+ server_certificate_hash = "";
+ if (ca_certificate == null)
+ ca_certificate = "";
+ if (subject_name_constraint == null)
+ subject_name_constraint = "";
+ if (subject_alt_name_constraint == null)
+ subject_alt_name_constraint = "";
return true;
}
nai_out = request.id_card.nai;
password_out = request.id_card.password;
- server_certificate_hash = "certificate";
-
- // User should have been prompted if there was no p/w.
- return_val_if_fail (nai_out != null, false);
- return_val_if_fail (password_out != null, false);
+ server_certificate_hash = request.id_card.trust_anchor.server_cert;
+ ca_certificate = request.id_card.trust_anchor.ca_cert;
+ subject_name_constraint = request.id_card.trust_anchor.subject;
+ subject_alt_name_constraint = request.id_card.trust_anchor.subject_alt;
+
+ if (nai_out == null)
+ nai_out = "";
+ if (password_out == null)
+ password_out = "";
+ if (server_certificate_hash == null)
+ server_certificate_hash = "";
+ if (ca_certificate == null)
+ ca_certificate = "";
+ if (subject_name_constraint == null)
+ subject_name_constraint = "";
+ if (subject_alt_name_constraint == null)
+ subject_alt_name_constraint = "";
return true;
}
private TreeModelFilter filter;
public IdentitiesManager identities_manager;
+ private SList<IdCard> candidates;
private MoonshotServer ipc_server;
connect_signals();
init_ipc_server();
}
+
+ public void add_candidate (IdCard idcard)
+ {
+ candidates.append (idcard);
+ }
private bool visible_func (TreeModel model, TreeIter iter)
{
- string issuer;
- string search_text;
- string issuer_casefold;
- string search_text_casefold;
+ IdCard id_card;
model.get (iter,
- Columns.ISSUER_COL, out issuer);
- search_text = this.search_entry.get_text ();
+ Columns.IDCARD_COL, out id_card);
- if (issuer == null || search_text == null)
+ if (id_card == null)
return false;
+
+ if (candidates != null)
+ {
+ bool is_candidate = false;
+ foreach (IdCard candidate in candidates)
+ {
+ if (candidate == id_card)
+ is_candidate = true;
+ }
+ if (!is_candidate)
+ return false;
+ }
+
+ string entry_text = search_entry.get_text ();
+ if (entry_text == null || entry_text == "")
+ {
+ return true;
+ }
- issuer_casefold = issuer.casefold ();
- search_text_casefold = search_text.casefold ();
+ foreach (string search_text in entry_text.split(" "))
+ {
+ if (search_text == "")
+ continue;
+
- if (issuer_casefold.contains (search_text_casefold))
- return true;
+ string search_text_casefold = search_text.casefold ();
+
+ if (id_card.issuer != null)
+ {
+ string issuer_casefold = id_card.issuer;
+
+ if (issuer_casefold.contains (search_text_casefold))
+ return true;
+ }
+
+ if (id_card.display_name != null)
+ {
+ string display_name_casefold = id_card.display_name.casefold ();
+
+ if (display_name_casefold.contains (search_text_casefold))
+ return true;
+ }
+
+ if (id_card.services.length > 0)
+ {
+ foreach (string service in id_card.services)
+ {
+ string service_casefold = service.casefold ();
+ if (service_casefold.contains (search_text_casefold))
+ return true;
+ }
+ }
+ }
return false;
}
this.search_entry.set_icon_sensitive (EntryIconPosition.SECONDARY, has_text);
this.vbox_right.set_visible (false);
- this.resize (WINDOW_WIDTH, WINDOW_HEIGHT);
}
private bool search_entry_key_press_event_cb (Gdk.EventKey e)
if (request.select_default)
{
- identity = this.default_id_card;
+ identity = default_id_card;
}
- /* Automatic service matching rules can go here */
-
if (identity == null)
{
- // Resort to manual selection
- this.show ();
- }
- else
- {
- // Send back the identity (we can't directly run the
- // callback because we may be being called from a 'yield')
- Idle.add (() => { send_identity_cb (identity); return false; });
- return;
+ bool has_nai = request.nai != null && request.nai != "";
+ bool has_srv = request.service != null && request.service != "";
+ bool confirm = false;
+ IdCard nai_provided = null;
+
+ foreach (IdCard id in identities_manager.id_card_list)
+ {
+ /* If NAI matches we add id card to the candidate list */
+ if (has_nai && request.nai == id.nai)
+ {
+ nai_provided = id;
+ add_candidate (id);
+ continue;
+ }
+
+ /* If any service matches we add id card to the candidate list */
+ if (has_srv)
+ {
+ foreach (string srv in id.services)
+ {
+ if (request.service == srv)
+ {
+ add_candidate (id);
+ continue;
+ }
+ }
+ }
+ }
+
+ /* If more than one candidate we dissasociate service from all ids */
+ if (has_srv && candidates.length() > 1)
+ {
+ foreach (IdCard id in candidates)
+ {
+ int i = 0;
+ SList<string> services_list = null;
+ bool has_service = false;
+
+ foreach (string srv in id.services)
+ {
+ if (srv == request.service)
+ {
+ has_service = true;
+ continue;
+ }
+ services_list.append (srv);
+ }
+
+ if (!has_service)
+ continue;
+
+ if (services_list.length () == 0)
+ {
+ id.services = {};
+ continue;
+ }
+
+ string[] services = new string[services_list.length ()];
+ foreach (string srv in services_list)
+ {
+ services[i] = srv;
+ i++;
+ }
+
+ id.services = services;
+ }
+ }
+
+ identities_manager.store_id_cards ();
+
+ /* If there are no candidates we use the service matching rules */
+ if (candidates.length () == 0)
+ {
+ foreach (IdCard id in identities_manager.id_card_list)
+ {
+ foreach (Rule rule in id.rules)
+ {
+ if (!match_service_pattern (request.service, rule.pattern))
+ continue;
+
+ candidates.append (id);
+
+ if (rule.always_confirm == "true")
+ confirm = true;
+ }
+ }
+ }
+
+ if (candidates.length () > 1)
+ {
+ if (has_nai && nai_provided != null)
+ {
+ identity = nai_provided;
+ confirm = false;
+ }
+ else
+ confirm = true;
+ }
+ else
+ identity = candidates.nth_data (0);
+
+ /* TODO: If candidate list empty return fail */
+
+ if (confirm)
+ {
+ filter.refilter();
+ redraw_id_card_widgets ();
+ show ();
+ return;
+ }
}
+ // Send back the identity (we can't directly run the
+ // callback because we may be being called from a 'yield')
+ Idle.add (() => { send_identity_cb (identity); return false; });
+ return;
+ }
+
+ private bool match_service_pattern (string service, string pattern)
+ {
+ var pspec = new PatternSpec (pattern);
+ return pspec.match_string (service);
}
public void send_identity_cb (IdCard identity)
var request = this.request_queue.pop_head ();
bool reset_password = false;
+ if (request.service != null && request.service != "")
+ {
+ string[] services = new string[identity.services.length + 1];
+
+ for (int i = 0; i < identity.services.length; i++)
+ services[i] = identity.services[i];
+
+ services[identity.services.length] = request.service;
+
+ identity.services = services;
+
+ identities_manager.store_id_cards();
+ }
+
if (identity.password == null)
{
var dialog = new AddPasswordDialog ();
if (reset_password)
identity.password = null;
+
+ candidates = null;
}
private void label_make_bold (Label label)
SList<string> services = new SList<string>();
- foreach (string srv in id_card.services)
+ foreach (string srv in idcard.services)
{
if (srv == candidate)
continue;
services.append (srv);
}
- id_card.services = new string[services.length()];
- for (int j=0; j<id_card.services.length; j++)
+ idcard.services = new string[services.length()];
+ for (int j=0; j<idcard.services.length; j++)
{
- id_card.services[j] = services.nth_data(j);
+ idcard.services[j] = services.nth_data(j);
}
var children = services_internal_vbox.get_children ();
foreach (var hbox in children)
hbox.destroy();
- fill_services_vbox (id_card);
+ fill_services_vbox (idcard);
custom_vbox.current_idcard.update_id_card_label ();
}
--- /dev/null
+<identities>
+ <identity>
+ <display-name>Unique Name</display-name>
+ <user>user1</user>
+ <password></password>
+ <realm>foo.baz</realm>
+ <services>
+ <service>irc@jabber.project-moonshot.org</service>
+ <service>xmpp@jabber.project-moonshot.org</service>
+ </services>
+ <selection-rules>
+ <rule>
+ <pattern>PATTERN</pattern>
+ <always-confirm>true</always-confirm>
+ </rule>
+ <rule>
+ <pattern>imap@*moonshot.org</pattern>
+ <always-confirm>false</always-confirm>
+ </rule>
+ </selection-rules>
+ <trust-anchor>
+ <ca-cert>ABCDEFGHIJKLMNOPQRSTUVWXYZ123455678910</ca-cert>
+ <subject>Foo</subject>
+ <subject-alt>Bar</subject-alt>
+ <!-- Or alternatively -->
+ <server-cert>ABCDEFGHIJKLMNOPQRSTUVWXYZ123455678910</server-cert>
+ </trust-anchor>
+ </identity>
+ <identity>
+ <display-name>Another Unique Name</display-name>
+ <user>user2</user>
+ <password></password>
+ <realm>foo.bar</realm>
+ <services>
+ <service>irc@jabber.project-moonshot.org</service>
+ <service>email@project-moonshot.org</service>
+ </services>
+ <selection-rules>
+ <rule>
+ <pattern>*@project-moonshot.org</pattern>
+ <always-confirm>true</always-confirm>
+ </rule>
+ </selection-rules>
+ <trust-anchor>
+ <ca-cert>ABCDEFGHIJKLMNOPQRSTUVWXYZ123455678910</ca-cert>
+ <subject>Foo</subject>
+ <subject-alt>Bar</subject-alt>
+ <!-- Or alternatively -->
+ <server-cert>ABCDEFGHIJKLMNOPQRSTUVWXYZ123455678910</server-cert>
+ </trust-anchor>
+ </identity>
+ <identity>
+ <display-name>Yet Another Unique Name</display-name>
+ <user>user3</user>
+ <password></password>
+ <realm>foo.com</realm>
+ <services>
+ <service>irc@jabber.project-moonshot.org</service>
+ <service>email@project-moonshot.org</service>
+ </services>
+ <trust-anchor>
+ <ca-cert>ABCDEFGHIJKLMNOPQRSTUVWXYZ123455678910</ca-cert>
+ <subject>Foo</subject>
+ <subject-alt>Bar</subject-alt>
+ <!-- Or alternatively -->
+ <server-cert>ABCDEFGHIJKLMNOPQRSTUVWXYZ123455678910</server-cert>
+ </trust-anchor>
+ </identity>
+</identities>