├── .editorconfig
├── .gitignore
├── Arch.Standard.sln
├── LICENSE
├── NuGet.config
├── NuGetPackageVerifier.json
├── README.md
├── src
└── Arch.Standard
│ ├── ApiResult
│ ├── ApiResult.cs
│ └── IApiResult.cs
│ ├── Arch.Standard.csproj
│ ├── Cryptography
│ └── CryptoExtensions.cs
│ ├── Exceptions
│ ├── IStandardError.cs
│ └── StandardException.cs
│ ├── Extensions
│ ├── ByteArrayExtensions.cs
│ ├── HashExtensions.cs
│ └── StringExtensions.cs
│ ├── PagedList
│ ├── IOrderedQueryableExtensions.cs
│ ├── IPagedList.cs
│ └── PagedList.cs
│ └── Utils
│ ├── CryptoRandom.cs
│ └── Totp.cs
└── test
└── Arch.Standard.Tests
├── Arch.Standard.Tests.csproj
├── IPagedListTest.cs
└── IStandardErrorTests.cs
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig is awesome:http://EditorConfig.org
2 |
3 | # top-most EditorConfig file
4 | root = true
5 |
6 | # Don't use tabs for indentation.
7 | [*]
8 | indent_style = space
9 | # (Please don't specify an indent_size here; that has too many unintended consequences.)
10 |
11 | # Code files
12 | [*.{cs,csx,vb,vbx}]
13 | indent_size = 4
14 |
15 | # Xml project files
16 | [*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}]
17 | indent_size = 2
18 |
19 | # Xml config files
20 | [*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct}]
21 | indent_size = 2
22 |
23 | # JSON files
24 | [*.json]
25 | indent_size = 2
26 |
27 | # Dotnet code style settings:
28 | [*.{cs,vb}]
29 | # Sort using and Import directives with System.* appearing first
30 | dotnet_sort_system_directives_first = true
31 | # Avoid "this." and "Me." if not necessary
32 | dotnet_style_qualification_for_field = false:suggestion
33 | dotnet_style_qualification_for_property = false:suggestion
34 | dotnet_style_qualification_for_method = false:suggestion
35 | dotnet_style_qualification_for_event = false:suggestion
36 |
37 | # Use language keywords instead of framework type names for type references
38 | dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
39 | dotnet_style_predefined_type_for_member_access = true:suggestion
40 |
41 | # Suggest more modern language features when available
42 | dotnet_style_object_initializer = true:suggestion
43 | dotnet_style_collection_initializer = true:suggestion
44 | dotnet_style_coalesce_expression = true:suggestion
45 | dotnet_style_null_propagation = true:suggestion
46 | dotnet_style_explicit_tuple_names = true:suggestion
47 |
48 | # CSharp code style settings:
49 | [*.cs]
50 | # Prefer "var" everywhere
51 | csharp_style_var_for_built_in_types = true:suggestion
52 | csharp_style_var_when_type_is_apparent = true:suggestion
53 | csharp_style_var_elsewhere = true:suggestion
54 |
55 | # Prefer method-like constructs to have a block body
56 | csharp_style_expression_bodied_methods = true:suggestion
57 | csharp_style_expression_bodied_constructors = true:suggestion
58 | csharp_style_expression_bodied_operators = true:suggestion
59 |
60 | # Prefer property-like constructs to have an expression-body
61 | csharp_style_expression_bodied_properties = true:suggestion
62 | csharp_style_expression_bodied_indexers = true:suggestion
63 | csharp_style_expression_bodied_accessors = true:suggestion
64 |
65 | # Suggest more modern language features when available
66 | csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
67 | csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
68 | csharp_style_inlined_variable_declaration = true:suggestion
69 | csharp_style_throw_expression = true:suggestion
70 | csharp_style_conditional_delegate_call = true:suggestion
71 |
72 | # Newline settings
73 | csharp_new_line_before_open_brace = all
74 | csharp_new_line_before_else = true
75 | csharp_new_line_before_catch = true
76 | csharp_new_line_before_finally = true
77 | csharp_new_line_before_members_in_object_initializers = true
78 | csharp_new_line_before_members_in_anonymous_types = true
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | x64/
19 | x86/
20 | bld/
21 | [Bb]in/
22 | [Oo]bj/
23 | [Ll]og/
24 |
25 | # Visual Studio 2015 cache/options directory
26 | .vs/
27 | # Uncomment if you have tasks that create the project's static files in wwwroot
28 | #wwwroot/
29 |
30 | # MSTest test Results
31 | [Tt]est[Rr]esult*/
32 | [Bb]uild[Ll]og.*
33 |
34 | # NUNIT
35 | *.VisualState.xml
36 | TestResult.xml
37 |
38 | # Build Results of an ATL Project
39 | [Dd]ebugPS/
40 | [Rr]eleasePS/
41 | dlldata.c
42 |
43 | # DNX
44 | project.lock.json
45 | artifacts/
46 |
47 | *_i.c
48 | *_p.c
49 | *_i.h
50 | *.ilk
51 | *.meta
52 | *.obj
53 | *.pch
54 | *.pdb
55 | *.pgc
56 | *.pgd
57 | *.rsp
58 | *.sbr
59 | *.tlb
60 | *.tli
61 | *.tlh
62 | *.tmp
63 | *.tmp_proj
64 | *.log
65 | *.vspscc
66 | *.vssscc
67 | .builds
68 | *.pidb
69 | *.svclog
70 | *.scc
71 |
72 | # Chutzpah Test files
73 | _Chutzpah*
74 |
75 | # Visual C++ cache files
76 | ipch/
77 | *.aps
78 | *.ncb
79 | *.opendb
80 | *.opensdf
81 | *.sdf
82 | *.cachefile
83 | *.VC.db
84 | *.VC.VC.opendb
85 |
86 | # Visual Studio profiler
87 | *.psess
88 | *.vsp
89 | *.vspx
90 | *.sap
91 |
92 | # TFS 2012 Local Workspace
93 | $tf/
94 |
95 | # Guidance Automation Toolkit
96 | *.gpState
97 |
98 | # ReSharper is a .NET coding add-in
99 | _ReSharper*/
100 | *.[Rr]e[Ss]harper
101 | *.DotSettings.user
102 |
103 | # JustCode is a .NET coding add-in
104 | .JustCode
105 |
106 | # TeamCity is a build add-in
107 | _TeamCity*
108 |
109 | # DotCover is a Code Coverage Tool
110 | *.dotCover
111 |
112 | # NCrunch
113 | _NCrunch_*
114 | .*crunch*.local.xml
115 | nCrunchTemp_*
116 |
117 | # MightyMoose
118 | *.mm.*
119 | AutoTest.Net/
120 |
121 | # Web workbench (sass)
122 | .sass-cache/
123 |
124 | # Installshield output folder
125 | [Ee]xpress/
126 |
127 | # DocProject is a documentation generator add-in
128 | DocProject/buildhelp/
129 | DocProject/Help/*.HxT
130 | DocProject/Help/*.HxC
131 | DocProject/Help/*.hhc
132 | DocProject/Help/*.hhk
133 | DocProject/Help/*.hhp
134 | DocProject/Help/Html2
135 | DocProject/Help/html
136 |
137 | # Click-Once directory
138 | publish/
139 |
140 | # Publish Web Output
141 | *.[Pp]ublish.xml
142 | *.azurePubxml
143 | # TODO: Comment the next line if you want to checkin your web deploy settings
144 | # but database connection strings (with potential passwords) will be unencrypted
145 | *.pubxml
146 | *.publishproj
147 |
148 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
149 | # checkin your Azure Web App publish settings, but sensitive information contained
150 | # in these scripts will be unencrypted
151 | PublishScripts/
152 |
153 | # NuGet Packages
154 | *.nupkg
155 | # The packages folder can be ignored because of Package Restore
156 | **/packages/*
157 | # except build/, which is used as an MSBuild target.
158 | !**/packages/build/
159 | # Uncomment if necessary however generally it will be regenerated when needed
160 | #!**/packages/repositories.config
161 | # NuGet v3's project.json files produces more ignoreable files
162 | *.nuget.props
163 | *.nuget.targets
164 |
165 | # Microsoft Azure Build Output
166 | csx/
167 | *.build.csdef
168 |
169 | # Microsoft Azure Emulator
170 | ecf/
171 | rcf/
172 |
173 | # Windows Store app package directories and files
174 | AppPackages/
175 | BundleArtifacts/
176 | Package.StoreAssociation.xml
177 | _pkginfo.txt
178 |
179 | # Visual Studio cache files
180 | # files ending in .cache can be ignored
181 | *.[Cc]ache
182 | # but keep track of directories ending in .cache
183 | !*.[Cc]ache/
184 |
185 | # Others
186 | ClientBin/
187 | ~$*
188 | *~
189 | *.dbmdl
190 | *.dbproj.schemaview
191 | *.pfx
192 | *.publishsettings
193 | node_modules/
194 | orleans.codegen.cs
195 |
196 | # Since there are multiple workflows, uncomment next line to ignore bower_components
197 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
198 | #bower_components/
199 |
200 | # RIA/Silverlight projects
201 | Generated_Code/
202 |
203 | # Backup & report files from converting an old project file
204 | # to a newer Visual Studio version. Backup files are not needed,
205 | # because we have git ;-)
206 | _UpgradeReport_Files/
207 | Backup*/
208 | UpgradeLog*.XML
209 | UpgradeLog*.htm
210 |
211 | # SQL Server files
212 | *.mdf
213 | *.ldf
214 |
215 | # Business Intelligence projects
216 | *.rdl.data
217 | *.bim.layout
218 | *.bim_*.settings
219 |
220 | # Microsoft Fakes
221 | FakesAssemblies/
222 |
223 | # GhostDoc plugin setting file
224 | *.GhostDoc.xml
225 |
226 | # Node.js Tools for Visual Studio
227 | .ntvs_analysis.dat
228 |
229 | # Visual Studio 6 build log
230 | *.plg
231 |
232 | # Visual Studio 6 workspace options file
233 | *.opt
234 |
235 | # Visual Studio LightSwitch build output
236 | **/*.HTMLClient/GeneratedArtifacts
237 | **/*.DesktopClient/GeneratedArtifacts
238 | **/*.DesktopClient/ModelManifest.xml
239 | **/*.Server/GeneratedArtifacts
240 | **/*.Server/ModelManifest.xml
241 | _Pvt_Extensions
242 |
243 | # Paket dependency manager
244 | .paket/paket.exe
245 | paket-files/
246 |
247 | # FAKE - F# Make
248 | .fake/
249 |
250 | # JetBrains Rider
251 | .idea/
252 | *.sln.iml
253 |
--------------------------------------------------------------------------------
/Arch.Standard.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.26228.9
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Arch.Standard", "src\Arch.Standard\Arch.Standard.csproj", "{1895BE3B-7F81-471B-885D-FEE6025C81ED}"
7 | EndProject
8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{F4562D4D-A918-4EF2-B3B1-D9851A398978}"
9 | EndProject
10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{A857B0BB-30EE-4D4A-A688-CFC5EF7C027A}"
11 | EndProject
12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Arch.Standard.Tests", "test\Arch.Standard.Tests\Arch.Standard.Tests.csproj", "{BEEEEF3D-F7EE-4506-98DD-0F984D14BBC3}"
13 | EndProject
14 | Global
15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
16 | Debug|Any CPU = Debug|Any CPU
17 | Release|Any CPU = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
20 | {1895BE3B-7F81-471B-885D-FEE6025C81ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {1895BE3B-7F81-471B-885D-FEE6025C81ED}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 | {1895BE3B-7F81-471B-885D-FEE6025C81ED}.Release|Any CPU.ActiveCfg = Release|Any CPU
23 | {1895BE3B-7F81-471B-885D-FEE6025C81ED}.Release|Any CPU.Build.0 = Release|Any CPU
24 | {BEEEEF3D-F7EE-4506-98DD-0F984D14BBC3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
25 | {BEEEEF3D-F7EE-4506-98DD-0F984D14BBC3}.Debug|Any CPU.Build.0 = Debug|Any CPU
26 | {BEEEEF3D-F7EE-4506-98DD-0F984D14BBC3}.Release|Any CPU.ActiveCfg = Release|Any CPU
27 | {BEEEEF3D-F7EE-4506-98DD-0F984D14BBC3}.Release|Any CPU.Build.0 = Release|Any CPU
28 | EndGlobalSection
29 | GlobalSection(SolutionProperties) = preSolution
30 | HideSolutionNode = FALSE
31 | EndGlobalSection
32 | GlobalSection(NestedProjects) = preSolution
33 | {1895BE3B-7F81-471B-885D-FEE6025C81ED} = {F4562D4D-A918-4EF2-B3B1-D9851A398978}
34 | {BEEEEF3D-F7EE-4506-98DD-0F984D14BBC3} = {A857B0BB-30EE-4D4A-A688-CFC5EF7C027A}
35 | EndGlobalSection
36 | EndGlobal
37 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Arch
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/NuGet.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/NuGetPackageVerifier.json:
--------------------------------------------------------------------------------
1 | {
2 | "Default": {
3 | "rules": [
4 | "DefaultCompositeRule"
5 | ]
6 | }
7 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Standard
2 | This repo contains some core infrastructures for shared Standard domain/structure to be consumed across the Arch team's repos.
3 |
--------------------------------------------------------------------------------
/src/Arch.Standard/ApiResult/ApiResult.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Arch team. All rights reserved.
2 |
3 | namespace Arch.Standard
4 | {
5 | ///
6 | /// Represents the default implementation of the interface.
7 | ///
8 | public class ApiResult : IApiResult
9 | {
10 | ///
11 | /// Gets or sets the status code.
12 | ///
13 | /// The status code.
14 | public int StatusCode { get; set; }
15 |
16 | ///
17 | /// Gets or sets the message.
18 | ///
19 | /// The message.
20 | public string Message { get; set; }
21 | }
22 |
23 | ///
24 | /// Represents the default implementation of the interface.
25 | ///
26 | /// The type of the result.
27 | public class ApiResult : ApiResult, IApiResult
28 | {
29 | ///
30 | /// Initializes a new instance of the class.
31 | ///
32 | public ApiResult()
33 | {
34 |
35 | }
36 |
37 | ///
38 | /// Initializes a new instance of the class.
39 | ///
40 | /// The result.
41 | /// The status code.
42 | /// The message.
43 | public ApiResult(TResult result, int statusCode, string message)
44 | {
45 | StatusCode = statusCode;
46 | Message = message;
47 | Result = result;
48 | }
49 |
50 | ///
51 | /// Gets or sets the result.
52 | ///
53 | /// The result.
54 | public TResult Result { get; set; }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/Arch.Standard/ApiResult/IApiResult.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Arch team. All rights reserved.
2 |
3 | namespace Arch.Standard
4 | {
5 | ///
6 | /// Provides the interfaces for a empty api result.
7 | ///
8 | public interface IApiResult
9 | {
10 | ///
11 | /// Gets or sets the status code.
12 | ///
13 | /// The status code.
14 | int StatusCode { get; set; }
15 |
16 | ///
17 | /// Gets or sets the message.
18 | ///
19 | /// The message.
20 | string Message { get; set; }
21 | }
22 |
23 | ///
24 | /// Provides the interfaces for a generic api result.
25 | ///
26 | ///
27 | public interface IApiResult : IApiResult
28 | {
29 | ///
30 | /// Gets or sets the result.
31 | ///
32 | /// The result.
33 | TResult Result { get; set; }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/Arch.Standard/Arch.Standard.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | This library contains some core infrastructures for shared Standard domain/structure to be consumed across the Arch team's libraries.
4 | 1.0.0
5 | rigofunc;rigofunc@outlook.com
6 | net461;netstandard1.6
7 | $(NoWarn);CS1591
8 | true
9 | true
10 | totp;apiresult;arch
11 | https://github.com/Arch/Standard
12 | https://github.com/Arch/Standard/blob/master/LICENSE
13 | git
14 | https://github.com/Arch/Standard.git
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/src/Arch.Standard/Cryptography/CryptoExtensions.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Arch team. All rights reserved.
2 |
3 | using System.Text;
4 | using System.Security.Cryptography;
5 | #if NET461
6 | using System.IO;
7 | #else
8 | using Org.BouncyCastle.Crypto.Engines;
9 | using Org.BouncyCastle.Crypto.Modes;
10 | using Org.BouncyCastle.Crypto.Paddings;
11 | using Org.BouncyCastle.Crypto.Parameters;
12 | #endif
13 |
14 | namespace Arch.Standard
15 | {
16 | ///
17 | /// Provides some extension methods for FCL encrpt and desrypt functionality.
18 | ///
19 | public static class CryptoExtensions
20 | {
21 | ///
22 | /// Encrypts the specified use triple DES.
23 | ///
24 | /// The input to encrypt.
25 | /// The encrypted result.
26 | public static byte[] TripleDesEncrypt(this byte[] input)
27 | {
28 | return default(byte[]);
29 | }
30 |
31 | ///
32 | /// Decrypts the specified use triple DES.
33 | ///
34 | /// The input to descrypt.
35 | /// The descrypted result.
36 | public static byte[] TripleDESDecrypt(this byte[] input)
37 | {
38 | return default(byte[]);
39 | }
40 |
41 | ///
42 | /// Encrypts the specified use DES.
43 | ///
44 | /// The input to encrypt.
45 | /// The key.
46 | /// The IV.
47 | /// The cipher mode.
48 | /// The padding mode.
49 | /// The encrypted result.
50 | public static byte[] DesEncrypt(this byte[] input, byte[] key, byte[] iv, CipherMode mode = CipherMode.CBC, PaddingMode paddingMode = PaddingMode.Zeros)
51 | {
52 | #if NET461
53 | var des = new DESCryptoServiceProvider()
54 | {
55 | Key = key,
56 | IV = iv,
57 | Mode = mode,
58 | Padding = paddingMode
59 | };
60 |
61 | using(var ms = new MemoryStream())
62 | {
63 | using(var cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write))
64 | {
65 | cs.Write(input, 0, input.Length);
66 | cs.FlushFinalBlock();
67 | return ms.ToArray();
68 | }
69 | }
70 | #else
71 | var engine = new DesEngine();
72 | var cipher = new PaddedBufferedBlockCipher(new CbcBlockCipher(engine), new ZeroBytePadding());
73 | cipher.Init(true, new ParametersWithIV(new DesParameters(key), iv));
74 | var rv = new byte[cipher.GetOutputSize(input.Length)];
75 | var tam = cipher.ProcessBytes(input, 0, input.Length, rv, 0);
76 | cipher.DoFinal(rv, tam);
77 |
78 | return rv;
79 | #endif
80 | }
81 |
82 | ///
83 | /// Encrypts the specified use DES.
84 | ///
85 | /// The input to encrypt.
86 | /// The key.
87 | /// The IV.
88 | /// The encoding, the default value is gb2312
89 | /// The encrypted result.
90 | public static byte[] DesEncrypt(this string input, byte[] key, byte[] iv, string encoding="gb2312") => Encoding.GetEncoding(encoding).GetBytes(input).DesEncrypt(key, iv);
91 |
92 | ///
93 | /// Decrypts the specified use DES.
94 | ///
95 | /// The input to encrypt.
96 | /// The key.
97 | /// The IV.
98 | /// The cipher mode.
99 | /// The padding mode.
100 | /// The descrypted result.
101 | public static byte[] DESDecrypt(this byte[] input, byte[] key, byte[] iv, CipherMode mode = CipherMode.CBC, PaddingMode paddingMode = PaddingMode.Zeros)
102 | {
103 | #if NET461
104 | var des = new DESCryptoServiceProvider()
105 | {
106 | Key = key,
107 | IV = iv,
108 | Mode = mode,
109 | Padding = paddingMode
110 | };
111 |
112 | using (var ms = new MemoryStream())
113 | {
114 | using (var cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write))
115 | {
116 | cs.Write(input, 0, input.Length);
117 | cs.FlushFinalBlock();
118 | return ms.ToArray();
119 | }
120 | }
121 | #else
122 | var engine = new DesEngine();
123 | var cipher = new PaddedBufferedBlockCipher(new CbcBlockCipher(engine), new ZeroBytePadding());
124 | cipher.Init(false, new ParametersWithIV(new DesParameters(key), iv));
125 | var rv = new byte[cipher.GetOutputSize(input.Length)];
126 | var tam = cipher.ProcessBytes(input, 0, input.Length, rv, 0);
127 |
128 | cipher.DoFinal(rv, tam);
129 |
130 | return rv;
131 | #endif
132 | }
133 |
134 | ///
135 | /// Decrypts the specified use DES.
136 | ///
137 | /// The input to encrypt.
138 | /// The key.
139 | /// The IV.
140 | /// The encoding, the default value is gb2312
141 | /// The descrypted result.
142 | public static byte[] DESDecrypt(this string input, byte[] key, byte[] iv, string encoding = "gb2312") => Encoding.GetEncoding(encoding).GetBytes(input).DESDecrypt(key, iv);
143 | }
144 | }
145 |
--------------------------------------------------------------------------------
/src/Arch.Standard/Exceptions/IStandardError.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Arch team. All rights reserved.
2 |
3 | using System.Collections.Generic;
4 |
5 | namespace Arch.Standard
6 | {
7 | ///
8 | /// Defines the interface(s) for invoke error.
9 | ///
10 | ///
11 | /// The value for the "code" name/value pair is a language-independent string.
12 | /// Its value is a service-defined error code that SHOULD be human-readable.
13 | ///
14 | /// The value for the "message" name/value pair MUST be a human-readable representation of the error.
15 | /// It is intended as an aid to developers and is not suitable for exposure to end users.
16 | ///
17 | /// The value for the "target" name/value pair is the target of the particular error
18 | /// (e.g., the name of the property in error).
19 | ///
20 | /// The value for the "details" name/value pair MUST be an array of JSON objects that MUST contain name/value pairs for "code"
21 | /// and "message," and MAY contain a name/value pair for "target," as described above.
22 | ///
23 | /// The value for the "innererror" name/value pair MUST be an object.
24 | /// The contents of this object are service-defined. Services wanting to return more specific errors
25 | /// than the root-level code MUST do so by including a name/value pair for "code" and a nested "innererror."
26 | /// Each nested "innererror" object represents a higher level of detail than its parent.
27 | ///
28 | public interface IStandardError
29 | {
30 | ///
31 | /// Gets or sets the code for this error.
32 | ///
33 | ///
34 | /// The code for this error.
35 | ///
36 | string Code { get; set; }
37 | ///
38 | /// Gets or sets the message for this error.
39 | ///
40 | ///
41 | /// The message for this error.
42 | ///
43 | string Message { get; set; }
44 | ///
45 | /// Gets or sets the target of the particular error (e.g., the name of the property in error).
46 | ///
47 | /// The target of the particular error.
48 | string Target { get; set; }
49 | ///
50 | /// An object containing more specific information than the current object about the error.
51 | ///
52 | /// The inner error.
53 | IStandardError InnerError { get; set; }
54 | ///
55 | /// Gets or sets the details for this error.
56 | ///
57 | /// The details for this error.
58 | IEnumerable Details { get; set; }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/Arch.Standard/Exceptions/StandardException.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Arch team. All rights reserved.
2 |
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Runtime.CompilerServices;
6 |
7 | namespace Arch.Standard
8 | {
9 | ///
10 | /// Represents an exception, which implements the interface.
11 | ///
12 | public class StandardException : Exception, IStandardError
13 | {
14 | private string _message;
15 | private List _details = new List();
16 |
17 | ///
18 | /// Creates an indicating a failed invoke operation, with a if applicable.
19 | ///
20 | /// The code to represents the error.
21 | /// An message which description caused the operation to fail.
22 | /// The target of the particular error (e.g., the name of the property in error), the default value is the calloer member name
23 | /// An indicating a failed invoke operation, with a if applicable.
24 | public static StandardException Caused(string code, string message, [CallerMemberName]string target = null) => new StandardException
25 | {
26 | Code = code,
27 | Message = message,
28 | Target = target,
29 | };
30 |
31 | ///
32 | /// Gets or sets the code for this error.
33 | ///
34 | ///
35 | /// The code for this error.
36 | ///
37 | public string Code { get; set; }
38 |
39 | ///
40 | /// Gets or sets the message for this error.
41 | ///
42 | ///
43 | /// The message for this error.
44 | ///
45 | public new string Message
46 | {
47 | get
48 | {
49 | if (string.IsNullOrEmpty(_message))
50 | {
51 | return base.Message;
52 | }
53 |
54 | return _message;
55 | }
56 | set => _message = value;
57 | }
58 |
59 | ///
60 | /// Gets or sets the target of the particular error (e.g., the name of the property in error).
61 | ///
62 | /// The target of the particular error.
63 | public string Target { get; set; }
64 |
65 | ///
66 | /// Gets or sets the details for this error.
67 | ///
68 | /// The details for this error.
69 | public IEnumerable Details
70 | {
71 | get => _details;
72 | set
73 | {
74 | if (value != null)
75 | {
76 | _details.Clear();
77 | _details.AddRange(value);
78 | }
79 | }
80 | }
81 |
82 | ///
83 | /// Gets or sets the inner error for this error.
84 | ///
85 | /// The inner error for this error.
86 | public IStandardError InnerError { get; set; }
87 |
88 | ///
89 | /// Throws this exception.
90 | ///
91 | public void Throw() => throw this;
92 |
93 | ///
94 | /// Appends an array of represents the details to current .
95 | ///
96 | /// The array of represents the details.
97 | /// Return the current instance for supporting fluent API feature.
98 | public StandardException Append(params IStandardError[] details)
99 | {
100 | if (details.Length > 0)
101 | {
102 | _details.AddRange(details);
103 | }
104 |
105 | // this for fluent API use
106 | // InvokeError.Caused(message).Append(details).Throw();
107 | return this;
108 | }
109 |
110 | ///
111 | /// Appends an to current .
112 | ///
113 | /// The represents the details.
114 | /// Return the current instance for supporting fluent API feature.
115 | public StandardException Concat(Exception exception)
116 | {
117 | var error = new StandardException
118 | {
119 | Code = "excption",
120 | Message = exception.ToString(),
121 | };
122 |
123 | _details.Add(error);
124 |
125 | // this for fluent API use
126 | // InvokeError.Caused(message).Append(details).Throw();
127 | return this;
128 | }
129 |
130 | ///
131 | /// Appends an array of represents the details to current .
132 | ///
133 | /// The array of represents the details.
134 | /// Return the current instance for supporting fluent API feature.
135 | public StandardException Append(IEnumerable details)
136 | {
137 | if (details != null)
138 | {
139 | _details.AddRange(details);
140 | }
141 |
142 | return this;
143 | }
144 |
145 | ///
146 | /// Returns a that represents this instance.
147 | ///
148 | /// A that represents this instance.
149 | public override string ToString()
150 | {
151 | if(string.IsNullOrEmpty(Code) || string.IsNullOrEmpty(_message))
152 | {
153 | return base.ToString();
154 | }
155 |
156 | if (_details.Count == 0)
157 | {
158 | return $"{"{ "}\"Code\": \"{Code}\", \"Message\": \"{Message}\", \"Target\": \"{Target}\"{" }"}";
159 | }
160 | else
161 | {
162 | return $"{"{ "}\"Code\": \"{Code}\", \"Message\": \"{Message}\", \"Details\": [{string.Join(",", _details)}]{" }"}";
163 | }
164 | }
165 | }
166 | }
167 |
--------------------------------------------------------------------------------
/src/Arch.Standard/Extensions/ByteArrayExtensions.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Arch team. All rights reserved.
2 |
3 | using System;
4 | using System.Text;
5 |
6 | namespace Arch.Standard
7 | {
8 | ///
9 | /// Provides some extension methods for byte[].
10 | ///
11 | public static class ByteArrayExtensions
12 | {
13 | ///
14 | /// Converts to base64 string.
15 | ///
16 | /// The input to convert.
17 | /// The base64 string.
18 | public static string ToBase64String(this byte[] input) => Convert.ToBase64String(input);
19 |
20 | ///
21 | /// Converts to base64 string and replace it's '+' to '-', '/' to '_' and '=' to '%3d'.
22 | ///
23 | /// The input to convert
24 | /// The base64 string and replace it's '+' to '-', '/' to '_' and '=' to '%3d'
25 | public static string ToUrlSuitable(this byte[] input) => input.ToBase64String().Replace("+", "-").Replace("/", "_").Replace("=", "%3d");
26 |
27 | ///
28 | /// Converts byte array to hex string.
29 | ///
30 | /// The bytes to convert.
31 | /// The hex string.
32 | public static string ToHexString(this byte[] bytes)
33 | {
34 | var hex = new StringBuilder(bytes.Length * 2);
35 | foreach (var b in bytes)
36 | {
37 | hex.AppendFormat("{0:x2}", b);
38 | }
39 |
40 | return hex.ToString();
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/Arch.Standard/Extensions/HashExtensions.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Arch team. All rights reserved.
2 |
3 | using System.Security.Cryptography;
4 | using System.Text;
5 |
6 | namespace Arch.Standard
7 | {
8 | ///
9 | /// Provides some extension methods for string hashing.
10 | ///
11 | public static class HashExtensions
12 | {
13 | private static byte[] _empty = new byte[0];
14 |
15 | ///
16 | /// Creates the hash of the by the specified and .
17 | ///
18 | /// The plain text to hash.
19 | /// The hash algorithm, if specify null, will use MD5 algorithm.
20 | /// The encoding, the default value is gb2312
21 | /// The hashed value.
22 | public static byte[] Hash(this string plainText, HashAlgorithm hashAlgorithm, string encoding = "gb2312")
23 | {
24 | // get bytes from the plaintext
25 | var bytes = Encoding.GetEncoding(encoding).GetBytes(plainText);
26 |
27 | // encrypt
28 | using (var algorithm = hashAlgorithm ?? System.Security.Cryptography.MD5.Create())
29 | {
30 | return algorithm.ComputeHash(bytes);
31 | }
32 | }
33 |
34 | ///
35 | /// Creates a MD5 hash of the specified input.
36 | ///
37 | /// The input.
38 | /// The encoding, the default value is gb2312
39 | /// The MD5 hash of the specified .
40 | public static byte[] MD5(this string input, string encoding = "gb2312")
41 | {
42 | if (string.IsNullOrEmpty(input))
43 | return _empty;
44 |
45 | return Hash(input, System.Security.Cryptography.MD5.Create(), encoding);
46 | }
47 |
48 | ///
49 | /// Creates a SHA512 hash of the specified input.
50 | ///
51 | /// The input.
52 | /// The encoding, the default value is gb2312
53 | /// The SHA512 hash of the specified , the value is base64 string.
54 | public static byte[] Sha512(this string input, string encoding = "gb2312")
55 | {
56 | if (string.IsNullOrEmpty(input))
57 | return _empty;
58 |
59 | return Hash(input, SHA512.Create(), encoding);
60 | }
61 |
62 | ///
63 | /// Creates a SHA256 hash of the specified input.
64 | ///
65 | /// The input.
66 | /// The encoding, the default value is gb2312
67 | /// The SHA256 hash of the specified , the value is base64 string.
68 | public static byte[] Sha256(this string input, string encoding = "gb2312")
69 | {
70 | if (string.IsNullOrEmpty(input))
71 | return _empty;
72 |
73 | return Hash(input, SHA256.Create());
74 | }
75 |
76 | ///
77 | /// Creates a SHA1 hash of the specified input.
78 | ///
79 | /// The input.
80 | /// The encoding, the default value is gb2312
81 | /// The hashed value.
82 | public static byte[] Sha1(this string input, string encoding = "gb2312")
83 | {
84 | if (string.IsNullOrEmpty(input))
85 | return _empty;
86 |
87 | return Hash(input, SHA1.Create());
88 | }
89 |
90 | ///
91 | /// Creates a SHA256 hash of the specified input.
92 | ///
93 | /// The input.
94 | /// The SHA256 hash of the specified .
95 | public static byte[] Sha256(this byte[] input)
96 | {
97 | if (input == null)
98 | {
99 | return null;
100 | }
101 |
102 | using (var sha = SHA256.Create())
103 | {
104 | return sha.ComputeHash(input);
105 | }
106 | }
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/src/Arch.Standard/Extensions/StringExtensions.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Arch team. All rights reserved.
2 |
3 | using System;
4 | using System.Text;
5 |
6 | namespace Arch.Standard
7 | {
8 | ///
9 | /// Provides some extension methods for
10 | ///
11 | public static class StringExtensions
12 | {
13 | ///
14 | /// Removes trim string from the current String object.
15 | ///
16 | /// current string object
17 | /// trim string object
18 | ///
19 | ///
20 | public static string TrimStart(this string source, string trim, StringComparison stringComparison = StringComparison.Ordinal)
21 | {
22 | if (source == null)
23 | {
24 | return null;
25 | }
26 |
27 | string s = source;
28 | while (s.StartsWith(trim, stringComparison))
29 | {
30 | s = s.Substring(trim.Length);
31 | }
32 |
33 | return s;
34 | }
35 |
36 | ///
37 | /// Removes trim string from the current String object.
38 | ///
39 | ///
40 | ///
41 | ///
42 | public static string TrimAfter(this string source, string trim)
43 | {
44 | int index = source.IndexOf(trim, StringComparison.Ordinal);
45 | if (index > 0)
46 | {
47 | source = source.Substring(0, index);
48 | }
49 |
50 | return source;
51 | }
52 |
53 | ///
54 | /// Escapes the string for MySQL.
55 | ///
56 | /// The value to escape
57 | /// The string with all quotes escaped.
58 | public static string MySQLEscape(this string value)
59 | {
60 | if (!IsQuoting(value))
61 | return value;
62 |
63 | var sb = new StringBuilder();
64 | foreach (var c in value)
65 | {
66 | var charClass = charClassArray[c];
67 | if (charClass != CharKinds.None)
68 | {
69 | sb.Append("\\");
70 | }
71 | sb.Append(c);
72 | }
73 |
74 | return sb.ToString();
75 | }
76 |
77 | #region MySQLEscape Helpers
78 |
79 | enum CharKinds : byte
80 | {
81 | None,
82 | Quote,
83 | Backslash
84 | }
85 |
86 | private static string backslashChars = "\u005c\u00a5\u0160\u20a9\u2216\ufe68\uff3c";
87 | private static string quoteChars = "\u0022\u0027\u0060\u00b4\u02b9\u02ba\u02bb\u02bc\u02c8\u02ca\u02cb\u02d9\u0300\u0301\u2018\u2019\u201a\u2032\u2035\u275b\u275c\uff07";
88 |
89 | private static CharKinds[] charClassArray = MakeCharClassArray();
90 |
91 | private static CharKinds[] MakeCharClassArray()
92 | {
93 |
94 | var a = new CharKinds[65536];
95 | foreach (var c in backslashChars)
96 | {
97 | a[c] = CharKinds.Backslash;
98 | }
99 | foreach (var c in quoteChars)
100 | {
101 | a[c] = CharKinds.Quote;
102 | }
103 |
104 | return a;
105 | }
106 |
107 | private static bool IsQuoting(string str)
108 | {
109 | foreach (var c in str)
110 | {
111 | if (charClassArray[c] != CharKinds.None)
112 | {
113 | return true;
114 | }
115 | }
116 |
117 | return false;
118 | }
119 |
120 | #endregion
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/src/Arch.Standard/PagedList/IOrderedQueryableExtensions.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Arch team. All rights reserved.
2 |
3 | using System.Collections.Generic;
4 | using Arch.Standard;
5 |
6 | namespace System.Linq
7 | {
8 | ///
9 | /// Provides some extension methods for to provide paging capability.
10 | ///
11 | public static class IOrderedQueryableExtensions
12 | {
13 | ///
14 | /// Converts the specified source to by the specified and .
15 | ///
16 | /// The type of the source.
17 | /// The source to paging.
18 | /// The index of the page.
19 | /// The size of the page.
20 | /// The start index value.
21 | /// An instance of the inherited from interface.
22 | public static IPagedList ToPagedList(this IOrderedQueryable source, int pageIndex, int pageSize, int indexFrom = 0) => new PagedList(source, pageIndex, pageSize, indexFrom);
23 |
24 | ///
25 | /// Converts the specified source to by the specified , and
26 | ///
27 | /// The type of the source.
28 | /// The type of the result
29 | /// The source to convert.
30 | /// The converter to change the to .
31 | /// The page index.
32 | /// The page size.
33 | /// The start index value.
34 | /// An instance of the inherited from interface.
35 | public static IPagedList ToPagedList(this IOrderedQueryable source, Func, IEnumerable> converter, int pageIndex, int pageSize, int indexFrom = 0) => new PagedList(source, converter, pageIndex, pageSize, indexFrom);
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/Arch.Standard/PagedList/IPagedList.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Arch team. All rights reserved.
2 |
3 | using System.Collections.Generic;
4 |
5 | namespace Arch.Standard
6 | {
7 | ///
8 | /// Provides the interface(s) for paged list of any type.
9 | ///
10 | /// The type for paging.
11 | public interface IPagedList
12 | {
13 | ///
14 | /// Gets the index start value.
15 | ///
16 | /// The index start value.
17 | int IndexFrom { get; }
18 | ///
19 | /// Gets the page index (current).
20 | ///
21 | int PageIndex { get; }
22 | ///
23 | /// Gets the page size.
24 | ///
25 | int PageSize { get; }
26 | ///
27 | /// Gets the total count of the list of type
28 | ///
29 | int TotalCount { get; }
30 | ///
31 | /// Gets the total pages.
32 | ///
33 | int TotalPages { get; }
34 | ///
35 | /// Gets the current page items.
36 | ///
37 | IList Items { get; }
38 | ///
39 | /// Gets the has previous page.
40 | ///
41 | /// The has previous page.
42 | bool HasPreviousPage { get; }
43 |
44 | ///
45 | /// Gets the has next page.
46 | ///
47 | /// The has next page.
48 | bool HasNextPage { get; }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/Arch.Standard/PagedList/PagedList.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Arch team. All rights reserved.
2 |
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 |
7 | namespace Arch.Standard
8 | {
9 | ///
10 | /// Represents the default implementation of the interface.
11 | ///
12 | /// The type of the data to page
13 | public class PagedList : IPagedList
14 | {
15 | ///
16 | /// Gets or sets the index of the page.
17 | ///
18 | /// The index of the page.
19 | public int PageIndex { get; set; }
20 | ///
21 | /// Gets or sets the size of the page.
22 | ///
23 | /// The size of the page.
24 | public int PageSize { get; set; }
25 | ///
26 | /// Gets or sets the total count.
27 | ///
28 | /// The total count.
29 | public int TotalCount { get; set; }
30 | ///
31 | /// Gets or sets the total pages.
32 | ///
33 | /// The total pages.
34 | public int TotalPages { get; set; }
35 | ///
36 | /// Gets or sets the index from.
37 | ///
38 | /// The index from.
39 | public int IndexFrom { get; set; }
40 |
41 | ///
42 | /// Gets or sets the items.
43 | ///
44 | /// The items.
45 | public IList Items { get; set; }
46 |
47 | ///
48 | /// Gets the has previous page.
49 | ///
50 | /// The has previous page.
51 | public bool HasPreviousPage => PageIndex - IndexFrom > 0;
52 |
53 | ///
54 | /// Gets the has next page.
55 | ///
56 | /// The has next page.
57 | public bool HasNextPage => PageIndex - IndexFrom + 1 < TotalPages;
58 |
59 | ///
60 | /// Initializes a new instance of the class.
61 | ///
62 | /// The source.
63 | /// The index of the page.
64 | /// The size of the page.
65 | /// The index from.
66 | internal PagedList(IOrderedQueryable source, int pageIndex, int pageSize, int indexFrom)
67 | {
68 | if (indexFrom > pageIndex)
69 | {
70 | throw new ArgumentException($"indexFrom: {indexFrom} > pageIndex: {pageIndex}, must indexFrom <= pageIndex");
71 | }
72 |
73 | PageIndex = pageIndex;
74 | PageSize = pageSize;
75 | IndexFrom = indexFrom;
76 | TotalCount = source.Count();
77 | TotalPages = (int)Math.Ceiling(TotalCount / (double)PageSize);
78 |
79 | Items = source.Skip((PageIndex - IndexFrom) * PageSize).Take(PageSize).ToList();
80 | }
81 |
82 | ///
83 | /// Initializes a new instance of the class.
84 | ///
85 | internal PagedList() => Items = new T[0];
86 | }
87 |
88 | ///
89 | /// Provides the implementation of the and converter.
90 | ///
91 | /// The type of the source.
92 | /// The type of the result.
93 | internal class PagedList : IPagedList
94 | {
95 | ///
96 | /// Gets the index of the page.
97 | ///
98 | /// The index of the page.
99 | public int PageIndex { get; }
100 | ///
101 | /// Gets the size of the page.
102 | ///
103 | /// The size of the page.
104 | public int PageSize { get; }
105 | ///
106 | /// Gets the total count.
107 | ///
108 | /// The total count.
109 | public int TotalCount { get; }
110 | ///
111 | /// Gets the total pages.
112 | ///
113 | /// The total pages.
114 | public int TotalPages { get; }
115 | ///
116 | /// Gets the index from.
117 | ///
118 | /// The index from.
119 | public int IndexFrom { get; }
120 |
121 | ///
122 | /// Gets the items.
123 | ///
124 | /// The items.
125 | public IList Items { get; }
126 |
127 | ///
128 | /// Gets the has previous page.
129 | ///
130 | /// The has previous page.
131 | public bool HasPreviousPage => PageIndex - IndexFrom > 0;
132 |
133 | ///
134 | /// Gets the has next page.
135 | ///
136 | /// The has next page.
137 | public bool HasNextPage => PageIndex - IndexFrom + 1 < TotalPages;
138 |
139 | ///
140 | /// Initializes a new instance of the class.
141 | ///
142 | /// The source.
143 | /// The converter.
144 | /// The index of the page.
145 | /// The size of the page.
146 | /// The index from.
147 | public PagedList(IOrderedQueryable source, Func, IEnumerable> converter, int pageIndex, int pageSize, int indexFrom)
148 | {
149 | if (indexFrom > pageIndex)
150 | {
151 | throw new ArgumentException($"indexFrom: {indexFrom} > pageIndex: {pageIndex}, must indexFrom <= pageIndex");
152 | }
153 |
154 | PageIndex = pageIndex;
155 | PageSize = pageSize;
156 | IndexFrom = indexFrom;
157 | TotalCount = source.Count();
158 | TotalPages = (int)Math.Ceiling(TotalCount / (double)PageSize);
159 |
160 | var items = source.Skip((PageIndex - IndexFrom) * PageSize).Take(PageSize).ToArray();
161 |
162 | Items = new List(converter(items));
163 | }
164 |
165 | ///
166 | /// Initializes a new instance of the class.
167 | ///
168 | /// The source.
169 | /// The converter.
170 | public PagedList(IPagedList source, Func, IEnumerable> converter)
171 | {
172 | PageIndex = source.PageIndex;
173 | PageSize = source.PageSize;
174 | IndexFrom = source.IndexFrom;
175 | TotalCount = source.TotalCount;
176 | TotalPages = source.TotalPages;
177 |
178 | Items = new List(converter(source.Items));
179 | }
180 | }
181 |
182 | ///
183 | /// Provides some help methods for interface.
184 | ///
185 | public static class PagedList
186 | {
187 | ///
188 | /// Creates an empty of .
189 | ///
190 | /// The type for paging
191 | /// An empty instance of .
192 | public static IPagedList Empty() => new PagedList();
193 | ///
194 | /// Creates a new instance of from source of instance.
195 | ///
196 | /// The type of the result.
197 | /// The type of the source.
198 | /// The source.
199 | /// The converter.
200 | /// An instance of .
201 | public static IPagedList From(IPagedList source, Func, IEnumerable> converter) => new PagedList(source, converter);
202 | }
203 | }
204 |
--------------------------------------------------------------------------------
/src/Arch.Standard/Utils/CryptoRandom.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Arch team. All rights reserved.
2 |
3 | using System;
4 | using System.Text;
5 | using System.Security.Cryptography;
6 |
7 | namespace Arch.Standard.Utils
8 | {
9 | ///
10 | /// Provides the random utility which internal use random cryptography to implements the functionality.
11 | ///
12 | public class CryptoRandom
13 | {
14 | private static RandomNumberGenerator _rng = RandomNumberGenerator.Create();
15 |
16 | ///
17 | /// Creates a random bytes, which's length specified by .
18 | ///
19 | /// The length of the bytes.
20 | /// The random bytes.
21 | public static byte[] CreateRandomBytes(int length)
22 | {
23 | var bytes = new byte[length];
24 | _rng.GetBytes(bytes);
25 |
26 | return bytes;
27 | }
28 |
29 | ///
30 | /// Creates a random key, which's length specified by the .
31 | ///
32 | /// The length of the key.
33 | /// A random key, which's length specified by the .
34 | public static string CreateRandomKey(int length)
35 | {
36 | var bytes = new byte[length];
37 | _rng.GetBytes(bytes);
38 |
39 | return Convert.ToBase64String(CreateRandomBytes(length));
40 | }
41 |
42 | ///
43 | /// Creates an unique key by the specified length.
44 | ///
45 | /// The length of key.
46 | /// The unique key.
47 | public static string CreateUniqueKey(int length = 8) => CreateRandomBytes(length).ToHexString();
48 |
49 | ///
50 | /// Creates a series number prefix by and yyyyMMddHHmmss.
51 | ///
52 | /// The prefix of the series number.
53 | ///
54 | public static string CreateSeriesNumber(string prefix = "SW") => $"{prefix}{DateTime.Now.ToString("yyyyMMddHHmmss")}{CreateUniqueKey()}";
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/Arch.Standard/Utils/Totp.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Arch team. All rights reserved.
2 |
3 | using System;
4 | using System.Diagnostics;
5 | using System.Net;
6 | using System.Security.Cryptography;
7 | using System.Text;
8 |
9 | namespace Arch.Standard.Utils
10 | {
11 | ///
12 | /// https://tools.ietf.org/html/rfc6238
13 | ///
14 | public static class Totp
15 | {
16 | private static readonly DateTime _unixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
17 | private static TimeSpan _timestep = TimeSpan.FromMinutes(3);
18 | private static readonly Encoding _encoding = new UTF8Encoding(false, true);
19 |
20 | private static int ComputeTotp(HashAlgorithm hashAlgorithm, ulong timestepNumber, string modifier)
21 | {
22 | // # of 0's = length of pin
23 | const int Mod = 1000000;
24 |
25 | // See https://tools.ietf.org/html/rfc4226
26 | // We can add an optional modifier
27 | var timestepAsBytes = BitConverter.GetBytes(IPAddress.HostToNetworkOrder((long)timestepNumber));
28 | var hash = hashAlgorithm.ComputeHash(ApplyModifier(timestepAsBytes, modifier));
29 |
30 | // Generate DT string
31 | var offset = hash[hash.Length - 1] & 0xf;
32 | Debug.Assert(offset + 4 < hash.Length);
33 | var binaryCode = (hash[offset] & 0x7f) << 24
34 | | (hash[offset + 1] & 0xff) << 16
35 | | (hash[offset + 2] & 0xff) << 8
36 | | (hash[offset + 3] & 0xff);
37 |
38 | return binaryCode % Mod;
39 | }
40 |
41 | private static byte[] ApplyModifier(byte[] input, string modifier)
42 | {
43 | if (string.IsNullOrEmpty(modifier))
44 | {
45 | return input;
46 | }
47 |
48 | var modifierBytes = _encoding.GetBytes(modifier);
49 | var combined = new byte[checked(input.Length + modifierBytes.Length)];
50 | Buffer.BlockCopy(input, 0, combined, 0, input.Length);
51 | Buffer.BlockCopy(modifierBytes, 0, combined, input.Length, modifierBytes.Length);
52 | return combined;
53 | }
54 |
55 | // More info: https://tools.ietf.org/html/rfc6238#section-4
56 | private static ulong GetCurrentTimeStepNumber()
57 | {
58 | var delta = DateTime.UtcNow - _unixEpoch;
59 | return (ulong)(delta.Ticks / _timestep.Ticks);
60 | }
61 |
62 | ///
63 | /// Generates code for the specified .
64 | ///
65 | /// The security token to generate code.
66 | /// The modifier.
67 | /// The generated code.
68 | public static int GenerateCode(byte[] securityToken, string modifier = null)
69 | {
70 | if (securityToken == null)
71 | {
72 | throw new ArgumentNullException(nameof(securityToken));
73 | }
74 |
75 | // Allow a variance of no greater than 90 seconds in either direction
76 | var currentTimeStep = GetCurrentTimeStepNumber();
77 | using (var hashAlgorithm = new HMACSHA1(securityToken))
78 | {
79 | return ComputeTotp(hashAlgorithm, currentTimeStep, modifier);
80 | }
81 | }
82 |
83 | ///
84 | /// Validates the code for the specified .
85 | ///
86 | /// The security token for verifying.
87 | /// The code to validate.
88 | /// The modifier
89 | /// True if validate succeed, otherwise, false.
90 | public static bool ValidateCode(byte[] securityToken, int code, string modifier = null)
91 | {
92 | if (securityToken == null)
93 | {
94 | throw new ArgumentNullException(nameof(securityToken));
95 | }
96 |
97 | // Allow a variance of no greater than 90 seconds in either direction
98 | var currentTimeStep = GetCurrentTimeStepNumber();
99 | using (var hashAlgorithm = new HMACSHA1(securityToken))
100 | {
101 | for (var i = -2; i <= 2; i++)
102 | {
103 | var computedTotp = ComputeTotp(hashAlgorithm, (ulong)((long)currentTimeStep + i), modifier);
104 | if (computedTotp == code)
105 | {
106 | return true;
107 | }
108 | }
109 | }
110 |
111 | // No match
112 | return false;
113 | }
114 |
115 | ///
116 | /// Generates code for the specified .
117 | ///
118 | /// The security token to generate code.
119 | /// The modifier.
120 | /// The generated code.
121 | public static int GenerateCode(string securityToken, string modifier = null) => GenerateCode(Encoding.Unicode.GetBytes(securityToken), modifier);
122 |
123 | ///
124 | /// Validates the code for the specified .
125 | ///
126 | /// The security token for verifying.
127 | /// The code to validate.
128 | /// The modifier
129 | /// True if validate succeed, otherwise, false.
130 | public static bool ValidateCode(string securityToken, int code, string modifier = null) => ValidateCode(Encoding.Unicode.GetBytes(securityToken), code, modifier);
131 | }
132 | }
133 |
--------------------------------------------------------------------------------
/test/Arch.Standard.Tests/Arch.Standard.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp1.1;net461
5 | $(NoWarn);CS1591
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/test/Arch.Standard.Tests/IPagedListTest.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using System.Collections.Generic;
4 | using System.Text;
5 | using Xunit;
6 | using Newtonsoft.Json;
7 |
8 | namespace Arch.Standard.Tests
9 | {
10 | public class User
11 | {
12 | public int Id { get; set; }
13 |
14 | public string Username { get; set; }
15 |
16 | public string Password { get; set; }
17 | }
18 |
19 | public class IPagedListTest
20 | {
21 | private readonly IList _users;
22 | public IPagedListTest()
23 | {
24 | _users = new User[]
25 | {
26 | new User
27 | {
28 | Id = 1,
29 | Username = "rigofunc",
30 | Password = "p@ssword"
31 | },
32 | new User
33 | {
34 | Id = 2,
35 | Username = "yingtingxu",
36 | Password = "p@ssword"
37 | }
38 | };
39 | }
40 |
41 | [Fact]
42 | public void IPagedList_Can_Json_Serialized_And_Deserialized_Test()
43 | {
44 | var querable = _users.AsQueryable();
45 |
46 | var pagedUsers = querable.OrderBy(u => u.Id).ToPagedList(0, 10, 0);
47 |
48 | var json = JsonConvert.SerializeObject(pagedUsers);
49 |
50 | Assert.False(string.IsNullOrEmpty(json));
51 |
52 | var users = JsonConvert.DeserializeObject>(json);
53 |
54 | Assert.IsAssignableFrom>(users);
55 |
56 | Assert.Equal(2, users.Items.Count);
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/test/Arch.Standard.Tests/IStandardErrorTests.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Arch team of Tencent. All rights reserved.
2 |
3 | using System;
4 | using System.Linq;
5 | using Xunit;
6 | using Newtonsoft.Json;
7 |
8 | namespace Arch.Standard.Tests
9 | {
10 | public class IStandardErrorTests
11 | {
12 | [Fact]
13 | public void IStandardError_Target_IsCallerMemberName_Test()
14 | {
15 | var error = StandardException.Caused("Code", "xUnit");
16 |
17 | Assert.Equal(nameof(IStandardError_Target_IsCallerMemberName_Test), error.Target);
18 | Assert.Equal("xUnit", error.Message);
19 | }
20 |
21 | [Fact]
22 | public void IStandardError_Fluent_API_Feature_Test()
23 | {
24 | Assert.Throws(() => {
25 | StandardException.Caused("Code", "xunit").Append(StandardException.Caused("InnerCode", "details")).Throw();
26 | });
27 | }
28 |
29 | [Fact]
30 | public void IStandardError_Can_Json_Serialize_Test()
31 | {
32 | var exception = StandardException.Caused("Code", "xunit").Append(StandardException.Caused("InnerCode", "details", "InnerTarget"));
33 |
34 | var json = JsonConvert.SerializeObject(exception);
35 |
36 | Assert.False(string.IsNullOrEmpty(json));
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------