예제 #1
0
        /// <summary>
        /// adds the entry output data to the intent to be sent to a plugin
        /// </summary>
        public static void AddEntryToIntent(Intent intent, PwEntryOutput entry)
        {
            /*//add the entry XML
            not yet implemented. What to do with attachments?
            MemoryStream memStream = new MemoryStream();
            KdbxFile.WriteEntries(memStream, new[] {entry});
            string entryData = StrUtil.Utf8.GetString(memStream.ToArray());
            intent.PutExtra(Strings.ExtraEntryData, entryData);
            */
            //add the output string array (placeholders replaced taking into account the db context)
            Dictionary<string, string> outputFields = entry.OutputStrings.ToDictionary(pair => StrUtil.SafeXmlString(pair.Key), pair => pair.Value.ReadString());

            JSONObject jsonOutput = new JSONObject(outputFields);
            var jsonOutputStr = jsonOutput.ToString();
            intent.PutExtra(Strings.ExtraEntryOutputData, jsonOutputStr);

            JSONArray jsonProtectedFields = new JSONArray(
                (System.Collections.ICollection)entry.OutputStrings
                    .Where(pair => pair.Value.IsProtected)
                    .Select(pair => pair.Key)
                    .ToArray());
            intent.PutExtra(Strings.ExtraProtectedFieldsList, jsonProtectedFields.ToString());

            intent.PutExtra(Strings.ExtraEntryId, entry.Uuid.ToHexString());
        }
예제 #2
0
        public ITotpPluginAdapter TryGetAdapter(PwEntryOutput entry)
        {
            if (entry == null)
            {
                return(null);
            }

            try
            {
                foreach (ITotpPluginAdapter adapter in _pluginAdapters)
                {
                    TotpData totpData = adapter.GetTotpData(
                        App.Kp2a.LastOpenedEntry.OutputStrings.ToDictionary(pair => StrUtil.SafeXmlString(pair.Key),
                                                                            pair => pair.Value.ReadString()), LocaleManager.LocalizedAppContext, false);
                    if (totpData.IsTotpEntry)
                    {
                        return(adapter);
                    }
                }
            }
            catch (Exception e)
            {
                Kp2aLog.LogUnexpectedError(e);
            }


            return(null);
        }
예제 #3
0
파일: PluginHost.cs 프로젝트: 77rusa/README
        /// <summary>
        /// adds the entry output data to the intent to be sent to a plugin
        /// </summary>
        public static void AddEntryToIntent(Intent intent, PwEntryOutput entry)
        {
            /*//add the entry XML
             * not yet implemented. What to do with attachments?
             * MemoryStream memStream = new MemoryStream();
             * KdbxFile.WriteEntries(memStream, new[] {entry});
             * string entryData = StrUtil.Utf8.GetString(memStream.ToArray());
             * intent.PutExtra(Strings.ExtraEntryData, entryData);
             */
            //add the output string array (placeholders replaced taking into account the db context)
            Dictionary <string, string> outputFields = entry.OutputStrings.ToDictionary(pair => StrUtil.SafeXmlString(pair.Key), pair => pair.Value.ReadString());

            JSONObject jsonOutput    = new JSONObject(outputFields);
            var        jsonOutputStr = jsonOutput.ToString();

            intent.PutExtra(Strings.ExtraEntryOutputData, jsonOutputStr);

            JSONArray jsonProtectedFields = new JSONArray(
                (System.Collections.ICollection)entry.OutputStrings
                .Where(pair => pair.Value.IsProtected)
                .Select(pair => pair.Key)
                .ToArray());

            intent.PutExtra(Strings.ExtraProtectedFieldsList, jsonProtectedFields.ToString());

            intent.PutExtra(Strings.ExtraEntryId, entry.Uuid.ToHexString());
        }
        bool MakeAccessibleForKeyboard(PwEntryOutput entry, string searchUrl)
        {
#if EXCLUDE_KEYBOARD
            return(false);
#else
            bool hasData = false;
            Keepass2android.Kbbridge.KeyboardDataBuilder kbdataBuilder = new Keepass2android.Kbbridge.KeyboardDataBuilder();

            String[] keys = { PwDefs.UserNameField,
                              PwDefs.PasswordField,
                              PwDefs.UrlField,
                              PwDefs.NotesField,
                              PwDefs.TitleField };
            int[]    resIds = { Resource.String.entry_user_name,
                                Resource.String.entry_password,
                                Resource.String.entry_url,
                                Resource.String.entry_comment,
                                Resource.String.entry_title };

            //add standard fields:
            int i = 0;
            foreach (string key in keys)
            {
                String value = entry.OutputStrings.ReadSafe(key);

                if (value.Length > 0)
                {
                    kbdataBuilder.AddString(key, GetString(resIds[i]), value);
                    hasData = true;
                }
                i++;
            }
            //add additional fields:
            foreach (var pair in entry.OutputStrings)
            {
                var key   = pair.Key;
                var value = pair.Value.ReadString();

                if (!PwDefs.IsStandardField(key))
                {
                    kbdataBuilder.AddString(pair.Key, pair.Key, value);
                    hasData = true;
                }
            }


            kbdataBuilder.Commit();
            Keepass2android.Kbbridge.KeyboardData.EntryName = entry.OutputStrings.ReadSafe(PwDefs.TitleField);
            Keepass2android.Kbbridge.KeyboardData.EntryId   = entry.Uuid.ToHexString();
            if (hasData)
            {
                Keepass2android.Autofill.AutoFillService.NotifyNewData(searchUrl);
            }

            return(hasData);
#endif
        }
예제 #5
0
파일: Kp2aTotp.cs 프로젝트: 77rusa/README
        public ITotpPluginAdapter TryGetAdapter(PwEntryOutput entry)
        {
            if (entry == null)
            {
                return(null);
            }
            foreach (ITotpPluginAdapter adapter in _pluginAdapters)
            {
                TotpData totpData = adapter.GetTotpData(App.Kp2a.LastOpenedEntry.OutputStrings.ToDictionary(pair => StrUtil.SafeXmlString(pair.Key), pair => pair.Value.ReadString()), Application.Context, false);
                if (totpData.IsTotpEnry)
                {
                    return(adapter);
                }
            }

            return(null);
        }
예제 #6
0
        public TotpData TryGetTotpData(PwEntryOutput entry)
        {
            if (entry == null)
            {
                return(null);
            }
            foreach (ITotpPluginAdapter adapter in _pluginAdapters)
            {
                TotpData totpData = adapter.GetTotpData(entry.OutputStrings.ToDictionary(pair => StrUtil.SafeXmlString(pair.Key), pair => pair.Value.ReadString()), LocaleManager.LocalizedAppContext, false);
                if (totpData.IsTotpEntry)
                {
                    return(totpData);
                }
            }

            return(null);
        }
        public void DisplayAccessNotifications(PwEntryOutput entry, bool closeAfterCreate, string searchUrl)
        {
            var hadKeyboardData = ClearNotifications();

            String entryName = entry.OutputStrings.ReadSafe(PwDefs.TitleField);

            ISharedPreferences prefs = PreferenceManager.GetDefaultSharedPreferences(this);
            var notBuilder           = new PasswordAccessNotificationBuilder(this, _notificationManager);

            if (prefs.GetBoolean(GetString(Resource.String.CopyToClipboardNotification_key), Resources.GetBoolean(Resource.Boolean.CopyToClipboardNotification_default)))
            {
                if (entry.OutputStrings.ReadSafe(PwDefs.PasswordField).Length > 0)
                {
                    notBuilder.AddPasswordAccess();
                }

                if (entry.OutputStrings.ReadSafe(PwDefs.UserNameField).Length > 0)
                {
                    notBuilder.AddUsernameAccess();
                }
            }

            bool hasKeyboardDataNow = false;

            if (prefs.GetBoolean(GetString(Resource.String.UseKp2aKeyboard_key), Resources.GetBoolean(Resource.Boolean.UseKp2aKeyboard_default)))
            {
                //keyboard
                hasKeyboardDataNow = MakeAccessibleForKeyboard(entry, searchUrl);
                if (hasKeyboardDataNow)
                {
                    notBuilder.AddKeyboardAccess();

                    if (closeAfterCreate && Keepass2android.Autofill.AutoFillService.IsAvailable)
                    {
                        if (IsKp2aInputMethodEnabled)
                        {
                            ActivateKeyboardIfAppropriate(closeAfterCreate, prefs);
                        }
                        else if (Keepass2android.Autofill.AutoFillService.IsRunning)
                        {
                            //don't do anything, service is notified
                        }
                        else                         //neither keyboard nor activity service are running/enabled. Ask the user what to do.
                        {
                            var i = new Intent(this, typeof(ActivateAutoFillActivity));
                            i.AddFlags(ActivityFlags.NewTask | ActivityFlags.ClearTask);
                            StartActivity(i);
                            prefs.Edit().PutBoolean("has_asked_autofillservice", true).Commit();
                        }
                    }
                    else
                    {
                        ActivateKeyboardIfAppropriate(closeAfterCreate, prefs);
                    }
                }
            }

            if ((!hasKeyboardDataNow) && (hadKeyboardData))
            {
                ClearKeyboard(true);                 //this clears again and then (this is the point) broadcasts that we no longer have keyboard data
            }
            _numElementsToWaitFor = notBuilder.CreateNotifications(entryName);

            if (_numElementsToWaitFor == 0)
            {
                StopSelf();
                return;
            }

            IntentFilter filter = new IntentFilter();

            filter.AddAction(Intents.CopyUsername);
            filter.AddAction(Intents.CopyPassword);
            filter.AddAction(Intents.CheckKeyboard);

            //register receiver to get notified when notifications are discarded in which case we can shutdown the service
            _notificationDeletedBroadcastReceiver = new NotificationDeletedBroadcastReceiver(this);
            IntentFilter deletefilter = new IntentFilter();

            deletefilter.AddAction(ActionNotificationCancelled);
            RegisterReceiver(_notificationDeletedBroadcastReceiver, deletefilter);
        }
        public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
        {
            Kp2aLog.Log("Received intent to provide access to entry");

            _stopOnLockBroadcastReceiver = new StopOnLockBroadcastReceiver(this);
            IntentFilter filter = new IntentFilter();

            filter.AddAction(Intents.DatabaseLocked);
            RegisterReceiver(_stopOnLockBroadcastReceiver, filter);

            if ((intent.Action == Intents.ShowNotification) || (intent.Action == Intents.UpdateKeyboard))
            {
                String uuidBytes = intent.GetStringExtra(EntryActivity.KeyEntry);
                String searchUrl = intent.GetStringExtra(SearchUrlTask.UrlToSearchKey);

                PwUuid entryId = PwUuid.Zero;
                if (uuidBytes != null)
                {
                    entryId = new PwUuid(MemUtil.HexStringToByteArray(uuidBytes));
                }

                PwEntryOutput entry;
                try
                {
                    if ((App.Kp2a.GetDb().LastOpenedEntry != null) &&
                        (entryId.Equals(App.Kp2a.GetDb().LastOpenedEntry.Uuid)))
                    {
                        entry = App.Kp2a.GetDb().LastOpenedEntry;
                    }
                    else
                    {
                        entry = new PwEntryOutput(App.Kp2a.GetDb().Entries[entryId], App.Kp2a.GetDb().KpDatabase);
                    }
                }
                catch (Exception)
                {
                    //seems like restarting the service happened after closing the DB
                    StopSelf();
                    return(StartCommandResult.NotSticky);
                }

                if (intent.Action == Intents.ShowNotification)
                {
                    //first time opening the entry -> bring up the notifications
                    bool closeAfterCreate = intent.GetBooleanExtra(EntryActivity.KeyCloseAfterCreate, false);
                    DisplayAccessNotifications(entry, closeAfterCreate, searchUrl);
                }
                else                 //UpdateKeyboard
                {
#if !EXCLUDE_KEYBOARD
                    //this action is received when the data in the entry has changed (e.g. by plugins)
                    //update the keyboard data.
                    //Check if keyboard is (still) available
                    if (Keepass2android.Kbbridge.KeyboardData.EntryId == entry.Uuid.ToHexString())
                    {
                        MakeAccessibleForKeyboard(entry, searchUrl);
                    }
#endif
                }
            }
            if (intent.Action == Intents.CopyStringToClipboard)
            {
                TimeoutCopyToClipboard(intent.GetStringExtra(_stringtocopy));
            }
            if (intent.Action == Intents.ActivateKeyboard)
            {
                ActivateKp2aKeyboard();
            }
            if (intent.Action == Intents.ClearNotificationsAndData)
            {
                ClearNotifications();
            }


            return(StartCommandResult.RedeliverIntent);
        }
예제 #9
0
        public void DisplayAccessNotifications(PwEntryOutput entry, bool closeAfterCreate, string searchUrl)
        {
            var hadKeyboardData = ClearNotifications();

            String   entryName = entry.OutputStrings.ReadSafe(PwDefs.TitleField);
            Database db        = App.Kp2a.FindDatabaseForElement(entry.Entry);

            var bmp = Util.DrawableToBitmap(db.DrawableFactory.GetIconDrawable(this,
                                                                               db.KpDatabase, entry.Entry.IconId, entry.Entry.CustomIconUuid, false));


            if (!(((entry.Entry.CustomIconUuid != null) && (!entry.Entry.CustomIconUuid.Equals(PwUuid.Zero)))) &&
                PreferenceManager.GetDefaultSharedPreferences(this).GetString("IconSetKey", PackageName) == PackageName)
            {
                Color drawingColor = new Color(189, 189, 189);
                bmp = Util.ChangeImageColor(bmp, drawingColor);
            }

            Bitmap entryIcon = Util.MakeLargeIcon(bmp, this);

            ISharedPreferences prefs = PreferenceManager.GetDefaultSharedPreferences(this);
            var notBuilder           = new PasswordAccessNotificationBuilder(this, _notificationManager);

            if (prefs.GetBoolean(GetString(Resource.String.CopyToClipboardNotification_key), Resources.GetBoolean(Resource.Boolean.CopyToClipboardNotification_default)))
            {
                if (entry.OutputStrings.ReadSafe(PwDefs.PasswordField).Length > 0)
                {
                    notBuilder.AddPasswordAccess();
                }

                if (entry.OutputStrings.ReadSafe(PwDefs.UserNameField).Length > 0)
                {
                    notBuilder.AddUsernameAccess();
                }
            }

            bool hasKeyboardDataNow = false;

            if (prefs.GetBoolean(GetString(Resource.String.UseKp2aKeyboard_key), Resources.GetBoolean(Resource.Boolean.UseKp2aKeyboard_default)))
            {
                //keyboard
                hasKeyboardDataNow = MakeAccessibleForKeyboard(entry, searchUrl);
                if (hasKeyboardDataNow)
                {
                    notBuilder.AddKeyboardAccess();
                    if (prefs.GetBoolean("kp2a_switch_rooted", false))
                    {
                        //switch rooted
                        bool onlySwitchOnSearch = prefs.GetBoolean(GetString(Resource.String.OpenKp2aKeyboardAutomaticallyOnlyAfterSearch_key), false);
                        if (closeAfterCreate || (!onlySwitchOnSearch))
                        {
                            ActivateKp2aKeyboard();
                        }
                    }
                    else
                    {
                        //if the app is about to be closed again (e.g. after searching for a URL and returning to the browser:
                        // automatically bring up the Keyboard selection dialog
                        if ((closeAfterCreate) && prefs.GetBoolean(GetString(Resource.String.OpenKp2aKeyboardAutomatically_key), Resources.GetBoolean(Resource.Boolean.OpenKp2aKeyboardAutomatically_default)))
                        {
                            ActivateKp2aKeyboard();
                        }
                    }
                }
            }

            if ((!hasKeyboardDataNow) && (hadKeyboardData))
            {
                ClearKeyboard(true); //this clears again and then (this is the point) broadcasts that we no longer have keyboard data
            }
            _numElementsToWaitFor = notBuilder.CreateNotifications(entryName, entryIcon);

            if (_numElementsToWaitFor == 0)
            {
                StopSelf();
                return;
            }

            //register receiver to get notified when notifications are discarded in which case we can shutdown the service
            _notificationDeletedBroadcastReceiver = new NotificationDeletedBroadcastReceiver(this);
            IntentFilter deletefilter = new IntentFilter();

            deletefilter.AddAction(ActionNotificationCancelled);
            RegisterReceiver(_notificationDeletedBroadcastReceiver, deletefilter);
        }
예제 #10
0
        bool MakeAccessibleForKeyboard(PwEntryOutput entry)
        {
            #if EXCLUDE_KEYBOARD
            return false;
            #else
            bool hasData = false;
            Keepass2android.Kbbridge.KeyboardDataBuilder kbdataBuilder = new Keepass2android.Kbbridge.KeyboardDataBuilder();

            String[] keys = {PwDefs.UserNameField,
                PwDefs.PasswordField,
                PwDefs.UrlField,
                PwDefs.NotesField,
                PwDefs.TitleField
            };
            int[] resIds = {Resource.String.entry_user_name,
                Resource.String.entry_password,
                Resource.String.entry_url,
                Resource.String.entry_comment,
                Resource.String.entry_title };

            //add standard fields:
            int i=0;
            foreach (string key in keys)
            {
                String value = entry.OutputStrings.ReadSafe(key);

                if (value.Length > 0)
                {
                    kbdataBuilder.AddString(key, GetString(resIds[i]), value);
                    hasData = true;
                }
                i++;
            }
            //add additional fields:
            foreach (var pair in entry.OutputStrings)
            {
                var key = pair.Key;
                var value = pair.Value.ReadString();

                if (!PwDefs.IsStandardField(key)) {
                    kbdataBuilder.AddString(pair.Key, pair.Key, value);
                    hasData = true;
                }
            }

            kbdataBuilder.Commit();
            Keepass2android.Kbbridge.KeyboardData.EntryName = entry.OutputStrings.ReadSafe(PwDefs.TitleField);
            Keepass2android.Kbbridge.KeyboardData.EntryId = entry.Uuid.ToHexString();

            return hasData;
            #endif
        }
예제 #11
0
        public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
        {
            Kp2aLog.Log("Received intent to provide access to entry");

            _stopOnLockBroadcastReceiver = new StopOnLockBroadcastReceiver(this);
            IntentFilter filter = new IntentFilter();
            filter.AddAction(Intents.DatabaseLocked);
            RegisterReceiver(_stopOnLockBroadcastReceiver, filter);

            if ((intent.Action == Intents.ShowNotification) || (intent.Action == Intents.UpdateKeyboard))
            {
                String uuidBytes = intent.GetStringExtra(EntryActivity.KeyEntry);

                PwUuid entryId = PwUuid.Zero;
                if (uuidBytes != null)
                    entryId = new PwUuid(MemUtil.HexStringToByteArray(uuidBytes));

                PwEntryOutput entry;
                try
                {
                    if ((App.Kp2a.GetDb().LastOpenedEntry != null)
                        && (entryId.Equals(App.Kp2a.GetDb().LastOpenedEntry.Uuid)))
                    {
                        entry = App.Kp2a.GetDb().LastOpenedEntry;
                    }
                    else
                    {
                        entry = new PwEntryOutput(App.Kp2a.GetDb().Entries[entryId], App.Kp2a.GetDb().KpDatabase);
                    }

                }
                catch (Exception)
                {
                    //seems like restarting the service happened after closing the DB
                    StopSelf();
                    return StartCommandResult.NotSticky;
                }

                if (intent.Action == Intents.ShowNotification)
                {
                    //first time opening the entry -> bring up the notifications
                    bool closeAfterCreate = intent.GetBooleanExtra(EntryActivity.KeyCloseAfterCreate, false);
                    DisplayAccessNotifications(entry, closeAfterCreate);
                }
                else //UpdateKeyboard
                {
            #if !EXCLUDE_KEYBOARD
                    //this action is received when the data in the entry has changed (e.g. by plugins)
                    //update the keyboard data.
                    //Check if keyboard is (still) available
                    if (Keepass2android.Kbbridge.KeyboardData.EntryId == entry.Uuid.ToHexString())
                        MakeAccessibleForKeyboard(entry);
            #endif
                }
            }
            if (intent.Action == Intents.CopyStringToClipboard)
            {

                TimeoutCopyToClipboard(intent.GetStringExtra(_stringtocopy));
            }
            if (intent.Action == Intents.ActivateKeyboard)
            {
                ActivateKp2aKeyboard();
            }
            if (intent.Action == Intents.ClearNotificationsAndData)
            {
                ClearNotifications();
            }

            return StartCommandResult.RedeliverIntent;
        }
예제 #12
0
        public void DisplayAccessNotifications(PwEntryOutput entry, bool closeAfterCreate)
        {
            var hadKeyboardData = ClearNotifications();

            String entryName = entry.OutputStrings.ReadSafe(PwDefs.TitleField);

            ISharedPreferences prefs = PreferenceManager.GetDefaultSharedPreferences(this);
            var notBuilder = new PasswordAccessNotificationBuilder(this, _notificationManager);
            if (prefs.GetBoolean(GetString(Resource.String.CopyToClipboardNotification_key), Resources.GetBoolean(Resource.Boolean.CopyToClipboardNotification_default)))
            {

                if (entry.OutputStrings.ReadSafe(PwDefs.PasswordField).Length > 0)
                {
                    notBuilder.AddPasswordAccess();

                }

                if (entry.OutputStrings.ReadSafe(PwDefs.UserNameField).Length > 0)
                {
                    notBuilder.AddUsernameAccess();
                }
            }

            bool hasKeyboardDataNow = false;
            if (prefs.GetBoolean(GetString(Resource.String.UseKp2aKeyboard_key), Resources.GetBoolean(Resource.Boolean.UseKp2aKeyboard_default)))
            {

                //keyboard
                hasKeyboardDataNow = MakeAccessibleForKeyboard(entry);
                if (hasKeyboardDataNow)
                {
                    notBuilder.AddKeyboardAccess();
                    if (prefs.GetBoolean("kp2a_switch_rooted", false))
                    {
                        //switch rooted
                        bool onlySwitchOnSearch = prefs.GetBoolean(GetString(Resource.String.OpenKp2aKeyboardAutomaticallyOnlyAfterSearch_key), false);
                        if (closeAfterCreate || (!onlySwitchOnSearch))
                        {
                            ActivateKp2aKeyboard();
                        }
                    }
                    else
                    {
                        //if the app is about to be closed again (e.g. after searching for a URL and returning to the browser:
                        // automatically bring up the Keyboard selection dialog
                        if ((closeAfterCreate) && prefs.GetBoolean(GetString(Resource.String.OpenKp2aKeyboardAutomatically_key), Resources.GetBoolean(Resource.Boolean.OpenKp2aKeyboardAutomatically_default)))
                        {
                            ActivateKp2aKeyboard();
                        }
                    }

                }

            }

            if ((!hasKeyboardDataNow) && (hadKeyboardData))
            {
                ClearKeyboard(true); //this clears again and then (this is the point) broadcasts that we no longer have keyboard data
            }
            _numElementsToWaitFor = notBuilder.CreateNotifications(entryName);

            if (_numElementsToWaitFor == 0)
            {
                StopSelf();
                return;
            }

            IntentFilter filter = new IntentFilter();
            filter.AddAction(Intents.CopyUsername);
            filter.AddAction(Intents.CopyPassword);
            filter.AddAction(Intents.CheckKeyboard);

            //register receiver to get notified when notifications are discarded in which case we can shutdown the service
            _notificationDeletedBroadcastReceiver = new NotificationDeletedBroadcastReceiver(this);
            IntentFilter deletefilter = new IntentFilter();
            deletefilter.AddAction(ActionNotificationCancelled);
            RegisterReceiver(_notificationDeletedBroadcastReceiver, deletefilter);
        }
        public void DisplayAccessNotifications(PwEntryOutput entry, bool closeAfterCreate, string searchUrl)
        {
            var hadKeyboardData = ClearNotifications();

            String entryName = entry.OutputStrings.ReadSafe(PwDefs.TitleField);

            ISharedPreferences prefs = PreferenceManager.GetDefaultSharedPreferences(this);
            var notBuilder           = new PasswordAccessNotificationBuilder(this, _notificationManager);

            if (prefs.GetBoolean(GetString(Resource.String.CopyToClipboardNotification_key), Resources.GetBoolean(Resource.Boolean.CopyToClipboardNotification_default)))
            {
                if (entry.OutputStrings.ReadSafe(PwDefs.PasswordField).Length > 0)
                {
                    notBuilder.AddPasswordAccess();
                }

                if (entry.OutputStrings.ReadSafe(PwDefs.UserNameField).Length > 0)
                {
                    notBuilder.AddUsernameAccess();
                }
            }

            bool hasKeyboardDataNow = false;

            if (prefs.GetBoolean(GetString(Resource.String.UseKp2aKeyboard_key), Resources.GetBoolean(Resource.Boolean.UseKp2aKeyboard_default)))
            {
                //keyboard
                hasKeyboardDataNow = MakeAccessibleForKeyboard(entry, searchUrl);
                if (hasKeyboardDataNow)
                {
                    notBuilder.AddKeyboardAccess();
                    if (prefs.GetBoolean("kp2a_switch_rooted", false))
                    {
                        //switch rooted
                        bool onlySwitchOnSearch = prefs.GetBoolean(GetString(Resource.String.OpenKp2aKeyboardAutomaticallyOnlyAfterSearch_key), false);
                        if (closeAfterCreate || (!onlySwitchOnSearch))
                        {
                            ActivateKp2aKeyboard();
                        }
                    }
                    else
                    {
                        //if the app is about to be closed again (e.g. after searching for a URL and returning to the browser:
                        // automatically bring up the Keyboard selection dialog
                        if ((closeAfterCreate) && prefs.GetBoolean(GetString(Resource.String.OpenKp2aKeyboardAutomatically_key), Resources.GetBoolean(Resource.Boolean.OpenKp2aKeyboardAutomatically_default)))
                        {
                            ActivateKp2aKeyboard();
                        }
                    }
                }
            }

            if ((!hasKeyboardDataNow) && (hadKeyboardData))
            {
                ClearKeyboard(true);                 //this clears again and then (this is the point) broadcasts that we no longer have keyboard data
            }
            _numElementsToWaitFor = notBuilder.CreateNotifications(entryName);

            if (_numElementsToWaitFor == 0)
            {
                StopSelf();
                return;
            }

            IntentFilter filter = new IntentFilter();

            filter.AddAction(Intents.CopyUsername);
            filter.AddAction(Intents.CopyPassword);
            filter.AddAction(Intents.CheckKeyboard);

            //register receiver to get notified when notifications are discarded in which case we can shutdown the service
            _notificationDeletedBroadcastReceiver = new NotificationDeletedBroadcastReceiver(this);
            IntentFilter deletefilter = new IntentFilter();

            deletefilter.AddAction(ActionNotificationCancelled);
            RegisterReceiver(_notificationDeletedBroadcastReceiver, deletefilter);
        }
        public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
        {
            Kp2aLog.Log("Received intent to provide access to entry");

            if (_stopOnLockBroadcastReceiver == null)
            {
                _stopOnLockBroadcastReceiver = new StopOnLockBroadcastReceiver(this);
                IntentFilter filter = new IntentFilter();
                filter.AddAction(Intents.DatabaseLocked);
                RegisterReceiver(_stopOnLockBroadcastReceiver, filter);
            }

            if ((intent.Action == Intents.ShowNotification) || (intent.Action == Intents.UpdateKeyboard))
            {
                String entryId   = intent.GetStringExtra(EntryActivity.KeyEntry);
                String searchUrl = intent.GetStringExtra(SearchUrlTask.UrlToSearchKey);

                if (entryId == null)
                {
                    Kp2aLog.Log("received intent " + intent.Action + " without KeyEntry!");
#if DEBUG
                    throw new Exception("invalid intent received!");
#endif
                    return(StartCommandResult.NotSticky);
                }


                PwEntryOutput entry;
                try
                {
                    ElementAndDatabaseId fullId = new ElementAndDatabaseId(entryId);


                    if (((App.Kp2a.LastOpenedEntry != null) &&
                         (fullId.ElementId.Equals(App.Kp2a.LastOpenedEntry.Uuid))))
                    {
                        entry = App.Kp2a.LastOpenedEntry;
                    }
                    else
                    {
                        Database entryDb = App.Kp2a.GetDatabase(fullId.DatabaseId);
                        entry = new PwEntryOutput(entryDb.EntriesById[fullId.ElementId], entryDb);
                    }
                }
                catch (Exception e)
                {
                    Kp2aLog.LogUnexpectedError(e);
                    //seems like restarting the service happened after closing the DB
                    StopSelf();
                    return(StartCommandResult.NotSticky);
                }

                if (intent.Action == Intents.ShowNotification)
                {
                    //first time opening the entry -> bring up the notifications
                    bool activateKeyboard = intent.GetBooleanExtra(EntryActivity.KeyActivateKeyboard, false);
                    DisplayAccessNotifications(entry, activateKeyboard, searchUrl);
                }
                else //UpdateKeyboard
                {
#if !EXCLUDE_KEYBOARD
                    //this action is received when the data in the entry has changed (e.g. by plugins)
                    //update the keyboard data.
                    //Check if keyboard is (still) available
                    if (Keepass2android.Kbbridge.KeyboardData.EntryId == entry.Uuid.ToHexString())
                    {
                        MakeAccessibleForKeyboard(entry, searchUrl);
                    }
#endif
                }
            }
            if (intent.Action == Intents.CopyStringToClipboard)
            {
                TimeoutCopyToClipboard(intent.GetStringExtra(_stringtocopy));
            }
            if (intent.Action == Intents.ActivateKeyboard)
            {
                ActivateKp2aKeyboard();
            }
            if (intent.Action == Intents.ClearNotificationsAndData)
            {
                ClearNotifications();
            }


            return(StartCommandResult.RedeliverIntent);
        }