From c050d4a502de390d2b973a09079d70d4fc26803e Mon Sep 17 00:00:00 2001 From: Ernest Borowski Date: Wed, 28 Sep 2022 15:22:04 +0200 Subject: [PATCH] Add Settings Certificates UI. This project has two subprojects: 1. SettingCertificates that has actual widget code and Interop API. 2. SettingView that has aplication for launching this widget, it is just for debugging purposes and should be not packaged in release build. To test it: 1. Install tpk file from packaging dir 2. Open sln in Visual Studio, build and launch project. When there is code change in "SettingsCertificates" subproject: 1. Build SettingsCertificates subproject 2. Install it on the device using sdb: sdb install ./SettingCertificates/SettingCertificates/bin/Release/tizen10.0/org.tizen.cssetting-certificates-1.0.0.tpk 3. Launch SettingView using: Visual Studio -> Debug -> Start Without Debugging Change-Id: I92510e1ec1deeccd5043cbda971b58021ae9e65b Signed-off-by: Ernest Borowski --- .../ItemLayout/ILCheckLabel.cs | 56 --- .../ItemLayout/ILIconLabel.cs | 62 --- .../ItemLayout/ILLabelSlider.cs | 56 --- .../ItemLayout/ItemLayout.cs | 198 -------- .../SettingCertificates/ListItem.cs | 44 -- .../SettingCertificates.cs | 40 +- .../SettingCertificates.csproj | 24 + .../SettingWidget_AboutDevice.cs | 34 -- .../SettingCertificates/SettingWidget_Base.cs | 182 ------- .../SettingWidget_MainMenu.cs | 56 --- .../WidgetSettingCertificates.cs | 444 ++++++++++++++++++ .../api/Interop/Interop.CertSvc.cs | 326 +++++++++++++ .../api/Interop/Interop.Libraries.cs | 23 + .../res/locale/Resource.Designer.cs | 228 +++++++++ .../res/locale/Resources.Designer.cs | 243 ++++++++++ .../res/locale/Resources.en.Designer.cs | 63 +++ .../res/locale/Resources.en.resx | 180 +++++++ .../res/locale/Resources.ko-KR.resx | 180 +++++++ .../res/locale/Resources.pl.resx | 180 +++++++ .../res/locale/Resources.resx | 180 +++++++ .../SettingCertificates/tizen-manifest.xml | 26 +- .../SettingView/SettingView.cs | 25 +- .../SettingView/SettingViewBorder.cs | 20 +- .../SettingView/tizen-manifest.xml | 2 +- ...rg.tizen.cssetting-certificates-1.0.0.tpk} | Bin 90002 -> 115510 bytes packaging/org.tizen.setting-certificates.spec | 4 +- 26 files changed, 2147 insertions(+), 729 deletions(-) delete mode 100644 SettingCertificates/SettingCertificates/ItemLayout/ILCheckLabel.cs delete mode 100644 SettingCertificates/SettingCertificates/ItemLayout/ILIconLabel.cs delete mode 100644 SettingCertificates/SettingCertificates/ItemLayout/ILLabelSlider.cs delete mode 100644 SettingCertificates/SettingCertificates/ItemLayout/ItemLayout.cs delete mode 100644 SettingCertificates/SettingCertificates/ListItem.cs delete mode 100644 SettingCertificates/SettingCertificates/SettingWidget_AboutDevice.cs delete mode 100644 SettingCertificates/SettingCertificates/SettingWidget_Base.cs delete mode 100644 SettingCertificates/SettingCertificates/SettingWidget_MainMenu.cs create mode 100644 SettingCertificates/SettingCertificates/WidgetSettingCertificates.cs create mode 100644 SettingCertificates/SettingCertificates/api/Interop/Interop.CertSvc.cs create mode 100644 SettingCertificates/SettingCertificates/api/Interop/Interop.Libraries.cs create mode 100644 SettingCertificates/SettingCertificates/res/locale/Resource.Designer.cs create mode 100644 SettingCertificates/SettingCertificates/res/locale/Resources.Designer.cs create mode 100644 SettingCertificates/SettingCertificates/res/locale/Resources.en.Designer.cs create mode 100644 SettingCertificates/SettingCertificates/res/locale/Resources.en.resx create mode 100644 SettingCertificates/SettingCertificates/res/locale/Resources.ko-KR.resx create mode 100644 SettingCertificates/SettingCertificates/res/locale/Resources.pl.resx create mode 100644 SettingCertificates/SettingCertificates/res/locale/Resources.resx rename packaging/{org.tizen.setting-certificates-1.0.0.tpk => org.tizen.cssetting-certificates-1.0.0.tpk} (58%) diff --git a/SettingCertificates/SettingCertificates/ItemLayout/ILCheckLabel.cs b/SettingCertificates/SettingCertificates/ItemLayout/ILCheckLabel.cs deleted file mode 100644 index 2527f63..0000000 --- a/SettingCertificates/SettingCertificates/ItemLayout/ILCheckLabel.cs +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using Tizen.NUI; -using Tizen.NUI.BaseComponents; - -/* - * The Item Layout has two modes depending on the number of text labels inserted into it. - * Structure is depicted below. - * - * +------------------------------------------------------------------------+ ------ - * | | -> Item Margin - * | +------+ +--------------------------------------------------------+ | ------ - * | | | | | | - * | |CHECK | | TITLE | | - * | | | | | | - * | +------+ +--------------------------------------------------------+ | - * +------------------------------------------------------------------------+ - * | | - * | | - * | | - * Text Left Margin - * | | - * Text Right Margin - * - * +------------------------------------------------------------------------------+------- - * | +-------------------------------------------------------------+ | - * | +-------+ | TITLE | | Description Top Margin - * | | | | | | - * | |CHECK | +-------------------------------------------------------------+ | - * | | | +-------------------------------------------------------------+ |------- - * | +-------+ | DESCRIPTION | | - * | | | | - * | +-------------------------------------------------------------+ | - * +------------------------------------------------------------------------------+ -*/ - -namespace SettingMain -{ - internal class ILCheckLabel : ItemLayout - { - } -} diff --git a/SettingCertificates/SettingCertificates/ItemLayout/ILIconLabel.cs b/SettingCertificates/SettingCertificates/ItemLayout/ILIconLabel.cs deleted file mode 100644 index 09dc080..0000000 --- a/SettingCertificates/SettingCertificates/ItemLayout/ILIconLabel.cs +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using Tizen.NUI; -using Tizen.NUI.BaseComponents; - -/* - * The Item Layout has two modes depending on the number of text labels inserted into it. - * Structure is depicted below. - * - * +------------------------------------------------------------------------+ ------ - * | | -> Item Margin - * | +------+ +--------------------------------------------------------+ | ------ - * | | | | | | - * | | ICON | | TITLE | | - * | | | | | | - * | +------+ +--------------------------------------------------------+ | - * +------------------------------------------------------------------------+ - * | | - * | | - * | | - * Text Left Margin - * | | - * Text Right Margin - * - * +------------------------------------------------------------------------------+------- - * | +-------------------------------------------------------------+ | - * | +-------+ | TITLE | | Description Top Margin - * | | | | | | - * | | ICON | +-------------------------------------------------------------+ | - * | | | +-------------------------------------------------------------+ |------- - * | +-------+ | DESCRIPTION | | - * | | | | - * | +-------------------------------------------------------------+ | - * +------------------------------------------------------------------------------+ -*/ - -namespace SettingMain -{ - /// - /// The custom layout sample implementation. This class creates layout for Item Object as it is depicted above. - /// The custom layout must be derived from LayoutGroup and override the two methods, OnMeasure and OnLayout. - /// OnMeasure and OnLayout methods must be extended and called during the measuring and layout phases respectively. - /// - internal class ILIconLabel : ItemLayout - { - } - -} diff --git a/SettingCertificates/SettingCertificates/ItemLayout/ILLabelSlider.cs b/SettingCertificates/SettingCertificates/ItemLayout/ILLabelSlider.cs deleted file mode 100644 index c99d523..0000000 --- a/SettingCertificates/SettingCertificates/ItemLayout/ILLabelSlider.cs +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using Tizen.NUI; -using Tizen.NUI.BaseComponents; - -/* - * The Item Layout has two modes depending on the number of text labels inserted into it. - * Structure is depicted below. - * - * +------------------------------------------------------------------------+ ------ - * | | -> Item Margin - * | +------+ +--------------------------------------------------------+ | ------ - * | | | | | | - * | | | | TITLE | | - * | | | | | | - * | +------+ +--------------------------------------------------------+ | - * +------------------------------------------------------------------------+ - * | | - * | | - * | | - * Text Left Margin - * | | - * Text Right Margin - * - * +------------------------------------------------------------------------------+------- - * | +-------------------------------------------------------------+ | - * | +-------+ | TITLE | | Description Top Margin - * | | | | | | - * | | | +-------------------------------------------------------------+ | - * | | | +-------------------------------------------------------------+ |------- - * | +-------+ | SLIDER | | - * | | | | - * | +-------------------------------------------------------------+ | - * +------------------------------------------------------------------------------+ -*/ - -namespace SettingMain -{ - internal class ILLabelSlider : ItemLayout - { - } -} diff --git a/SettingCertificates/SettingCertificates/ItemLayout/ItemLayout.cs b/SettingCertificates/SettingCertificates/ItemLayout/ItemLayout.cs deleted file mode 100644 index 07281ef..0000000 --- a/SettingCertificates/SettingCertificates/ItemLayout/ItemLayout.cs +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using Tizen.NUI; -using Tizen.NUI.BaseComponents; -using Tizen.NUI.Components; - -/* - * The Item Layout has two modes depending on the number of text labels inserted into it. - * Structure is depicted below. - * - * +------------------------------------------------------------------------+ ------ - * | | -> Item Margin - * | +------+ +--------------------------------------------------------+ | ------ - * | | | | | | - * | | ICON | | TITLE | | - * | | | | | | - * | +------+ +--------------------------------------------------------+ | - * +------------------------------------------------------------------------+ - * | | - * | | - * | | - * Text Left Margin - * | | - * Text Right Margin - * - * +------------------------------------------------------------------------------+------- - * | +-------------------------------------------------------------+ | - * | +-------+ | TITLE | | Description Top Margin - * | | | | | | - * | | ICON | +-------------------------------------------------------------+ | - * | | | +-------------------------------------------------------------+ |------- - * | +-------+ | DESCRIPTION | | - * | | | | - * | +-------------------------------------------------------------+ | - * +------------------------------------------------------------------------------+ -*/ - -namespace SettingMain -{ - /// - /// The custom layout sample implementation. This class creates layout for Item Object as it is depicted above. - /// The custom layout must be derived from LayoutGroup and override the two methods, OnMeasure and OnLayout. - /// OnMeasure and OnLayout methods must be extended and called during the measuring and layout phases respectively. - /// - internal class ItemLayout : LayoutGroup - { - /// - /// Top margin of item contents. - /// - private const int ItemMargin = 5; - - /// - /// Point where Description and Title begins. - /// - private const int TextLeftMargin = 120; - - /// - /// Point where Description and Title ends. - /// - private const int TextRightMargin = 710; - - /// - /// Vertical Description margin. - /// - private const int DescriptionTopMargin = 70; - - /// - /// Height of a text object. - /// - private const int TextHeight = 50; - - /// - /// Function calculates the layout size requirements using parent width and height measure specifications. - /// - /// Parent width measure specification - /// Parent height measure specification - protected override void OnMeasure(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec) - { - var itemWidth = new LayoutLength(0); - var itemHeight = new LayoutLength(0); - var iconHeight = new LayoutLength(0); - - float labelMaxWidth = 0; - - //All layout items have to be measured to calculate Item width and height - foreach (LayoutItem childLayout in LayoutChildren) - { - if (childLayout != null) - { - //Set widthMEasureSpecification and HeightMeasureSpecification for children - MeasureChild(childLayout, widthMeasureSpec, heightMeasureSpec); - - //Item size depends of the content. If item contains descrpitoin height of the item is different. - if (childLayout.Owner is TextLabel) - { - itemHeight += childLayout.MeasuredHeight.Size; - - if (childLayout.MeasuredWidth.Size.AsRoundedValue() > labelMaxWidth) - { - labelMaxWidth = childLayout.MeasuredWidth.Size.AsRoundedValue(); - } - } - else if (childLayout.Owner is CheckBox) - { - itemHeight += childLayout.MeasuredHeight.Size; - - if (childLayout.MeasuredWidth.Size.AsRoundedValue() > labelMaxWidth) - { - labelMaxWidth = childLayout.MeasuredWidth.Size.AsRoundedValue(); - } - } - else if (childLayout.Owner is Slider) - { - itemHeight += childLayout.MeasuredHeight.Size * 2; - - if (childLayout.MeasuredWidth.Size.AsRoundedValue() > labelMaxWidth) - { - labelMaxWidth = childLayout.MeasuredWidth.Size.AsRoundedValue(); - } - } - else - { - itemWidth += childLayout.MeasuredWidth.Size; - iconHeight = childLayout.MeasuredHeight.Size; - } - - //update item width by maximum label widht - itemWidth += new LayoutLength(labelMaxWidth); - } - } - - if (iconHeight.AsRoundedValue() > itemHeight.AsRoundedValue()) - { - itemHeight = iconHeight; - } - - // Finally, call this method to set the dimensions we would like - SetMeasuredDimensions(new MeasuredSize(itemWidth, MeasuredSize.StateType.MeasuredSizeOK), - new MeasuredSize(itemHeight, MeasuredSize.StateType.MeasuredSizeOK)); - } - - /// - /// Laying out and positioning the children within View itself using their measured sizes. - /// - /// This is a new size or position for this layout. - /// Left position, relative to parent. - /// Top position, relative to parent. - /// Right position, relative to parent. - /// Bottom position, relative to parent. - protected override void OnLayout(bool changed, LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom) - { - //Size have to be calculated for all childrens. - foreach (LayoutItem childLayout in LayoutChildren) - { - //Layout owner name is used to set valid size values - if (childLayout.Owner.Name == Program.ItemContentNameIcon) - { - LayoutLength width = childLayout.MeasuredWidth.Size; - LayoutLength height = childLayout.MeasuredHeight.Size; - - childLayout.Layout(new LayoutLength(ItemMargin), - new LayoutLength(ItemMargin), - width + ItemMargin, - height + ItemMargin); - } - else if (childLayout.Owner.Name == Program.ItemContentNameTitle) - { - childLayout.Layout(new LayoutLength(TextLeftMargin), - new LayoutLength(ItemMargin), - new LayoutLength(TextRightMargin), - new LayoutLength(TextHeight + ItemMargin)); - } - else if (childLayout.Owner.Name == Program.ItemContentNameDescription) - { - childLayout.Layout(new LayoutLength(TextLeftMargin), - new LayoutLength(DescriptionTopMargin), - new LayoutLength(TextRightMargin), - new LayoutLength(DescriptionTopMargin + TextHeight + 3 * ItemMargin)); - } - } - } - - } -} diff --git a/SettingCertificates/SettingCertificates/ListItem.cs b/SettingCertificates/SettingCertificates/ListItem.cs deleted file mode 100644 index 1beb759..0000000 --- a/SettingCertificates/SettingCertificates/ListItem.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace SettingMain -{ - public class ListItem - { - private readonly int ItemType = 0; - private readonly string Path = null; - private readonly string Label = null; - private readonly string Description = null; - - public ListItem(int type, string path, string label, string description = "") - { - ItemType = type; - Path = path; - Label = label; - Description = description; - } - - - public int GetItemType() - { - return ItemType; - } - public string GetPath() - { - return Path; - } - - public string GetLabel() - { - return Label; - } - - public string GetDescription() - { - return Description; - } - }; -} diff --git a/SettingCertificates/SettingCertificates/SettingCertificates.cs b/SettingCertificates/SettingCertificates/SettingCertificates.cs index 0bcea6c..0a49932 100644 --- a/SettingCertificates/SettingCertificates/SettingCertificates.cs +++ b/SettingCertificates/SettingCertificates/SettingCertificates.cs @@ -1,20 +1,29 @@ -using System; -using System.ComponentModel; -using System.Diagnostics; +/* + * Copyright (c) 2022 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +using System; using System.Collections.Generic; // for Dictionary using Tizen.NUI; -using Tizen.NUI.BaseComponents; -using Tizen.NUI.Components; -using Tizen.Applications; -namespace SettingMain + +namespace SettingCertificates { public class Program : NUIWidgetApplication { - - public static readonly string ItemContentNameIcon = "ItemIcon"; - public static readonly string ItemContentNameTitle = "ItemTitle"; - public static readonly string ItemContentNameDescription = "ItemDescription"; + internal static readonly string LogTag = "SettingMain.Program"; public Program(Dictionary widgetSet) : base(widgetSet) { @@ -24,6 +33,7 @@ namespace SettingMain protected override void OnCreate() { base.OnCreate(); + Tizen.Log.Debug(LogTag, "OnCreate SettingMain"); } public void OnKeyEvent(object sender, Window.KeyEventArgs e) @@ -36,9 +46,11 @@ namespace SettingMain static void Main(string[] args) { - Dictionary widgetSet = new Dictionary(); - widgetSet.Add(typeof(SettingWidget_MainMenu), "main@org.tizen.SettingMain"); - //widgetSet.Add(typeof(SettingWidget_AboutDevice), "aboutdevice@org.tizen.SettingMain"); + Tizen.Log.Debug(LogTag, "Main SettingMain"); + Dictionary widgetSet = new Dictionary + { + { typeof(WidgetSettingCertificates), "certificates@org.tizen.cssetting-certificates" } + }; var app = new Program(widgetSet); app.Run(args); } diff --git a/SettingCertificates/SettingCertificates/SettingCertificates.csproj b/SettingCertificates/SettingCertificates/SettingCertificates.csproj index d37fb42..c68b57f 100644 --- a/SettingCertificates/SettingCertificates/SettingCertificates.csproj +++ b/SettingCertificates/SettingCertificates/SettingCertificates.csproj @@ -26,5 +26,29 @@ + + + + True + True + Resources.resx + + + True + True + Resources.en.resx + + + + + + ResXFileCodeGenerator + Resources.en.Designer.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + + diff --git a/SettingCertificates/SettingCertificates/SettingWidget_AboutDevice.cs b/SettingCertificates/SettingCertificates/SettingWidget_AboutDevice.cs deleted file mode 100644 index 3dbacf4..0000000 --- a/SettingCertificates/SettingCertificates/SettingWidget_AboutDevice.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using System.ComponentModel; -using System.Diagnostics; -using System.Collections.Generic; // for Dictionary -using Tizen.NUI; -using Tizen.NUI.BaseComponents; -using Tizen.NUI.Components; -using Tizen.Applications; - -namespace SettingMain -{ - class SettingWidget_AboutDevice : SettingWidget_Base - { - private static readonly ListItem[] listItems = - { - new ListItem(1, SETTING_LIST_ICON_PATH_CFG+"sett_manage_cert_active_Default.png", "Manage certificate", ""), - new ListItem(1, SETTING_LIST_ICON_PATH_CFG+"sett_legal_infot_active_Default.png", "Legal infomation", ""), - new ListItem(1, "", "Device Info", ""), - new ListItem(1, "", "Name", "Tizen"), - new ListItem(1, "", "Model number", "rpi3"), - new ListItem(1, "", "Tizen version", "TIZEN 6.5"), - new ListItem(1, "", "CPU", "BCM2837"), - new ListItem(1, "", "RAM", "4.0GB"), - new ListItem(1, "", "Resolution", "1280 x 720"), - new ListItem(1, "", "Status", "show network status and other infomation."), - }; - - public SettingWidget_AboutDevice() - : base(listItems) - { - Tizen.Log.Error("SettingWidget", "AboutDevice \n"); - } - } -} diff --git a/SettingCertificates/SettingCertificates/SettingWidget_Base.cs b/SettingCertificates/SettingCertificates/SettingWidget_Base.cs deleted file mode 100644 index 7b28886..0000000 --- a/SettingCertificates/SettingCertificates/SettingWidget_Base.cs +++ /dev/null @@ -1,182 +0,0 @@ -using System; -using System.ComponentModel; -using System.Diagnostics; -using System.Collections.Generic; -using Tizen.NUI; -using Tizen.NUI.BaseComponents; -using Tizen.NUI.Components; -using Tizen.Applications; - -namespace SettingMain -{ - class SettingWidget_Base : Widget - { - private static readonly string resPath = Tizen.Applications.Application.Current.DirectoryInfo.Resource; - protected const string SETTING_LIST_ICON_PATH_CFG = "/list_icon/"; - protected ListItem[] mListItems; - - public SettingWidget_Base(ListItem[] listItems) - : base() - { - Tizen.Log.Error("SettingWidget", "SettingWidget_Base \n"); - mListItems = listItems; - } - protected override void OnCreate(string contentInfo, Window window) - { - Bundle bundle = Bundle.Decode(contentInfo); - - mRootView = new View(); - mRootView.BackgroundColor = Color.White; - mRootView.Size2D = window.Size; - mRootView.PivotPoint = PivotPoint.Center; - window.GetDefaultLayer().Add(mRootView); - - CreateVerticalScrollableBase(window); - - } - private void CreateVerticalScrollableBase(Window window) - { - verticalScrollableBase = new ScrollableBase() - { - ScrollingDirection = ScrollableBase.Direction.Vertical, - WidthSpecification = LayoutParamPolicies.MatchParent, - HeightSpecification = LayoutParamPolicies.MatchParent, - HideScrollbar = false, - }; - verticalScrollableBase.ScrollOutOfBound += OnVerticalScrollOutOfBound; - - ListItem[] items = mListItems; - verticalItems = new Button[items.Length]; - for (int i = 0; i < items.Length; i++) - { - verticalItems[i] = new Button - { - BackgroundColor = new Color(1.0f, 1.0f, 1.0f, 1.0f), - Position = new Position(0, i * 80), - Size = new Size(mRootView.Size2D.Width, 80), - PointSize = 12.0f, - TextColor = Color.Black, - Layout = new LinearLayout() - { - LinearOrientation = LinearLayout.Orientation.Horizontal, - VerticalAlignment = VerticalAlignment.Center, - HorizontalAlignment = HorizontalAlignment.Begin, - CellPadding = new Size2D(20, 20), - }, - - }; - - string iconpath = items[i].GetPath(); - if (iconpath.Length > 0) - { - var margin1 = new View - { - Size2D = new Size2D(10, 32), - HeightResizePolicy = ResizePolicyType.FillToParent - }; - verticalItems[i].Add(margin1); - - ImageView icon = new ImageView(resPath + items[i].GetPath()) - { - Size2D = new Size2D(32, 32), - Name = Program.ItemContentNameIcon, - }; - verticalItems[i].Add(icon); - } - - var margin = new View - { - Size2D = new Size2D(10, 32), - HeightResizePolicy = ResizePolicyType.FillToParent - }; - verticalItems[i].Add(margin); - - PropertyMap titleStyle = new PropertyMap(); - titleStyle.Add("weight", new PropertyValue(600)); - TextLabel title = new TextLabel(items[i].GetLabel()) - { - FontStyle = titleStyle, - Name = Program.ItemContentNameTitle, - Padding = new Extents(8, 8, 8, 8), - }; - verticalItems[i].Add(title); - - - if (i % 2 == 0) - { - verticalItems[i].BackgroundColor = Color.White; - } - else - { - verticalItems[i].BackgroundColor = Color.Cyan; - } -#if false - var okButton = new Button() - { - Text = "OK", - }; - okButton.Clicked += (object sender1, ClickedEventArgs e) => { window.GetDefaultNavigator().Pop(); }; - - verticalItems[i].Clicked += (object sender, ClickedEventArgs e) => - { - DialogPage.ShowAlertDialog("Clicked", verticalItems[i].Name, okButton); - }; -#endif - - verticalScrollableBase.Add(verticalItems[i]); - } - mRootView.Add(verticalScrollableBase); - } - - private void OnVerticalScrollOutOfBound(object sender, ScrollOutOfBoundEventArgs e) - { -#if false - if (e.Displacement > 80) - { - if (e.PanDirection == ScrollOutOfBoundEventArgs.Direction.Down) - { - verticalItems[0].Text = $"Reached at the top, panned displacement is {e.Displacement}."; - } - } - else if (0 - e.Displacement > 80) - { - if (e.PanDirection == ScrollOutOfBoundEventArgs.Direction.Up) - { - verticalItems[mListItems.Length - 1].Text = $"Reached at the bottom, panned displacement is {e.Displacement}."; - } - } -#endif - } - - protected override void OnPause() - { - base.OnPause(); - } - - protected override void OnResume() - { - Tizen.Log.Error("widget", "OnResume \n"); - base.OnResume(); - } - - protected override void OnResize(Window window) - { - base.OnResize(window); - } - - protected override void OnTerminate(string contentInfo, TerminationType type) - { - base.OnTerminate(contentInfo, type); - } - - protected override void OnUpdate(string contentInfo, int force) - { - base.OnUpdate(contentInfo, force); - } - - protected View mRootView; - protected ScrollableBase verticalScrollableBase = null; - protected Button[] verticalItems; - } -} - diff --git a/SettingCertificates/SettingCertificates/SettingWidget_MainMenu.cs b/SettingCertificates/SettingCertificates/SettingWidget_MainMenu.cs deleted file mode 100644 index be37c13..0000000 --- a/SettingCertificates/SettingCertificates/SettingWidget_MainMenu.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System; -using System.ComponentModel; -using System.Diagnostics; -using System.Collections.Generic; -using Tizen.NUI; -using Tizen.NUI.BaseComponents; -using Tizen.NUI.Components; -using Tizen.Applications; - -namespace SettingMain -{ - class SettingWidget_MainMenu : SettingWidget_Base - { - private static readonly ListItem[] mItems = { - // Connections - new ListItem(1, SETTING_LIST_ICON_PATH_CFG+"settings_wifi.png", "Wifi","Wifi"), - new ListItem(1, SETTING_LIST_ICON_PATH_CFG+"settings_bluetooth.png", "Bluetooth","Bluetooth"), - new ListItem(1, SETTING_LIST_ICON_PATH_CFG+"settings_wifi.png", "Wired Network","Wired Network"), - new ListItem(1, SETTING_LIST_ICON_PATH_CFG+"settings_wifi.png", "Tethering","Tethering"), - - // Sound - new ListItem(1, SETTING_LIST_ICON_PATH_CFG+"settings_sound_and_notifications.png", "Sound","Sound"), - new ListItem(1, SETTING_LIST_ICON_PATH_CFG+"settings_notifications.png", "Notifications","Notifications"), - - // Display - new ListItem(1, SETTING_LIST_ICON_PATH_CFG+"settings_display.png", "Display","Display"), - new ListItem(1, SETTING_LIST_ICON_PATH_CFG+"settings_wallpapers.png", "Wallpaper","Wallpaper"), - new ListItem(1, SETTING_LIST_ICON_PATH_CFG+"settings_softkey.png", "Tray","Tray"), - new ListItem(1, SETTING_LIST_ICON_PATH_CFG+"settings_softkey.png", "Screen Mirroring","Screen Mirroring"), - - // Personal - new ListItem(1, SETTING_LIST_ICON_PATH_CFG+"settings_account.png", "Accounts","Accounts"), - new ListItem(1, SETTING_LIST_ICON_PATH_CFG+"settings_privacy_and_safety.png", "Privacy","Privacy"), - - // Memory - new ListItem(1, SETTING_LIST_ICON_PATH_CFG+"settings_applications.png", "Apps","Applications"), - new ListItem(1, SETTING_LIST_ICON_PATH_CFG+"settings_storage.png", "Storage","Storage"), - - // System - new ListItem(1, SETTING_LIST_ICON_PATH_CFG+"settings_language_and_input.png", "Language and input","Language and input"), - new ListItem(1, SETTING_LIST_ICON_PATH_CFG+"settings_date_and_time.png", "Date and time","Date and time"), - new ListItem(1, SETTING_LIST_ICON_PATH_CFG+"settings_reset.png", "Reset","Reset"), - new ListItem(1, SETTING_LIST_ICON_PATH_CFG+"settings_accessibility.png", "Accessibility","Accessibility"), - - // Device - new ListItem(1, SETTING_LIST_ICON_PATH_CFG+"settings_about_device.png", "About device","About device"), - }; - - public SettingWidget_MainMenu() - :base(mItems) - { - Tizen.Log.Error("SettingWidget", "Main menu \n"); - } - } - -} diff --git a/SettingCertificates/SettingCertificates/WidgetSettingCertificates.cs b/SettingCertificates/SettingCertificates/WidgetSettingCertificates.cs new file mode 100644 index 0000000..6e36e09 --- /dev/null +++ b/SettingCertificates/SettingCertificates/WidgetSettingCertificates.cs @@ -0,0 +1,444 @@ +/* + * Copyright (c) 2022 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +using SettingPrivacy.res.locale; +using System; +using System.Collections.Generic; +using Tizen.Applications; +using Tizen.NUI; +using Tizen.NUI.BaseComponents; +using Tizen.NUI.Components; +using static Interop; +using static Interop.CertSvc; + +namespace SettingCertificates +{ + class WidgetSettingCertificates : Widget + { + protected View _rootView = null; + List _rootCA, _userCert; + private Navigator _navigator; + internal static string LogTag = "SettingMain.Certificate"; + + public WidgetSettingCertificates() : base() + { + } + void log(string str) + { + Tizen.Log.Debug(LogTag, str); + } + protected override void OnCreate(string contentInfo, Window window) + { + Bundle bundle = Bundle.Decode(contentInfo); + CreateCertList(); + _rootView = new View(); + _rootView.BackgroundColor = Color.White; + _rootView.Size2D = window.Size; + _rootView.PivotPoint = PivotPoint.Center; + window.GetDefaultLayer().Add(_rootView); + _navigator = window.GetDefaultNavigator(); + _navigator.Push(CreateFirstPage()); + + } + private ContentPage CreateFirstPage() + { + ScrollableBase content = CreateScrollableBase(); + var rootCert = new DefaultLinearItem() + { + WidthSpecification = LayoutParamPolicies.MatchParent, + Text = Resources.IDS_ST_BODY_TRUSTED_ROOT_CA_CERTIFICATES_ABB/*"Trusted root CA certificates"*/, + IsSelectable = false, + Margin = new Extents(20, 20, 1, 1), + BackgroundColor = Color.White, + }; + + rootCert.Clicked += (o, e) => + { + _navigator.Push(CreateSecondPage(Resources.IDS_ST_BODY_TRUSTED_ROOT_CA_CERTIFICATES_ABB/*"Trusted root CA certificates"*/, _rootCA)); + }; + content.Add(rootCert); + var userCert = new DefaultLinearItem() + { + WidthSpecification = LayoutParamPolicies.MatchParent, + Text = Resources.IDS_ST_BODY_USER_CERTIFICATES/*"User certificates"*/, + IsSelectable = false, + Margin = new Extents(20, 20, 1, 1), + BackgroundColor = Color.White, + CornerRadius = new Vector4(10, 10, 10, 10) + }; + + userCert.Clicked += (o, e) => + { + _navigator.Push(CreateSecondPage(Resources.IDS_ST_BODY_USER_CERTIFICATES/*"User certificates"*/, _userCert)); + }; + content.Add(userCert); + + ContentPage firstPage = CreateContentPage(Resources.IDS_ST_HEADER_MANAGE_CERTIFICATES_ABB/*"Manage certificates"*/, content); + firstPage.AppBar.AutoNavigationContent = false; + + var navigationContent = new Button(((AppBarStyle)ThemeManager.GetStyle("Tizen.NUI.Components.AppBar")).BackButton); + navigationContent.Clicked += (o, e) => + { + Bundle bundle = new Bundle(); + bundle.AddItem("WIDGET_ACTION", "POP"); + SetContentInfo(bundle.Encode()); + }; + firstPage.AppBar.NavigationContent = navigationContent; + + return firstPage; + } + private ContentPage CreateSecondPage(string title, List certificates) + { + ScrollableBase content = CreateScrollableBase(); + content.BackgroundColor = new Color("#EFEFEF"); + foreach (certificateMetadata cert in certificates) + { + var item = new DefaultLinearItem() + { + WidthSpecification = LayoutParamPolicies.MatchParent, + Text = cert.title, + IsSelectable = false, + Margin = new Extents(20, 20, 1, 1), + BackgroundColor = Color.White, + CornerRadius = new Vector4(10, 10, 10, 10) + }; + + item.Clicked += (o, e) => + { + _navigator.Push(CreateCertDetails(cert)); + }; + content.Add(item); + } + return CreateContentPage(title, content); + } + private ContentPage CreateCertDetails(certificateMetadata cert) + { + ScrollableBase content = CreateScrollableBase(); + content.BackgroundColor = new Color("#EFEFEF"); + const float fieldTitleFontScale = 1.2F; + const float titleFontScale = 1.1F; + PropertyMap titleFontStyle = new PropertyMap(); + titleFontStyle.Add("weight", new PropertyValue("bold")); + /* Use Certificate */ + var item = new DefaultLinearItem() + { + WidthSpecification = LayoutParamPolicies.MatchParent, + Text = " " + "Use certificate", // NOT defined in Resources... + IsSelectable = false, + BackgroundColor = Color.White, + Margin = new Extents(20, 20, 1, 0), + CornerRadius = new Vector4(10, 10, 10, 10) + }; + content.Add(item); + /* Owner Certificate */ + TextLabel ownerLabel = new TextLabel() + { + Text = " " + Resources.IDS_SCP_BODY_OWNER_ABB/*"Owner"*/, + Margin = new Extents(20, 20, 6, 6), + WidthSpecification = LayoutParamPolicies.MatchParent, + FontSizeScale = titleFontScale, + FontStyle = titleFontStyle, + }; + content.Add(ownerLabel); + foreach (CertificateField field in new CertificateField[] { CertificateField.CERTSVC_SUBJECT_COMMON_NAME, CertificateField.CERTSVC_SUBJECT_ORGANIZATION_NAME }) + { + TextLabel fieldTitle = new TextLabel() + { + Text = " " + cert.GetFieldTitle(field), + FontSizeScale = fieldTitleFontScale, + BackgroundColor = Color.White, + Margin = new Extents(20, 20, 1, 0), + WidthSpecification = LayoutParamPolicies.MatchParent, + }; + TextLabel fieldValue = new TextLabel() + { + Text = " " + cert.GetField(field), + BackgroundColor = Color.White, + Margin = new Extents(20, 20, 1, 0), + WidthSpecification = LayoutParamPolicies.MatchParent, + FontStyle = titleFontStyle, + }; + content.Add(fieldTitle); + content.Add(fieldValue); + } + /* Issuer Certificate */ + TextLabel issuerLabel = new TextLabel() + { + Text = " " + Resources.IDS_ST_BODY_ISSUER/*"Issuer"*/, + Margin = new Extents(20, 20, 6, 6), + WidthSpecification = LayoutParamPolicies.MatchParent, + FontSizeScale = titleFontScale, + FontStyle = titleFontStyle, + }; + content.Add(issuerLabel); + foreach (CertificateField field in new CertificateField[] { CertificateField.CERTSVC_ISSUER_COMMON_NAME, CertificateField.CERTSVC_ISSUER_ORGANIZATION_NAME }) + { + TextLabel fieldTitle = new TextLabel() + { + Text = " " + cert.GetFieldTitle(field), + FontSizeScale = fieldTitleFontScale, + BackgroundColor = Color.White, + Margin = new Extents(20, 20, 1, 0), + WidthSpecification = LayoutParamPolicies.MatchParent, + }; + TextLabel fieldValue = new TextLabel() + { + Text = " " + cert.GetField(field), + BackgroundColor = Color.White, + Margin = new Extents(20, 20, 1, 0), + WidthSpecification = LayoutParamPolicies.MatchParent, + FontStyle = titleFontStyle, + }; + content.Add(fieldTitle); + content.Add(fieldValue); + } + /* Issuer Certificate information */ + TextLabel certInfo = new TextLabel() + { + Text = " " + Resources.IDS_ST_BODY_CERTIFICATE_INFORMATION/*"Certificate information"*/, + Margin = new Extents(20, 20, 6, 6), + WidthSpecification = LayoutParamPolicies.MatchParent, + FontSizeScale = titleFontScale, + FontStyle = titleFontStyle, + }; + content.Add(certInfo); + foreach (CertificateField field in new CertificateField[] { CertificateField.CERTSVC_VERSION }) + { + TextLabel fieldTitle = new TextLabel() + { + Text = " " + cert.GetFieldTitle(field), + FontSizeScale = fieldTitleFontScale, + BackgroundColor = Color.White, + Margin = new Extents(20, 20, 1, 0), + WidthSpecification = LayoutParamPolicies.MatchParent, + }; + TextLabel fieldValue = new TextLabel() + { + Text = " " + cert.GetField(field), + BackgroundColor = Color.White, + Margin = new Extents(20, 20, 1, 0), + WidthSpecification = LayoutParamPolicies.MatchParent, + FontStyle = titleFontStyle, + }; + content.Add(fieldTitle); + content.Add(fieldValue); + } + { + TextLabel fieldTitle = new TextLabel() + { + Text = " " + Resources.IDS_ST_BODY_VALID_FROM_C/*"Valid from:"*/, + FontSizeScale = fieldTitleFontScale, + BackgroundColor = Color.White, + Margin = new Extents(20, 20, 1, 0), + WidthSpecification = LayoutParamPolicies.MatchParent, + }; + TextLabel fieldValue = new TextLabel() + { + Text = " " + cert.before.ToString("U"), + BackgroundColor = Color.White, + Margin = new Extents(20, 20, 1, 0), + WidthSpecification = LayoutParamPolicies.MatchParent, + FontStyle = titleFontStyle, + }; + content.Add(fieldTitle); + content.Add(fieldValue); + } + { + TextLabel fieldTitle = new TextLabel() + { + Text = " " + Resources.IDS_ST_BODY_VALID_TO_C/*"Valid to:"*/, + FontSizeScale = fieldTitleFontScale, + BackgroundColor = Color.White, + Margin = new Extents(20, 20, 1, 0), + WidthSpecification = LayoutParamPolicies.MatchParent, + }; + TextLabel fieldValue = new TextLabel() + { + Text = " " + cert.after.ToString("U"), + BackgroundColor = Color.White, + Margin = new Extents(20, 20, 1, 0), + WidthSpecification = LayoutParamPolicies.MatchParent, + FontStyle = titleFontStyle, + }; + content.Add(fieldTitle); + content.Add(fieldValue); + } + foreach (CertificateField field in new CertificateField[] { CertificateField.CERTSVC_SERIAL_NUMBER, CertificateField.CERTSVC_SIGNATURE_ALGORITHM, + CertificateField.CERTSVC_KEY_USAGE }) + { + TextLabel fieldTitle = new TextLabel() + { + Text = " " + cert.GetFieldTitle(field), + FontSizeScale = fieldTitleFontScale, + BackgroundColor = Color.White, + Margin = new Extents(20, 20, 1, 0), + WidthSpecification = LayoutParamPolicies.MatchParent, + }; + TextLabel fieldValue = new TextLabel() + { + Text = " " + cert.GetField(field), + BackgroundColor = Color.White, + Margin = new Extents(20, 20, 1, 0), + WidthSpecification = LayoutParamPolicies.MatchParent, + FontStyle = titleFontStyle, + }; + content.Add(fieldTitle); + content.Add(fieldValue); + } + { + string txt = Resources.IDS_ST_BODY_FALSE/*"False"*/; + if (cert.rootCa == 1) + { + txt = Resources.IDS_ST_BODY_TRUE/*"True"*/; + } + TextLabel fieldTitle = new TextLabel() + { + Text = " " + Resources.IDS_ST_BODY_CERTIFICATION_AUTHORITY_C/*"Certification authority:"*/, + FontSizeScale = fieldTitleFontScale, + BackgroundColor = Color.White, + Margin = new Extents(20, 20, 1, 0), + WidthSpecification = LayoutParamPolicies.MatchParent, + }; + TextLabel fieldValue = new TextLabel() + { + Text = " " + txt, + BackgroundColor = Color.White, + Margin = new Extents(20, 20, 1, 0), + WidthSpecification = LayoutParamPolicies.MatchParent, + FontStyle = titleFontStyle, + }; + content.Add(fieldTitle); + content.Add(fieldValue); + } + { + TextLabel fieldTitle = new TextLabel() + { + Text = " " + cert.GetFieldTitle(CertificateField.CERTSVC_KEY), + FontSizeScale = fieldTitleFontScale, + BackgroundColor = Color.White, + Margin = new Extents(20, 20, 1, 0), + WidthSpecification = LayoutParamPolicies.MatchParent, + }; + TextLabel fieldValue = new TextLabel() + { + MultiLine = true, + Text = cert.GetField(CertificateField.CERTSVC_KEY).Replace(" ", " "), + BackgroundColor = Color.White, + Margin = new Extents(20, 20, 1, 0), + WidthSpecification = LayoutParamPolicies.MatchParent, + FontStyle = titleFontStyle, + CornerRadius = new Vector4(0, 0, 10, 10), + }; + content.Add(fieldTitle); + content.Add(fieldValue); + } + + return CreateContentPage(Resources.IDS_ST_BODY_CERTIFICATE_DETAILS/*"Certificate details"*/, content); + } + bool CreateCertList() + { + log("create instance"); + int result = CertSvc.InstanceNew(out IntPtr instance); + if ((CertSvc.ErrorCode)result != CertSvc.ErrorCode.CERTSVC_SUCCESS) + { + log("unable to create cert instance, result: " + result.ToString()); + return false; + } + log("Instance created"); + result = CertSvc.GetPKCS12CertificateListFromStore(instance, CertSvc.CertStoreType.ALL_STORE, 0, out IntPtr storeCertList, out int length); + if ((CertSvc.ErrorCode)result != CertSvc.ErrorCode.CERTSVC_SUCCESS) + { + log("unable to get root certificates, result: " + result.ToString()); + result = CertSvc.FreePKCS12CertificateListFromStore(instance, out storeCertList); + if ((CertSvc.ErrorCode)result != CertSvc.ErrorCode.CERTSVC_SUCCESS) + { + log("unable to free certlist, result: " + result.ToString()); + } + CertSvc.InstanceFree(instance); + return false; + } + log("All store length: " + length); + _rootCA = CertSvc.GetCertLists(instance, storeCertList, length); + + result = CertSvc.FreePKCS12CertificateListFromStore(instance, out storeCertList); + if ((CertSvc.ErrorCode)result != CertSvc.ErrorCode.CERTSVC_SUCCESS) + { + log("unalbe to free certlist, result: " + result.ToString()); + } + result = CertSvc.GetPKCS12UserCertificateListFromStore(instance, CertStoreType.ALL_STORE, out IntPtr user, out int ul); + if ((CertSvc.ErrorCode)result != CertSvc.ErrorCode.CERTSVC_SUCCESS) + { + log("unable to get user certificate list, result: " + result.ToString()); + } + log("User length: " + ul); + _userCert = CertSvc.GetCertLists(instance, user, ul); + result = CertSvc.FreePKCS12CertificateListFromStore(instance, out user); + if ((CertSvc.ErrorCode)result != CertSvc.ErrorCode.CERTSVC_SUCCESS) + { + log("unalbe to free user certlist, result: " + result.ToString()); + } + CertSvc.InstanceFree(instance); + return true; + } + private ScrollableBase CreateScrollableBase() + { + return new ScrollableBase() + { + ScrollingDirection = ScrollableBase.Direction.Vertical, + WidthSpecification = LayoutParamPolicies.MatchParent, + HeightSpecification = LayoutParamPolicies.MatchParent, + HideScrollbar = false, + Layout = new LinearLayout() + { + LinearOrientation = LinearLayout.Orientation.Vertical, + }, + }; + } + private ContentPage CreateContentPage(string title, ScrollableBase content) + { + log("CreateContentPage with title: " + title); + return new ContentPage() + { + AppBar = new AppBar() + { + Title = title, + }, + Content = content, + BackgroundColor = new Color("#EFEFEF"), + }; + } + + private void OnVerticalScrollOutOfBound(object sender, ScrollOutOfBoundEventArgs e) + { +#if false + if (e.Displacement > 80) + { + if (e.PanDirection == ScrollOutOfBoundEventArgs.Direction.Down) + { + verticalItems[0].Text = $"Reached at the top, panned displacement is {e.Displacement}."; + } + } + else if (0 - e.Displacement > 80) + { + if (e.PanDirection == ScrollOutOfBoundEventArgs.Direction.Up) + { + verticalItems[mListItems.Length - 1].Text = $"Reached at the bottom, panned displacement is {e.Displacement}."; + } + } +#endif + } + } +} diff --git a/SettingCertificates/SettingCertificates/api/Interop/Interop.CertSvc.cs b/SettingCertificates/SettingCertificates/api/Interop/Interop.CertSvc.cs new file mode 100644 index 0000000..ff8775b --- /dev/null +++ b/SettingCertificates/SettingCertificates/api/Interop/Interop.CertSvc.cs @@ -0,0 +1,326 @@ +/* + * Copyright (c) 2022 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +using System; +using System.Runtime.InteropServices; +using System.Collections.Generic; +using System.ComponentModel; +using System.Reflection; +using System.Linq; +using SettingPrivacy.res.locale; + +internal static partial class Interop +{ + internal static partial class CertSvc + { + internal static string LogTag = "InteropTest.CertSvc"; + internal enum ErrorCode + { + CERTSVC_TRUE = 1, + CERTSVC_FALSE = 0, + CERTSVC_SUCCESS = 1, + CERTSVC_FAIL = 0, + CERTSVC_BAD_ALLOC = -2, + CERTSVC_WRONG_ARGUMENT = -4, + CERTSVC_INVALID_ALGORITHM = -5, + CERTSVC_INVALID_SIGNATURE = -6, + CERTSVC_IO_ERROR = -7, + CERTSVC_INVALID_PASSWORD = -8, + CERTSVC_DUPLICATED_ALIAS = -9, + CERTSVC_ALIAS_DOES_NOT_EXIST = -10, + CERTSVC_INVALID_STORE_TYPE = -11, + CERTSVC_INVALID_STATUS = -12, + CERTSVC_INVALID_CERTIFICATE = -13, + }; + internal enum CertStoreType + { + NONE_STORE = 0, + VPN_STORE = 1 << 0, + WIFI_STORE = 1 << 1, + EMAIL_STORE = 1 << 2, + SYSTEM_STORE = 1 << 3, + ALL_STORE = VPN_STORE | WIFI_STORE | EMAIL_STORE | SYSTEM_STORE, + }; + internal enum CertificateField + { + CERTSVC_SUBJECT, + [Description("Common name")] + CERTSVC_SUBJECT_COMMON_NAME, + CERTSVC_SUBJECT_COUNTRY_NAME, + CERTSVC_SUBJECT_STATE_NAME, + CERTSVC_SUBJECT_LOCALITY_NAME, + [Description("Organization")] + CERTSVC_SUBJECT_ORGANIZATION_NAME, + CERTSVC_SUBJECT_ORGANIZATION_UNIT_NAME, + CERTSVC_SUBJECT_EMAIL_ADDRESS, + /* CERTSVC_SUBJECT_UID, */ + CERTSVC_ISSUER, + [Description("Common name")] + CERTSVC_ISSUER_COMMON_NAME, + CERTSVC_ISSUER_COUNTRY_NAME, + CERTSVC_ISSUER_STATE_NAME, + CERTSVC_ISSUER_LOCALITY_NAME, + [Description("Organization")] + CERTSVC_ISSUER_ORGANIZATION_NAME, + CERTSVC_ISSUER_ORGANIZATION_UNIT_NAME, + CERTSVC_ISSUER_EMAIL_ADDRESS, + /* CERTSVC_ISSUER_UID, */ + [Description("Version")] + CERTSVC_VERSION, + [Description("Serial number")] + CERTSVC_SERIAL_NUMBER, + [Description("Key usage")] + CERTSVC_KEY_USAGE, + [Description("Public key")] + CERTSVC_KEY, + CERTSVC_KEY_ALGO, + [Description("Signature algorithm")] + CERTSVC_SIGNATURE_ALGORITHM, + }; + public static string GetCertFieldDescription(CertificateField field) + { + Type genericEnumType = field.GetType(); + MemberInfo[] memberInfo = genericEnumType.GetMember(field.ToString()); + if ((memberInfo != null && memberInfo.Length > 0)) + { + var _Attribs = memberInfo[0].GetCustomAttributes(typeof(System.ComponentModel.DescriptionAttribute), false); + if ((_Attribs != null && _Attribs.Count() > 0)) + { + return ((System.ComponentModel.DescriptionAttribute)_Attribs.ElementAt(0)).Description; + } + } + return field.ToString(); + } + + internal enum CertStatus + { + DISABLED = 0, + ENABLED = 1, + }; + [StructLayout(LayoutKind.Sequential)] + internal struct StoreCertList + { + internal IntPtr gname; + internal IntPtr title; + internal CertStatus status; + internal CertStoreType storeType; + internal IntPtr next; + } + internal class certificateMetadata + { + internal string gname; + internal string title; + internal CertStatus status; + internal CertStoreType storeType; + internal string[] fields; + internal DateTime before; + internal DateTime after; + internal int rootCa; + public certificateMetadata() + { + fields = new string[Enum.GetNames(typeof(CertificateField)).Length]; + } + public string GetField(CertificateField field) + { + return fields[(int)field]; + } + public string GetFieldTitle(CertificateField field) + { + switch (field) + { + case CertificateField.CERTSVC_SUBJECT_COMMON_NAME: + return Resources.IDS_ST_BODY_COMMON_NAME_C; /*Common name*/ + case CertificateField.CERTSVC_SUBJECT_ORGANIZATION_NAME: + return Resources.IDS_ST_BODY_ORGANISATION_C; /*Organization*/ + case CertificateField.CERTSVC_ISSUER_COMMON_NAME: + return Resources.IDS_ST_BODY_ISSUER_COLON; /*Common name*/ + case CertificateField.CERTSVC_ISSUER_ORGANIZATION_NAME: + return Resources.IDS_ST_BODY_ORGANISATION_C; /*Organization*/ + case CertificateField.CERTSVC_VERSION: + return Resources.IDS_ST_BODY_VERSION_C; /*Version*/ + case CertificateField.CERTSVC_SERIAL_NUMBER: + return Resources.IDS_ST_BODY_SERIAL_NUMBER_COLON; /*Serial number*/ + case CertificateField.CERTSVC_KEY_USAGE: + return Resources.IDS_ST_BODY_KEY_USAGE_C; /*Key usage*/ + case CertificateField.CERTSVC_KEY: + return Resources.IDS_ST_BODY_PUBLIC_KEY_C; /*Public key*/ + case CertificateField.CERTSVC_SIGNATURE_ALGORITHM: + return Resources.IDS_ST_BODY_SIGNATURE_ALGORITHM_C; /*Signature algorithm*/ + + default: + break; + } + return GetCertFieldDescription(field); + } + } + + internal struct StoreCertHandle + { + string name; + string title; + CertStatus status; + CertStoreType storeType; + } + internal struct Certificate + { + internal int privateHandler; + internal Instance Instance; + } + + internal struct Instance + { + internal IntPtr privatePtr; + } + + internal struct CertSvcString + { + internal IntPtr privateHandler; + internal int privateLength; + internal Instance Instance; + } + /* + // cert UI: + Owner: + Common name: + Organization: + Issuer: + Common name: + Organization: + Certificate Information: + Version: + Valid from: + Valid to: + Serial number: + Signature algorithm: + Key Usage: + Certification authority: + Public Key: + + */ + + internal static List GetCertLists(IntPtr instance, IntPtr certList, int length) + { + IntPtr cur = certList; + var list = new List(); + + while (cur != IntPtr.Zero) + { + StoreCertList item = Marshal.PtrToStructure(cur); + certificateMetadata cert = new certificateMetadata + { + status = item.status, + gname = Marshal.PtrToStringUTF8(item.gname), + title = Marshal.PtrToStringUTF8(item.title), + storeType = item.storeType + }; + ErrorCode err = (ErrorCode)GetPKCS12CertificateFromStore(instance, item.storeType, item.gname, out Certificate cout); + if (err != ErrorCode.CERTSVC_SUCCESS) + { + Tizen.Log.Debug(LogTag, "Unable to GetPKCS12CertificateFromStore, err: " + err + ", instance: " + + instance + " gname: " + item.gname + " store_type: " + item.storeType); + cur = item.next; + continue; + } + + err = (ErrorCode)GetCertificateNotAfter(cout, out long time); + if (err != ErrorCode.CERTSVC_SUCCESS) + { + Tizen.Log.Debug(LogTag, "Unable to GetCertificateNotAfter, , err: " + err + ", instance: " + + instance + " gname: " + item.gname + " store_type: " + item.storeType); + cur = item.next; + continue; + } + cert.after = new DateTime(1970, 1, 1).ToLocalTime().AddSeconds(time); + err = (ErrorCode)GetCertificateNotBefore(cout, out time); + if (err != ErrorCode.CERTSVC_SUCCESS) + { + Tizen.Log.Debug(LogTag, "Unable to GetCertificateNotBefore, , err: " + err + ", instance: " + + instance + " gname: " + item.gname + " store_type: " + item.storeType); + cur = item.next; + continue; + } + cert.before = new DateTime(1970, 1, 1).ToLocalTime().AddSeconds(time); + err = (ErrorCode)GetCertificateIsRootCa(cout, out int isRootCa); + if (err != ErrorCode.CERTSVC_SUCCESS) + { + Tizen.Log.Debug(LogTag, "Unable to GetCertificateIsRootCa, , err: " + err + ", instance: " + + instance + " gname: " + item.gname + " store_type: " + item.storeType); + cur = item.next; + continue; + } + cert.rootCa = isRootCa; + bool gotError = false; + foreach (CertificateField certificateField in Enum.GetValues(typeof(CertificateField))) + { + err = (ErrorCode)GetCertificateStringField(cout, certificateField, out CertSvcString certSvcString); + if (err != ErrorCode.CERTSVC_SUCCESS) + { + Tizen.Log.Debug(LogTag, "Unable to GetCertificateStringField, , err: " + err + ", instance: " + + instance + " gname: " + item.gname + " store_type: " + item.storeType); + cur = item.next; + gotError = true; + break; + } + string stringField = Marshal.PtrToStringUTF8(certSvcString.privateHandler); + cert.fields[(int)certificateField] = stringField; + } + if (gotError == true) + { + continue; + } + cur = item.next; + list.Add(cert); + } + Tizen.Log.Debug(LogTag, "CertList size: " + list.Count); + return list; + } + + // int certsvc_instance_new(CertSvcInstance *instance); + [DllImport(Libraries.CertSvc, EntryPoint = "certsvc_instance_new")] + internal static extern int InstanceNew(out IntPtr instance); + // void certsvc_instance_free(CertSvcInstance instance); + [DllImport(Libraries.CertSvc, EntryPoint = "certsvc_instance_free")] + internal static extern void InstanceFree(IntPtr instance); + // int certsvc_pkcs12_get_certificate_list_from_store(CertSvcInstance instance, CertStoreType storeType, int is_root_app, CertSvcStoreCertList **certlist, size_t *lenght); + [DllImport(Libraries.CertSvc, EntryPoint = "certsvc_pkcs12_get_certificate_list_from_store")] + internal static extern int GetPKCS12CertificateListFromStore(IntPtr instance, CertStoreType storeType, int isRootApp, out IntPtr certList, out int length); + // int certsvc_pkcs12_free_certificate_list_from_store(CertSvcInstance instance, CertSvcStoreCertList **certlist); + [DllImport(Libraries.CertSvc, EntryPoint = "certsvc_pkcs12_free_certificate_list_loaded_from_store")] + internal static extern int FreePKCS12CertificateListFromStore(IntPtr instance, out IntPtr certList); + // int certsvc_pkcs12_get_certificate_from_store(CertSvcInstance instance, CertStoreType storeType, const char* gname, CertSvcCertificate *certificate); + [DllImport(Libraries.CertSvc, EntryPoint = "certsvc_pkcs12_get_certificate_from_store")] + internal static extern int GetPKCS12CertificateFromStore(IntPtr instance, CertStoreType storeType, IntPtr gname, out Certificate certificate); + + // int certsvc_certificate_get_string_field(CertSvcCertificate certificate, CertSvcCertificateField field, CertSvcString *buffer); + [DllImport(Libraries.CertSvc, EntryPoint = "certsvc_certificate_get_string_field")] + internal static extern int GetCertificateStringField(Certificate certificate, CertificateField field, out CertSvcString buffer); + // int certsvc_certificate_get_not_after(CertSvcCertificate certificate, time_t *result); + [DllImport(Libraries.CertSvc, EntryPoint = "certsvc_certificate_get_not_after")] + internal static extern int GetCertificateNotAfter(Certificate certificate, out long result); + // int certsvc_certificate_get_not_before(CertSvcCertificate certificate, time_t *result); + [DllImport(Libraries.CertSvc, EntryPoint = "certsvc_certificate_get_not_before")] + internal static extern int GetCertificateNotBefore(Certificate certificate, out long result); + // int certsvc_certificate_is_root_ca(CertSvcCertificate certificate, int *result); + [DllImport(Libraries.CertSvc, EntryPoint = "certsvc_certificate_is_root_ca")] + internal static extern int GetCertificateIsRootCa(Certificate certificate, out int status); + + /* END USER API */ + // int certsvc_pkcs12_get_end_user_certificate_list_from_store(CertSvcInstance instance, CertStoreType storeType, CertSvcStoreCertList **certlist, size_t *lenght); + [DllImport(Libraries.CertSvc, EntryPoint = "certsvc_pkcs12_get_end_user_certificate_list_from_store")] + internal static extern int GetPKCS12UserCertificateListFromStore(IntPtr instance, CertStoreType storeType, out IntPtr certList, out int length); + + } +} \ No newline at end of file diff --git a/SettingCertificates/SettingCertificates/api/Interop/Interop.Libraries.cs b/SettingCertificates/SettingCertificates/api/Interop/Interop.Libraries.cs new file mode 100644 index 0000000..1259020 --- /dev/null +++ b/SettingCertificates/SettingCertificates/api/Interop/Interop.Libraries.cs @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2022 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +internal static partial class Interop +{ + internal static partial class Libraries + { + public const string CertSvc = "libcert-svc-vcore.so.2"; + } +} \ No newline at end of file diff --git a/SettingCertificates/SettingCertificates/res/locale/Resource.Designer.cs b/SettingCertificates/SettingCertificates/res/locale/Resource.Designer.cs new file mode 100644 index 0000000..693caad --- /dev/null +++ b/SettingCertificates/SettingCertificates/res/locale/Resource.Designer.cs @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2022 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +//------------------------------------------------------------------------------ +// +// 이 코드는 도구를 사용하여 생성되었습니다. +// 런타임 버전:4.0.30319.42000 +// +// 파일 내용을 변경하면 잘못된 동작이 발생할 수 있으며, 코드를 다시 생성하면 +// 이러한 변경 내용이 손실됩니다. +// +//------------------------------------------------------------------------------ + +namespace SettingPrivacy.res.locale +{ + using System; + + + /// + /// 지역화된 문자열 등을 찾기 위한 강력한 형식의 리소스 클래스입니다. + /// + // 이 클래스는 ResGen 또는 Visual Studio와 같은 도구를 통해 StronglyTypedResourceBuilder + // 클래스에서 자동으로 생성되었습니다. + // 멤버를 추가하거나 제거하려면 .ResX 파일을 편집한 다음 /str 옵션을 사용하여 ResGen을 + // 다시 실행하거나 VS 프로젝트를 다시 빌드하십시오. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources + { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() + { + } + + /// + /// 이 클래스에서 사용하는 캐시된 ResourceManager 인스턴스를 반환합니다. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager + { + get + { + if (object.ReferenceEquals(resourceMan, null)) + { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SettingCertificates.res.locale.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 이 강력한 형식의 리소스 클래스를 사용하여 모든 리소스 조회에 대해 현재 스레드의 CurrentUICulture 속성을 + /// 재정의합니다. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture + { + get + { + return resourceCulture; + } + set + { + resourceCulture = value; + } + } + internal static string IDS_ST_BODY_TRUSTED_ROOT_CA_CERTIFICATES_ABB + { + get + { + return ResourceManager.GetString("IDS_ST_BODY_TRUSTED_ROOT_CA_CERTIFICATES_ABB", resourceCulture); + } + } + internal static string IDS_ST_BODY_USER_CERTIFICATES + { + get + { + return ResourceManager.GetString("IDS_ST_BODY_USER_CERTIFICATES", resourceCulture); + } + } + internal static string IDS_ST_HEADER_MANAGE_CERTIFICATES_ABB + { + get + { + return ResourceManager.GetString("IDS_ST_HEADER_MANAGE_CERTIFICATES_ABB", resourceCulture); + } + } + internal static string IDS_SCP_BODY_OWNER_ABB + { + get + { + return ResourceManager.GetString("IDS_SCP_BODY_OWNER_ABB", resourceCulture); + } + } + internal static string IDS_ST_BODY_ISSUER + { + get + { + return ResourceManager.GetString("IDS_ST_BODY_ISSUER", resourceCulture); + } + } + internal static string IDS_ST_BODY_CERTIFICATE_INFORMATION + { + get + { + return ResourceManager.GetString("IDS_ST_BODY_CERTIFICATE_INFORMATION", resourceCulture); + } + } + internal static string IDS_ST_BODY_VALID_FROM_C + { + get + { + return ResourceManager.GetString("IDS_ST_BODY_VALID_FROM_C", resourceCulture); + } + } + internal static string IDS_ST_BODY_VALID_TO_C + { + get + { + return ResourceManager.GetString("IDS_ST_BODY_VALID_TO_C", resourceCulture); + } + } + internal static string IDS_ST_BODY_CERTIFICATION_AUTHORITY_C + { + get + { + return ResourceManager.GetString("IDS_ST_BODY_CERTIFICATION_AUTHORITY_C", resourceCulture); + } + } + internal static string IDS_ST_BODY_TRUE + { + get + { + return ResourceManager.GetString("IDS_ST_BODY_TRUE", resourceCulture); + } + } + internal static string IDS_ST_BODY_FALSE + { + get + { + return ResourceManager.GetString("IDS_ST_BODY_FALSE", resourceCulture); + } + } + internal static string IDS_ST_BODY_CERTIFICATE_DETAILS + { + get + { + return ResourceManager.GetString("IDS_ST_BODY_CERTIFICATE_DETAILS", resourceCulture); + } + } + internal static string IDS_ST_BODY_COMMON_NAME_C + { + get + { + return ResourceManager.GetString("IDS_ST_BODY_COMMON_NAME_C", resourceCulture); + } + } + internal static string IDS_ST_BODY_ORGANISATION_C + { + get + { + return ResourceManager.GetString("IDS_ST_BODY_ORGANISATION_C", resourceCulture); + } + } + internal static string IDS_ST_BODY_ISSUER_COLON + { + get + { + return ResourceManager.GetString("IDS_ST_BODY_ISSUER_COLON", resourceCulture); + } + } + internal static string IDS_ST_BODY_VERSION_C + { + get + { + return ResourceManager.GetString("IDS_ST_BODY_VERSION_C", resourceCulture); + } + } + internal static string IDS_ST_BODY_SERIAL_NUMBER_COLON + { + get + { + return ResourceManager.GetString("IDS_ST_BODY_SERIAL_NUMBER_COLON", resourceCulture); + } + } + internal static string IDS_ST_BODY_KEY_USAGE_C + { + get + { + return ResourceManager.GetString("IDS_ST_BODY_KEY_USAGE_C", resourceCulture); + } + } + internal static string IDS_ST_BODY_PUBLIC_KEY_C + { + get + { + return ResourceManager.GetString("IDS_ST_BODY_PUBLIC_KEY_C", resourceCulture); + } + } + internal static string IDS_ST_BODY_SIGNATURE_ALGORITHM_C + { + get + { + return ResourceManager.GetString("IDS_ST_BODY_SIGNATURE_ALGORITHM_C", resourceCulture); + } + } + } +} diff --git a/SettingCertificates/SettingCertificates/res/locale/Resources.Designer.cs b/SettingCertificates/SettingCertificates/res/locale/Resources.Designer.cs new file mode 100644 index 0000000..1b73135 --- /dev/null +++ b/SettingCertificates/SettingCertificates/res/locale/Resources.Designer.cs @@ -0,0 +1,243 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SettingCertificates.res.locale { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SettingCertificates.res.locale.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Owner. + /// + internal static string IDS_SCP_BODY_OWNER_ABB { + get { + return ResourceManager.GetString("IDS_SCP_BODY_OWNER_ABB", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Certificate details. + /// + internal static string IDS_ST_BODY_CERTIFICATE_DETAILS { + get { + return ResourceManager.GetString("IDS_ST_BODY_CERTIFICATE_DETAILS", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Certificate information. + /// + internal static string IDS_ST_BODY_CERTIFICATE_INFORMATION { + get { + return ResourceManager.GetString("IDS_ST_BODY_CERTIFICATE_INFORMATION", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Certification authority:. + /// + internal static string IDS_ST_BODY_CERTIFICATION_AUTHORITY_C { + get { + return ResourceManager.GetString("IDS_ST_BODY_CERTIFICATION_AUTHORITY_C", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Common name:. + /// + internal static string IDS_ST_BODY_COMMON_NAME_C { + get { + return ResourceManager.GetString("IDS_ST_BODY_COMMON_NAME_C", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to False. + /// + internal static string IDS_ST_BODY_FALSE { + get { + return ResourceManager.GetString("IDS_ST_BODY_FALSE", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Issuer:. + /// + internal static string IDS_ST_BODY_ISSUER { + get { + return ResourceManager.GetString("IDS_ST_BODY_ISSUER", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Issuer:. + /// + internal static string IDS_ST_BODY_ISSUER_COLON { + get { + return ResourceManager.GetString("IDS_ST_BODY_ISSUER_COLON", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Key usage:. + /// + internal static string IDS_ST_BODY_KEY_USAGE_C { + get { + return ResourceManager.GetString("IDS_ST_BODY_KEY_USAGE_C", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Organisation:. + /// + internal static string IDS_ST_BODY_ORGANISATION_C { + get { + return ResourceManager.GetString("IDS_ST_BODY_ORGANISATION_C", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Public key:. + /// + internal static string IDS_ST_BODY_PUBLIC_KEY_C { + get { + return ResourceManager.GetString("IDS_ST_BODY_PUBLIC_KEY_C", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Serial number:. + /// + internal static string IDS_ST_BODY_SERIAL_NUMBER_COLON { + get { + return ResourceManager.GetString("IDS_ST_BODY_SERIAL_NUMBER_COLON", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Signature algorithm:. + /// + internal static string IDS_ST_BODY_SIGNATURE_ALGORITHM_C { + get { + return ResourceManager.GetString("IDS_ST_BODY_SIGNATURE_ALGORITHM_C", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to True. + /// + internal static string IDS_ST_BODY_TRUE { + get { + return ResourceManager.GetString("IDS_ST_BODY_TRUE", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Trusted root CA certificates. + /// + internal static string IDS_ST_BODY_TRUSTED_ROOT_CA_CERTIFICATES_ABB { + get { + return ResourceManager.GetString("IDS_ST_BODY_TRUSTED_ROOT_CA_CERTIFICATES_ABB", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to User certificates. + /// + internal static string IDS_ST_BODY_USER_CERTIFICATES { + get { + return ResourceManager.GetString("IDS_ST_BODY_USER_CERTIFICATES", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Valid from:. + /// + internal static string IDS_ST_BODY_VALID_FROM_C { + get { + return ResourceManager.GetString("IDS_ST_BODY_VALID_FROM_C", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Valid to:. + /// + internal static string IDS_ST_BODY_VALID_TO_C { + get { + return ResourceManager.GetString("IDS_ST_BODY_VALID_TO_C", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Version:. + /// + internal static string IDS_ST_BODY_VERSION_C { + get { + return ResourceManager.GetString("IDS_ST_BODY_VERSION_C", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Manage certificates. + /// + internal static string IDS_ST_HEADER_MANAGE_CERTIFICATES_ABB { + get { + return ResourceManager.GetString("IDS_ST_HEADER_MANAGE_CERTIFICATES_ABB", resourceCulture); + } + } + } +} diff --git a/SettingCertificates/SettingCertificates/res/locale/Resources.en.Designer.cs b/SettingCertificates/SettingCertificates/res/locale/Resources.en.Designer.cs new file mode 100644 index 0000000..7c1b617 --- /dev/null +++ b/SettingCertificates/SettingCertificates/res/locale/Resources.en.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SettingCertificates.res.locale { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resource1 { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resource1() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SettingCertificates.res.locale.Resource1", typeof(Resource1).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/SettingCertificates/SettingCertificates/res/locale/Resources.en.resx b/SettingCertificates/SettingCertificates/res/locale/Resources.en.resx new file mode 100644 index 0000000..07c961f --- /dev/null +++ b/SettingCertificates/SettingCertificates/res/locale/Resources.en.resx @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Owner + + + Certificate details + + + Certificate information + + + Certification authority: + + + Common name: + + + False + + + Issuer: + + + Issuer: + + + Key usage: + + + Organisation: + + + Public key: + + + Serial number: + + + Signature algorithm: + + + True + + + Trusted root CA certificates + + + User certificates + + + Valid from: + + + Valid to: + + + Version: + + + Manage certificates + + \ No newline at end of file diff --git a/SettingCertificates/SettingCertificates/res/locale/Resources.ko-KR.resx b/SettingCertificates/SettingCertificates/res/locale/Resources.ko-KR.resx new file mode 100644 index 0000000..d35b53e --- /dev/null +++ b/SettingCertificates/SettingCertificates/res/locale/Resources.ko-KR.resx @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 소유자 + + + 인증서 상세정보 + + + 인증서 정보 + + + 인증 기관: + + + 일반 이름: + + + 거짓 + + + 발급자: + + + 발급자: + + + 키 용도: + + + 기관: + + + 공개키: + + + 시리얼 번호: + + + 서명 알고리즘: + + + 진실 + + + 신뢰할 수 있는 루트 CA 인증서 + + + 사용자 인증서 + + + 유효기간 시작일: + + + 유효기간 만료일: + + + 버전: + + + 인증서 관리 + + \ No newline at end of file diff --git a/SettingCertificates/SettingCertificates/res/locale/Resources.pl.resx b/SettingCertificates/SettingCertificates/res/locale/Resources.pl.resx new file mode 100644 index 0000000..23e7ec7 --- /dev/null +++ b/SettingCertificates/SettingCertificates/res/locale/Resources.pl.resx @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Właściciel + + + Szczegóły certyfikatu + + + Informacje o certyfikacie + + + Urząd certyfikacji: + + + Używana nazwa: + + + Fałsz + + + Wystawca: + + + Wystawca: + + + Wykorzystanie klucza: + + + Organizacja: + + + Klucz publiczny: + + + Numer seryjny: + + + Algorytm podpisywania: + + + Prawda + + + Certyfikaty CA zauf. gł. urzędu + + + Certyfikaty użytkownika + + + Ważny od: + + + Ważny do: + + + Wersja: + + + Zarządzanie certyfikatami + + \ No newline at end of file diff --git a/SettingCertificates/SettingCertificates/res/locale/Resources.resx b/SettingCertificates/SettingCertificates/res/locale/Resources.resx new file mode 100644 index 0000000..07c961f --- /dev/null +++ b/SettingCertificates/SettingCertificates/res/locale/Resources.resx @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Owner + + + Certificate details + + + Certificate information + + + Certification authority: + + + Common name: + + + False + + + Issuer: + + + Issuer: + + + Key usage: + + + Organisation: + + + Public key: + + + Serial number: + + + Signature algorithm: + + + True + + + Trusted root CA certificates + + + User certificates + + + Valid from: + + + Valid to: + + + Version: + + + Manage certificates + + \ No newline at end of file diff --git a/SettingCertificates/SettingCertificates/tizen-manifest.xml b/SettingCertificates/SettingCertificates/tizen-manifest.xml index dfc3033..5f79a4c 100644 --- a/SettingCertificates/SettingCertificates/tizen-manifest.xml +++ b/SettingCertificates/SettingCertificates/tizen-manifest.xml @@ -1,23 +1,23 @@  - + - + SettingCertificates.png + + 4x4 + - - - http://tizen.org/privilege/systemsettings.admin + http://tizen.org/privilege/appmanager.launch - diff --git a/SettingCertificates/SettingView/SettingView.cs b/SettingCertificates/SettingView/SettingView.cs index 486cbd8..15c714f 100644 --- a/SettingCertificates/SettingView/SettingView.cs +++ b/SettingCertificates/SettingView/SettingView.cs @@ -1,12 +1,29 @@ -using System; +/* + * Copyright (c) 2022 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +using System; using Tizen.NUI; -using Tizen.NUI.BaseComponents; using Tizen.Applications; namespace SettingView { public class Program : NUIApplication { + + WidgetView mWidgetView; public Program(string styleSheet, Size2D windowSize, Position2D windowPosition, IBorderInterface borderInterface) : base(styleSheet, windowSize, windowPosition, borderInterface) { @@ -25,7 +42,7 @@ namespace SettingView Tizen.Log.Error("SettingWidget", "REQUEST \n"); - mWidgetView = WidgetViewManager.Instance.AddWidget("certificates@org.tizen.setting-certificates", encodedBundle, window.Size.Width, window.Size.Height, 0.0f); + mWidgetView = WidgetViewManager.Instance.AddWidget("certificates@org.tizen.cssetting-certificates", encodedBundle, window.Size.Width, window.Size.Height, 0.0f); mWidgetView.Position = new Position(0, 0); window.GetDefaultLayer().Add(mWidgetView); } @@ -45,7 +62,5 @@ namespace SettingView app.Run(args); } - - WidgetView mWidgetView; } } diff --git a/SettingCertificates/SettingView/SettingViewBorder.cs b/SettingCertificates/SettingView/SettingViewBorder.cs index 6b801c1..dcf5802 100644 --- a/SettingCertificates/SettingView/SettingViewBorder.cs +++ b/SettingCertificates/SettingView/SettingViewBorder.cs @@ -1,11 +1,21 @@ -using System; +/* + * Copyright (c) 2022 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ using Tizen.NUI; using Tizen.NUI.BaseComponents; -using Tizen.NUI.Components; - -using System.Collections.Generic; -using System.Text; namespace SettingView { diff --git a/SettingCertificates/SettingView/tizen-manifest.xml b/SettingCertificates/SettingView/tizen-manifest.xml index 0f90291..4dcf8af 100644 --- a/SettingCertificates/SettingView/tizen-manifest.xml +++ b/SettingCertificates/SettingView/tizen-manifest.xml @@ -1,5 +1,5 @@  - + diff --git a/packaging/org.tizen.setting-certificates-1.0.0.tpk b/packaging/org.tizen.cssetting-certificates-1.0.0.tpk similarity index 58% rename from packaging/org.tizen.setting-certificates-1.0.0.tpk rename to packaging/org.tizen.cssetting-certificates-1.0.0.tpk index fde5de721db4d06cee7f0c8757435d21df63884f..40a29680303e65b5a02def29d654e2d5e0e75292 100644 GIT binary patch delta 44977 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