ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/RomCheater/trunk/RomCheater.UserSettingsSupport/IsolatedStoragePath.cs
Revision: 724
Committed: Tue Jun 18 20:22:08 2013 UTC (9 years, 11 months ago) by william
File size: 33784 byte(s)
Log Message:

File Contents

# Content
1 using System;
2 using System.Collections;
3 using System.IO;
4 using System.Reflection;
5 using System.Runtime.CompilerServices;
6 using System.Runtime.InteropServices;
7 using System.Runtime.Serialization.Formatters.Binary;
8 using System.Security;
9 using System.Security.Cryptography;
10 using System.Security.Policy;
11 using System.Security.Permissions;
12 using System.Text;
13 using System.Globalization;
14 using Microsoft.Win32;
15
16 namespace RomCheater.UserSettingsSupport
17 {
18 public interface IIsolatedStoragePath
19 {
20 Assembly AssemblyInfo { get; }
21 string ConfigFilePath { get; }
22 }
23 internal sealed class IsolatedStoragePath : IIsolatedStoragePath
24 {
25 const string EVIDENCE_STRONGNAME = "StrongName";
26 const string EVIDENCE_URL = "Url";
27
28
29
30 public IsolatedStoragePath() : this(false) { }
31 public IsolatedStoragePath(bool UseCallingAssembly) : this(UseCallingAssembly ? Assembly.GetCallingAssembly() : Assembly.GetExecutingAssembly()) { }
32 public IsolatedStoragePath(Assembly assembly) { CreatePath(assembly); }
33
34 #region IIsolatedStorageHash Members
35 private Assembly _AssemblyInfo;
36 public Assembly AssemblyInfo { get { return _AssemblyInfo; } private set { _AssemblyInfo = value; } }
37
38 private string _ConfigFilePath;
39 public string ConfigFilePath { get { return _ConfigFilePath; } private set { _ConfigFilePath = value; } }
40 #endregion
41
42
43 private void CreatePath(Assembly asm)
44 {
45 this.AssemblyInfo = asm;
46 this.ConfigFilePath = string.Empty;
47 //string path = string.Empty;
48 //string profile_dir = Environment.GetEnvironmentVariable("LocalAppData");
49 //string company_name = ((AssemblyCompanyAttribute)Attribute.GetCustomAttribute(this.AssemblyInfo, typeof(AssemblyCompanyAttribute), false)).Company;
50 //string app_fullname = new FileInfo(this.AssemblyInfo.Location).Name;
51 //string evidence_type = this.AssemblyInfo.GetName().GetPublicKey().Length == 0 ? EVIDENCE_URL : EVIDENCE_STRONGNAME;
52 //string evidence_hash = CompureEvidenceHashForAssembly(this.AssemblyInfo);
53 //string version = this.AssemblyInfo.GetName().Version.ToString();
54 //string config = "user.config";
55 //StringBuilder builder = new StringBuilder();
56 //builder.AppendFormat(@"{0}", profile_dir);
57 //if (company_name != string.Empty)
58 //{
59 // builder.AppendFormat(@"\{0}", company_name.Replace(" ", "_"));
60 //}
61 //builder.AppendFormat(@"\{0}", app_fullname);
62 //builder.AppendFormat(@"_{0}", evidence_type);
63 //builder.AppendFormat(@"_{0}", evidence_hash);
64 //builder.AppendFormat(@"\{0}", version);
65 //builder.AppendFormat(@"\{0}", config);
66 //path = builder.ToString();
67 //this.ConfigFilePath = path;
68
69
70 //var asm_test = Assembly.LoadFile(this.AssemblyInfo.Location);
71
72 ClientConfigPaths t = new ClientConfigPaths(this.AssemblyInfo, true);
73
74 this.ConfigFilePath = t.LocalConfigFilename;
75
76 }
77
78
79 #region ClientConfigPaths
80 class ClientConfigPaths
81 {
82 internal const string UserConfigFilename = "user.config";
83
84 const string ClickOnceDataDirectory = "DataDirectory";
85 const string ConfigExtension = ".config";
86 const int MAX_PATH = 260;
87 const int MAX_LENGTH_TO_USE = 25;
88 const string FILE_URI_LOCAL = "file:///";
89 const string FILE_URI_UNC = "file://";
90 const string FILE_URI = "file:";
91 const string HTTP_URI = "http://";
92 const string StrongNameDesc = "StrongName";
93 const string UrlDesc = "Url";
94 const string PathDesc = "Path";
95
96 static Char[] s_Base32Char = {
97 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
98 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
99 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
100 'y', 'z', '0', '1', '2', '3', '4', '5'};
101
102 //static volatile ClientConfigPaths s_current;
103 //static volatile bool s_currentIncludesUserConfig;
104 static SecurityPermission s_serializationPerm;
105 static SecurityPermission s_controlEvidencePerm;
106
107 //bool _hasEntryAssembly;
108 //bool _includesUserConfig;
109 //string _applicationUri;
110 //string _applicationConfigUri;
111 string _roamingConfigDirectory;
112 string _roamingConfigFilename;
113 string _localConfigDirectory;
114 string _localConfigFilename;
115 string _companyName;
116 string _productName;
117 string _productVersion;
118
119
120 [FileIOPermission(SecurityAction.Assert, AllFiles = FileIOPermissionAccess.PathDiscovery | FileIOPermissionAccess.Read)]
121 [SecurityPermission(SecurityAction.Assert, UnmanagedCode = true)]
122 public ClientConfigPaths(Assembly assembly, bool includeUserConfig)
123 {
124
125 //_includesUserConfig = includeUserConfig;
126
127 Assembly exeAssembly = assembly;
128 //string applicationUri = null;
129 //string applicationFilename = null;
130
131 //// get the assembly and applicationUri for the file
132 //if (exePath == null)
133 //{
134 // // First check if a configuration file has been set for this app domain. If so, we will use that.
135 // // The CLR would already have normalized this, so no further processing necessary.
136 // //AppDomain domain = AppDomain.CurrentDomain;
137 // //AppDomainSetup setup = domain.SetupInformation;
138 // //_applicationConfigUri = setup.ConfigurationFile;
139
140 // // Now figure out the application path.
141 // exeAssembly = Assembly.GetEntryAssembly();
142 // if (exeAssembly != null)
143 // {
144 // _hasEntryAssembly = true;
145 // applicationUri = exeAssembly.CodeBase;
146
147 // bool isFile = false;
148
149 // // If it is a local file URI, convert it to its filename, without invoking Uri class.
150 // // example: "file:///C:/WINNT/Microsoft.NET/Framework/v2.0.x86fre/csc.exe"
151 // if (StringUtil.StartsWithIgnoreCase(applicationUri, FILE_URI_LOCAL))
152 // {
153 // isFile = true;
154 // applicationUri = applicationUri.Substring(FILE_URI_LOCAL.Length);
155 // }
156 // // If it is a UNC file URI, convert it to its filename, without invoking Uri class.
157 // // example: "file://server/share/csc.exe"
158 // else if (StringUtil.StartsWithIgnoreCase(applicationUri, FILE_URI_UNC))
159 // {
160 // isFile = true;
161 // applicationUri = applicationUri.Substring(FILE_URI.Length);
162 // }
163
164 // if (isFile)
165 // {
166 // applicationUri = applicationUri.Replace('/', '\\');
167 // applicationFilename = applicationUri;
168 // }
169 // else
170 // {
171 // applicationUri = exeAssembly.EscapedCodeBase;
172 // }
173 // }
174 // else
175 // {
176 // StringBuilder sb = new StringBuilder(MAX_PATH);
177 // UnsafeNativeMethods.GetModuleFileName(new HandleRef(null, IntPtr.Zero), sb, sb.Capacity);
178 // applicationUri = Path.GetFullPath(sb.ToString());
179 // applicationFilename = applicationUri;
180 // }
181 //}
182 ////else
183 ////{
184 //// applicationUri = Path.GetFullPath(exePath);
185 //// if (!FileUtil.FileExists(applicationUri, false))
186 //// throw ExceptionUtil.ParameterInvalid("exePath");
187
188 //// applicationFilename = applicationUri;
189 ////}
190
191 //// Fallback if we haven't set the app config file path yet.
192 //if (_applicationConfigUri == null)
193 //{
194 // _applicationConfigUri = applicationUri + ConfigExtension;
195 //}
196
197 //// Set application path
198 //_applicationUri = applicationUri;
199
200 //// In the case when exePath was explicitly supplied, we will not be able to
201 //// construct user.config paths, so quit here.
202 //if (exePath != null)
203 //{
204 // return;
205 //}
206
207 //// Skip expensive initialization of user config file information if requested.
208 //if (!_includesUserConfig)
209 //{
210 // return;
211 //}
212
213 ////bool isHttp = StringUtil.StartsWithIgnoreCase(_applicationConfigUri, HTTP_URI);
214
215 //SetNamesAndVersion(applicationFilename, exeAssembly, false);
216 SetNamesAndVersion(exeAssembly, false);
217
218 //// Check if this is a clickonce deployed application. If so, point the user config
219 //// files to the clickonce data directory.
220 //if (this.IsClickOnceDeployed(AppDomain.CurrentDomain))
221 //{
222 // string dataPath = AppDomain.CurrentDomain.GetData(ClickOnceDataDirectory) as string;
223 // string versionSuffix = Validate(_productVersion, false);
224
225 // // NOTE: No roaming config for clickonce - not supported.
226 // if (Path.IsPathRooted(dataPath))
227 // {
228 // _localConfigDirectory = CombineIfValid(dataPath, versionSuffix);
229 // _localConfigFilename = CombineIfValid(_localConfigDirectory, UserConfigFilename);
230 // }
231
232 //}
233 //else if (!isHttp)
234 //{
235 // If we get the config from http, we do not have a roaming or local config directory,
236 // as it cannot be edited by the app in those cases because it does not have Full Trust.
237
238 // suffix for user config paths
239
240 string part1 = Validate(_companyName, true);
241
242 //string validAppDomainName = Validate(AppDomain.CurrentDomain.FriendlyName, true);
243 string friendlyName = new FileInfo(exeAssembly.Location).Name;
244 string validAppDomainName = Validate(friendlyName, true);
245 //string applicationUriLower = !String.IsNullOrEmpty(_applicationUri) ? _applicationUri.ToLower(CultureInfo.InvariantCulture) : null;
246 string namePrefix = !String.IsNullOrEmpty(validAppDomainName) ? validAppDomainName : Validate(_productName, true);
247 //string hashSuffix = GetTypeAndHashSuffix(AppDomain.CurrentDomain, applicationUriLower);
248 //string hashSuffix = GetTypeAndHashSuffix(exeAssembly, applicationUriLower);
249 string hashSuffix = GetTypeAndHashSuffix(exeAssembly);
250
251 string part2 = (!String.IsNullOrEmpty(namePrefix) && !String.IsNullOrEmpty(hashSuffix)) ? namePrefix + hashSuffix : null;
252
253 string part3 = Validate(_productVersion, false);
254
255 string dirSuffix = CombineIfValid(CombineIfValid(part1, part2), part3);
256
257 string roamingFolderPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
258 if (Path.IsPathRooted(roamingFolderPath))
259 {
260 _roamingConfigDirectory = CombineIfValid(roamingFolderPath, dirSuffix);
261 _roamingConfigFilename = CombineIfValid(_roamingConfigDirectory, UserConfigFilename);
262 }
263
264 string localFolderPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
265 if (Path.IsPathRooted(localFolderPath))
266 {
267 _localConfigDirectory = CombineIfValid(localFolderPath, dirSuffix);
268 _localConfigFilename = CombineIfValid(_localConfigDirectory, UserConfigFilename);
269 }
270 //}
271 }
272
273 //internal static ClientConfigPaths GetPaths(string exePath, bool includeUserConfig)
274 //{
275 // ClientConfigPaths result = null;
276
277 // if (exePath == null)
278 // {
279 // if (s_current == null || (includeUserConfig && !s_currentIncludesUserConfig))
280 // {
281 // s_current = new ClientConfigPaths(null, includeUserConfig);
282 // s_currentIncludesUserConfig = includeUserConfig;
283 // }
284
285 // result = s_current;
286 // }
287 // else
288 // {
289 // result = new ClientConfigPaths(exePath, includeUserConfig);
290 // }
291
292 // return result;
293 //}
294
295 //internal static void RefreshCurrent()
296 //{
297 // s_currentIncludesUserConfig = false;
298 // s_current = null;
299 //}
300
301 //internal static ClientConfigPaths Current
302 //{
303 // get
304 // {
305 // return GetPaths(null, true);
306 // }
307 //}
308
309 //internal bool HasEntryAssembly
310 //{
311 // get
312 // {
313 // return _hasEntryAssembly;
314 // }
315 //}
316
317 //internal string ApplicationUri
318 //{
319 // get
320 // {
321 // return _applicationUri;
322 // }
323 //}
324
325 //internal string ApplicationConfigUri
326 //{
327 // get
328 // {
329 // return _applicationConfigUri;
330 // }
331 //}
332
333 internal string RoamingConfigFilename
334 {
335 get
336 {
337 return _roamingConfigFilename;
338 }
339 }
340
341 internal string RoamingConfigDirectory
342 {
343 get
344 {
345 return _roamingConfigDirectory;
346 }
347 }
348
349 //internal bool HasRoamingConfig
350 //{
351 // get
352 // {
353 // // Assume we have roaming config if we haven't loaded user config file information.
354 // return RoamingConfigFilename != null || !_includesUserConfig;
355 // }
356 //}
357
358 internal string LocalConfigFilename
359 {
360 get
361 {
362 return _localConfigFilename;
363 }
364 }
365
366 internal string LocalConfigDirectory
367 {
368 get
369 {
370 return _localConfigDirectory;
371 }
372 }
373
374 //internal bool HasLocalConfig
375 //{
376 // get
377 // {
378 // // Assume we have roaming config if we haven't loaded user config file information.
379 // return LocalConfigFilename != null || !_includesUserConfig;
380 // }
381 //}
382
383 internal string ProductName
384 {
385 get
386 {
387 return _productName;
388 }
389 }
390
391 internal string ProductVersion
392 {
393 get
394 {
395 return _productVersion;
396 }
397 }
398
399 private static SecurityPermission ControlEvidencePermission
400 {
401 get
402 {
403 if (s_controlEvidencePerm == null)
404 {
405 s_controlEvidencePerm = new SecurityPermission(SecurityPermissionFlag.ControlEvidence);
406 }
407 return s_controlEvidencePerm;
408 }
409 }
410
411 private static SecurityPermission SerializationFormatterPermission
412 {
413 get
414 {
415 if (s_serializationPerm == null)
416 {
417 s_serializationPerm = new SecurityPermission(SecurityPermissionFlag.SerializationFormatter);
418 }
419 return s_serializationPerm;
420 }
421 }
422
423 // Combines path2 with path1 if possible, else returns null.
424 private string CombineIfValid(string path1, string path2)
425 {
426 string returnPath = null;
427
428 if (path1 != null && path2 != null)
429 {
430 try
431 {
432 string combinedPath = Path.Combine(path1, path2);
433 if (combinedPath.Length < MAX_PATH)
434 {
435 returnPath = combinedPath;
436 }
437 }
438 catch
439 {
440 }
441 }
442
443 return returnPath;
444 }
445
446 // Returns a type and hash suffix based on app domain evidence. The evidence we use, in
447 // priority order, is Strong Name, Url and Exe Path. If one of these is found, we compute a
448 // SHA1 hash of it and return a suffix based on that. If none is found, we return null.
449 //private string GetTypeAndHashSuffix(AppDomain appDomain, string exePath)
450 //private string GetTypeAndHashSuffix(Assembly appDomain, string exePath)
451 private string GetTypeAndHashSuffix(Assembly appDomain)
452 {
453 string suffix = null;
454 string typeName = null;
455 object evidenceObj = null;
456 //evidenceObj = GetEvidenceInfo(appDomain, exePath, out typeName);
457 evidenceObj = GetEvidenceInfo(appDomain, out typeName);
458
459 if (evidenceObj != null && !String.IsNullOrEmpty(typeName))
460 {
461 MemoryStream ms = new MemoryStream();
462 BinaryFormatter bSer = new BinaryFormatter();
463 SerializationFormatterPermission.Assert();
464 bSer.Serialize(ms, evidenceObj);
465 ms.Position = 0;
466 string evidenceHash = GetHash(ms);
467
468 if (!String.IsNullOrEmpty(evidenceHash))
469 {
470 suffix = "_" + typeName + "_" + evidenceHash;
471 }
472 }
473
474 return suffix;
475 }
476
477 // Mostly borrowed from IsolatedStorage, with some modifications
478 //private static object GetEvidenceInfo(AppDomain appDomain, string exePath, out string typeName)
479 //private static object GetEvidenceInfo(Assembly appDomain, string exePath, out string typeName)
480 private static object GetEvidenceInfo(Assembly appDomain, out string typeName)
481 {
482 ControlEvidencePermission.Assert();
483 Evidence evidence = appDomain.Evidence;
484 StrongName sn = null;
485 Url url = null;
486
487 if (evidence != null)
488 {
489 IEnumerator e = evidence.GetHostEnumerator();
490 object temp = null;
491
492 while (e.MoveNext())
493 {
494 temp = e.Current;
495
496 if (temp is StrongName)
497 {
498 sn = (StrongName)temp;
499 break;
500 }
501 else if (temp is Url)
502 {
503 url = (Url)temp;
504 }
505 }
506 }
507
508 object o = null;
509
510 // The order of preference is StrongName, Url, ExePath.
511 if (sn != null)
512 {
513 o = MakeVersionIndependent(sn);
514 typeName = StrongNameDesc;
515 }
516 else if (url != null)
517 {
518 // Extract the url string and normalize it to use as evidence
519 o = url.Value.ToUpperInvariant();
520 typeName = UrlDesc;
521 }
522 //else if (exePath != null)
523 //{
524 // o = exePath;
525 // typeName = PathDesc;
526 //}
527 else
528 {
529 typeName = null;
530 }
531
532 return o;
533 }
534
535 private static String GetHash(Stream s)
536 {
537 byte[] hash;
538
539 using (SHA1 sha1 = new SHA1CryptoServiceProvider())
540 {
541 hash = sha1.ComputeHash(s);
542 }
543
544 return ToBase32StringSuitableForDirName(hash);
545 }
546
547 private bool IsClickOnceDeployed(AppDomain appDomain)
548 {
549 // NOTE: For perf & servicing reasons, we don't want to introduce a dependency on
550 // System.Deployment.dll here. The following code is an alternative to calling
551 // ApplicationDeployment.IsNetworkDeployed.
552
553 ActivationContext actCtx = appDomain.ActivationContext;
554
555 // Ensures the app is running with a context from the store.
556 if (actCtx != null && actCtx.Form == ActivationContext.ContextForm.StoreBounded)
557 {
558 string fullAppId = actCtx.Identity.FullName;
559 if (!String.IsNullOrEmpty(fullAppId))
560 {
561 return true;
562 }
563 }
564
565 return false;
566 }
567
568 private static StrongName MakeVersionIndependent(StrongName sn)
569 {
570 return new StrongName(sn.PublicKey, sn.Name, new Version(0, 0, 0, 0));
571 }
572
573 //private void SetNamesAndVersion(string applicationFilename, Assembly exeAssembly, bool isHttp)
574 private void SetNamesAndVersion(Assembly exeAssembly, bool isHttp)
575 {
576 Type mainType = null;
577
578 //
579 // Get CompanyName, ProductName, and ProductVersion
580 // First try custom attributes on the assembly.
581 //
582 if (exeAssembly != null)
583 {
584 object[] attrs = exeAssembly.GetCustomAttributes(typeof(AssemblyCompanyAttribute), false);
585 if (attrs != null && attrs.Length > 0)
586 {
587 _companyName = ((AssemblyCompanyAttribute)attrs[0]).Company;
588 if (_companyName != null)
589 {
590 _companyName = _companyName.Trim();
591 }
592 }
593
594 attrs = exeAssembly.GetCustomAttributes(typeof(AssemblyProductAttribute), false);
595 if (attrs != null && attrs.Length > 0)
596 {
597 _productName = ((AssemblyProductAttribute)attrs[0]).Product;
598 if (_productName != null)
599 {
600 _productName = _productName.Trim();
601 }
602 }
603
604 _productVersion = exeAssembly.GetName().Version.ToString();
605 if (_productVersion != null)
606 {
607 _productVersion = _productVersion.Trim();
608 }
609 }
610
611 //
612 // If we couldn't get custom attributes, try the Win32 file version
613 //
614 if (!isHttp && (String.IsNullOrEmpty(_companyName) || String.IsNullOrEmpty(_productName) || String.IsNullOrEmpty(_productVersion)))
615 {
616 string versionInfoFileName = null;
617
618 if (exeAssembly != null)
619 {
620 MethodInfo entryPoint = exeAssembly.EntryPoint;
621 if (entryPoint != null)
622 {
623 mainType = entryPoint.ReflectedType;
624 if (mainType != null)
625 {
626 versionInfoFileName = mainType.Module.FullyQualifiedName;
627 }
628 }
629 }
630
631 //if (versionInfoFileName == null)
632 //{
633 // versionInfoFileName = applicationFilename;
634 //}
635
636 if (versionInfoFileName != null)
637 {
638 System.Diagnostics.FileVersionInfo version = System.Diagnostics.FileVersionInfo.GetVersionInfo(versionInfoFileName);
639 if (version != null)
640 {
641 if (String.IsNullOrEmpty(_companyName))
642 {
643 _companyName = version.CompanyName;
644 if (_companyName != null)
645 {
646 _companyName = _companyName.Trim();
647 }
648 }
649
650 if (String.IsNullOrEmpty(_productName))
651 {
652 _productName = version.ProductName;
653 if (_productName != null)
654 {
655 _productName = _productName.Trim();
656 }
657 }
658
659 if (String.IsNullOrEmpty(_productVersion))
660 {
661 _productVersion = version.ProductVersion;
662 if (_productVersion != null)
663 {
664 _productVersion = _productVersion.Trim();
665 }
666 }
667 }
668 }
669 }
670
671 if (String.IsNullOrEmpty(_companyName) || String.IsNullOrEmpty(_productName))
672 {
673 string ns = null;
674 if (mainType != null)
675 {
676 ns = mainType.Namespace;
677 }
678
679 // Desperate measures for product name
680 if (String.IsNullOrEmpty(_productName))
681 {
682 // Try the remainder of the namespace
683 if (ns != null)
684 {
685 int lastDot = ns.LastIndexOf(".", StringComparison.Ordinal);
686 if (lastDot != -1 && lastDot < ns.Length - 1)
687 {
688 _productName = ns.Substring(lastDot + 1);
689 }
690 else
691 {
692 _productName = ns;
693 }
694
695 _productName = _productName.Trim();
696 }
697
698 // Try the type of the entry assembly
699 if (String.IsNullOrEmpty(_productName) && mainType != null)
700 {
701 _productName = mainType.Name.Trim();
702 }
703
704 // give up, return empty string
705 if (_productName == null)
706 {
707 _productName = string.Empty;
708 }
709 }
710
711 // Desperate measures for company name
712 if (String.IsNullOrEmpty(_companyName))
713 {
714 // Try the first part of the namespace
715 if (ns != null)
716 {
717 int firstDot = ns.IndexOf(".", StringComparison.Ordinal);
718 if (firstDot != -1)
719 {
720 _companyName = ns.Substring(0, firstDot);
721 }
722 else
723 {
724 _companyName = ns;
725 }
726
727 _companyName = _companyName.Trim();
728 }
729
730 // If that doesn't work, use the product name
731 if (String.IsNullOrEmpty(_companyName))
732 {
733 _companyName = _productName;
734 }
735 }
736 }
737
738 // Desperate measures for product version - assume 1.0
739 if (String.IsNullOrEmpty(_productVersion))
740 {
741 _productVersion = "1.0.0.0";
742 }
743 }
744
745 // Borrowed from IsolatedStorage
746 private static string ToBase32StringSuitableForDirName(byte[] buff)
747 {
748 StringBuilder sb = new StringBuilder();
749 byte b0, b1, b2, b3, b4;
750 int l, i;
751
752 l = buff.Length;
753 i = 0;
754
755 // Create l chars using the last 5 bits of each byte.
756 // Consume 3 MSB bits 5 bytes at a time.
757
758 do
759 {
760 b0 = (i < l) ? buff[i++] : (byte)0;
761 b1 = (i < l) ? buff[i++] : (byte)0;
762 b2 = (i < l) ? buff[i++] : (byte)0;
763 b3 = (i < l) ? buff[i++] : (byte)0;
764 b4 = (i < l) ? buff[i++] : (byte)0;
765
766 // Consume the 5 Least significant bits of each byte
767 sb.Append(s_Base32Char[b0 & 0x1F]);
768 sb.Append(s_Base32Char[b1 & 0x1F]);
769 sb.Append(s_Base32Char[b2 & 0x1F]);
770 sb.Append(s_Base32Char[b3 & 0x1F]);
771 sb.Append(s_Base32Char[b4 & 0x1F]);
772
773 // Consume 3 MSB of b0, b1, MSB bits 6, 7 of b3, b4
774 sb.Append(s_Base32Char[(
775 ((b0 & 0xE0) >> 5) |
776 ((b3 & 0x60) >> 2))]);
777
778 sb.Append(s_Base32Char[(
779 ((b1 & 0xE0) >> 5) |
780 ((b4 & 0x60) >> 2))]);
781
782 // Consume 3 MSB bits of b2, 1 MSB bit of b3, b4
783
784 b2 >>= 5;
785
786 if ((b3 & 0x80) != 0)
787 b2 |= 0x08;
788 if ((b4 & 0x80) != 0)
789 b2 |= 0x10;
790
791 sb.Append(s_Base32Char[b2]);
792
793 } while (i < l);
794
795 return sb.ToString();
796 }
797
798 // Makes the passed in string suitable to use as a path name by replacing illegal characters
799 // with underscores. Additionally, we do two things - replace spaces too with underscores and
800 // limit the resultant string's length to MAX_LENGTH_TO_USE if limitSize is true.
801 private string Validate(string str, bool limitSize)
802 {
803 string validated = str;
804
805 if (!String.IsNullOrEmpty(validated))
806 {
807 // First replace all illegal characters with underscores
808 foreach (char c in Path.GetInvalidFileNameChars())
809 {
810 validated = validated.Replace(c, '_');
811 }
812
813 // Replace all spaces with underscores
814 validated = validated.Replace(' ', '_');
815
816 if (limitSize)
817 {
818 validated = (validated.Length > MAX_LENGTH_TO_USE) ? validated.Substring(0, MAX_LENGTH_TO_USE) : validated;
819 }
820 }
821
822 return validated;
823 }
824 }
825 #endregion
826 }
827 }