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