Also fix bugs related to multiple requests.
using Gee;
-class IdentityManagerModel : Object {
+public class IdentityManagerModel : Object {
private const string FILE_NAME = "identities.txt";
private IIdentityCardStore store;
using Gee;
using Gtk;
-class IdentityManagerView : Window {
+public class IdentityManagerView : Window {
private const int WINDOW_WIDTH = 400;
private const int WINDOW_HEIGHT = 500;
protected IdentityManagerApp parent_app;
private TreeModelFilter filter;
public IdentityManagerModel identities_manager;
- private SList<IdCard> candidates;
+ private unowned SList<IdCard> candidates;
- private IdCard default_id_card;
public GLib.Queue<IdentityRequest> request_queue;
private HashTable<Gtk.Button, string> service_button_map;
load_id_cards();
}
- public void add_candidate (IdCard idcard)
- {
- candidates.append (idcard);
- }
-
private bool visible_func (TreeModel model, TreeIter iter)
{
IdCard id_card;
remove_id_card_widget((IdCardWidget)id_card_widget);
}
- this.default_id_card = null;
LinkedList<IdCard> card_list = identities_manager.get_card_list() ;
if (card_list == null) {
return;
add_id_card_data (id_card);
add_id_card_widget (id_card);
}
-
- if (card_list.size > 0){
- this.default_id_card = card_list.first();
- }
}
private void fill_details (IdCardWidget id_card_widget)
dialog.destroy ();
}
- public void select_identity (IdentityRequest request)
+ public void queue_identity_request(IdentityRequest request)
{
- IdCard identity = null;
-
- this.request_queue.push_tail (request);
-
- if (custom_vbox.current_idcard != null &&
- custom_vbox.current_idcard.send_button != null)
- custom_vbox.current_idcard.send_button.set_sensitive (true);
-
- if (request.select_default)
- {
- identity = default_id_card;
- }
-
- if (identity == null)
- {
- 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.get_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.get_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;
- }
+ if (this.request_queue.is_empty())
+ { /* setup widgets */
+ candidates = request.candidates;
+ filter.refilter();
+ redraw_id_card_widgets ();
+ show ();
}
- // 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);
+ this.request_queue.push_tail (request);
}
public void send_identity_cb (IdCard identity)
{
return_if_fail (request_queue.length > 0);
+ candidates = null;
var request = this.request_queue.pop_head ();
bool reset_password = false;
- if (request.service != null && request.service != "")
- {
- bool duplicate_service = false;
-
- foreach (string service in identity.services)
- {
- if (service == request.service)
- duplicate_service = true;
- }
- if (duplicate_service == false)
- {
- 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.update_card (identity);
- }
- }
-
if (identity.password == null)
{
var dialog = new AddPasswordDialog ();
}
if (this.request_queue.is_empty())
+ {
+ candidates = null;
Gtk.main_quit ();
+ } else {
+ candidates = this.request_queue.peek_head().candidates;
+ filter.refilter();
+ redraw_id_card_widgets ();
+ }
if (identity != null)
- this.default_id_card = identity;
+ parent_app.default_id_card = identity;
request.return_identity (identity);
if (reset_password)
identity.password = null;
- candidates = null;
}
private void label_make_bold (Label label)
+using Gee;
using Gtk;
-class IdentityManagerApp {
+public class IdentityManagerApp {
public IdentityManagerModel model;
+ public IdCard default_id_card;
private IdentityManagerView view;
private MoonshotServer ipc_server;
private const int WINDOW_WIDTH = 400;
private const int WINDOW_HEIGHT = 500;
public void show() {
- view.show();
+ if (view != null) view.show();
}
- public IdentityManagerApp () {
+ public IdentityManagerApp (bool headless) {
model = new IdentityManagerModel(this);
- view = new IdentityManagerView(this);
+ if (!headless)
+ view = new IdentityManagerView(this);
+ LinkedList<IdCard> card_list = model.get_card_list() ;
+ if (card_list.size > 0)
+ this.default_id_card = card_list.first();
+
init_ipc_server ();
#if OS_MACOS
Signal.connect(osxApp, "NSApplicationOpenFile", (GLib.Callback)(on_osx_open_files), this);
#endif
- view.show();
+ if (view != null) view.show();
+ }
+
+ public bool add_identity (IdCard id) {
+ /* TODO: add to store here irrespective of view's existence */
+ if (view != null) return view.add_identity(id);
+ return false;
+ }
+
+ public void select_identity (IdentityRequest request) {
+ IdCard identity = null;
+
+ if (request.select_default)
+ {
+ identity = default_id_card;
+ }
+
+ if (identity == null)
+ {
+ 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 model.get_card_list())
+ {
+ /* If NAI matches we add id card to the candidate list */
+ if (has_nai && request.nai == id.nai)
+ {
+ nai_provided = id;
+ request.candidates.append (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)
+ {
+ request.candidates.append (id);
+ continue;
+ }
+ }
+ }
+ }
+
+ /* If more than one candidate we dissasociate service from all ids */
+ if (has_srv && request.candidates.length() > 1)
+ {
+ foreach (IdCard id in request.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;
+ }
+ }
+
+// model.store_id_cards ();
+
+ /* If there are no candidates we use the service matching rules */
+ if (request.candidates.length () == 0)
+ {
+ foreach (IdCard id in model.get_card_list())
+ {
+ foreach (Rule rule in id.rules)
+ {
+ if (!match_service_pattern (request.service, rule.pattern))
+ continue;
+
+ request.candidates.append (id);
+
+ if (rule.always_confirm == "true")
+ confirm = true;
+ }
+ }
+ }
+
+ if (request.candidates.length () > 1)
+ {
+ if (has_nai && nai_provided != null)
+ {
+ identity = nai_provided;
+ confirm = false;
+ }
+ else
+ confirm = true;
+ }
+ if (identity == null)
+ identity = request.candidates.nth_data (0);
+
+ /* TODO: If candidate list empty return fail */
+
+ if (confirm && (view != null))
+ {
+ view.queue_identity_request(request);
+ return;
+ }
+ }
+ // Send back the identity (we can't directly run the
+ // callback because we may be being called from a 'yield')
+ Idle.add (() => { request.return_identity (identity); return false; });
+ return;
+ }
+
+ private bool match_service_pattern (string service, string pattern)
+ {
+ var pspec = new PatternSpec (pattern);
+ return pspec.match_string (service);
}
#if IPC_MSRPC
uint reply = bus.request_name ("org.janet.Moonshot", (uint) 0);
assert (reply == DBus.RequestNameReply.PRIMARY_OWNER);
- this.ipc_server = new MoonshotServer (this.view);
+ this.ipc_server = new MoonshotServer (this);
conn.register_object ("/org/janet/moonshot", ipc_server);
}
catch (DBus.Error e)
private void init_ipc_server ()
{
- this.ipc_server = new MoonshotServer (this.view);
+ this.ipc_server = new MoonshotServer (this);
GLib.Bus.own_name (GLib.BusType.SESSION,
"org.janet.Moonshot",
GLib.BusNameOwnerFlags.NONE,
public static int main(string[] args){
- Gtk.init(ref args);
+#if IPC_DBUS_GLIB
+ bool headless = GLib.Environment.get_variable("DISPLAY") != null;
+#else
+ bool headless = false;
+#endif
+ if (!headless)
+ Gtk.init(ref args);
#if OS_WIN32
// Force specific theme settings on Windows without requiring a gtkrc file
Intl.textdomain (Config.GETTEXT_PACKAGE);
- var app = new IdentityManagerApp();
+ var app = new IdentityManagerApp(headless);
app.show();
- Gtk.main();
+ if (headless) {
+#if IPC_DBUS_GLIB
+ MainLoop loop = new MainLoop();
+ loop.run();
+#endif
+ } else {
+ Gtk.main();
+ }
return 0;
}
-delegate void ReturnIdentityCallback (IdentityRequest request);
+public delegate void ReturnIdentityCallback (IdentityRequest request);
-class IdentityRequest : Object {
+public class IdentityRequest : Object {
public IdCard? id_card = null;
public bool complete = false;
public bool select_default = false;
- private IdentityManagerView main_window;
+ private IdentityManagerApp parent_app;
public string nai;
public string password;
public string service;
+ public SList<IdCard> candidates;
ReturnIdentityCallback callback = null;
- public IdentityRequest (IdentityManagerView main_window,
+ public IdentityRequest (IdentityManagerApp app,
string nai,
string password,
string service)
{
- this.main_window = main_window;
+ this.parent_app = app;
this.nai = nai;
this.password = password;
this.service = service;
}
- public IdentityRequest.default (IdentityManagerView main_window)
+ public IdentityRequest.default (IdentityManagerApp app)
{
- this.main_window = main_window;
+ this.parent_app = app;
this.select_default = true;
}
}
public bool execute () {
- main_window.select_identity (this);
+ parent_app.select_identity (this);
/* This function works as a GSourceFunc, so it can be passed to
* the main loop from other threads
}
public void return_identity (IdCard? id_card) {
- return_if_fail (callback != null);
-
this.id_card = id_card;
this.complete = true;
+ /* update id_card service list */
+ if (id_card != null && this.service != null && this.service != "")
+ {
+ bool duplicate_service = false;
+
+ foreach (string service in id_card.services)
+ {
+ if (service == this.service)
+ duplicate_service = true;
+ }
+ if (duplicate_service == false)
+ {
+ string[] services = new string[id_card.services.length + 1];
+
+ for (int i = 0; i < id_card.services.length; i++)
+ services[i] = id_card.services[i];
+
+ services[id_card.services.length] = this.service;
+ id_card.services = services;
+
+ this.parent_app.model.update_card (id_card);
+ }
+ }
+
+ return_if_fail (callback != null);
callback (this);
}
[DBus (name = "org.janet.Moonshot")]
public class MoonshotServer : Object {
- private IdentityManagerView main_window;
+ private IdentityManagerApp parent_app;
- public MoonshotServer (Gtk.Window window)
+ public MoonshotServer (IdentityManagerApp app)
{
- this.main_window = (IdentityManagerView) window;
+ this.parent_app = app;
}
public async bool get_identity (string nai,
out string subject_name_constraint,
out string subject_alt_name_constraint)
{
- var request = new IdentityRequest (main_window,
+ var request = new IdentityRequest (parent_app,
nai,
password,
service);
out string subject_name_constraint,
out string subject_alt_name_constraint)
{
- var request = new IdentityRequest.default (main_window);
+ var request = new IdentityRequest.default (parent_app);
request.set_callback ((IdentityRequest) => get_default_identity.callback());
request.execute ();
yield;
}
}
- return main_window.add_identity (idcard);
+ return parent_app.add_identity (idcard);
}