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 (10 years, 5 months ago) by william
File size: 33784 byte(s)
Log Message:

File Contents

# User Rev Content
1 william 722 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 william 724
70     //var asm_test = Assembly.LoadFile(this.AssemblyInfo.Location);
71    
72 william 723 ClientConfigPaths t = new ClientConfigPaths(this.AssemblyInfo, true);
73 william 722
74 william 724 this.ConfigFilePath = t.LocalConfigFilename;
75    
76 william 722 }
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 william 724 //static volatile ClientConfigPaths s_current;
103     //static volatile bool s_currentIncludesUserConfig;
104 william 722 static SecurityPermission s_serializationPerm;
105     static SecurityPermission s_controlEvidencePerm;
106    
107 william 724 //bool _hasEntryAssembly;
108     //bool _includesUserConfig;
109     //string _applicationUri;
110     //string _applicationConfigUri;
111 william 722 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 william 723 public ClientConfigPaths(Assembly assembly, bool includeUserConfig)
123 william 722 {
124    
125 william 723 //_includesUserConfig = includeUserConfig;
126 william 722
127 william 723 Assembly exeAssembly = assembly;
128     //string applicationUri = null;
129     //string applicationFilename = null;
130 william 722
131 william 723 //// 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 william 722
140 william 723 // // Now figure out the application path.
141     // exeAssembly = Assembly.GetEntryAssembly();
142     // if (exeAssembly != null)
143     // {
144     // _hasEntryAssembly = true;
145     // applicationUri = exeAssembly.CodeBase;
146 william 722
147 william 723 // bool isFile = false;
148 william 722
149 william 723 // // 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 william 722
164 william 723 // 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 william 722
188 william 723 //// applicationFilename = applicationUri;
189     ////}
190 william 722
191 william 723 //// Fallback if we haven't set the app config file path yet.
192     //if (_applicationConfigUri == null)
193     //{
194     // _applicationConfigUri = applicationUri + ConfigExtension;
195     //}
196 william 722
197 william 723 //// Set application path
198     //_applicationUri = applicationUri;
199 william 722
200 william 723 //// 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 william 722
207 william 723 //// Skip expensive initialization of user config file information if requested.
208     //if (!_includesUserConfig)
209     //{
210     // return;
211     //}
212 william 722
213 william 723 ////bool isHttp = StringUtil.StartsWithIgnoreCase(_applicationConfigUri, HTTP_URI);
214 william 722
215 william 723 //SetNamesAndVersion(applicationFilename, exeAssembly, false);
216     SetNamesAndVersion(exeAssembly, false);
217 william 722
218 william 723 //// 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 william 722
225 william 723 // // 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 william 722
232 william 723 //}
233     //else if (!isHttp)
234     //{
235 william 722 // 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 william 723 //string validAppDomainName = Validate(AppDomain.CurrentDomain.FriendlyName, true);
243     string friendlyName = new FileInfo(exeAssembly.Location).Name;
244     string validAppDomainName = Validate(friendlyName, true);
245 william 724 //string applicationUriLower = !String.IsNullOrEmpty(_applicationUri) ? _applicationUri.ToLower(CultureInfo.InvariantCulture) : null;
246 william 722 string namePrefix = !String.IsNullOrEmpty(validAppDomainName) ? validAppDomainName : Validate(_productName, true);
247 william 723 //string hashSuffix = GetTypeAndHashSuffix(AppDomain.CurrentDomain, applicationUriLower);
248 william 724 //string hashSuffix = GetTypeAndHashSuffix(exeAssembly, applicationUriLower);
249     string hashSuffix = GetTypeAndHashSuffix(exeAssembly);
250 william 722
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 william 723 //}
271 william 722 }
272    
273 william 723 //internal static ClientConfigPaths GetPaths(string exePath, bool includeUserConfig)
274     //{
275     // ClientConfigPaths result = null;
276 william 722
277 william 723 // 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 william 722
285 william 723 // result = s_current;
286     // }
287     // else
288     // {
289     // result = new ClientConfigPaths(exePath, includeUserConfig);
290     // }
291 william 722
292 william 723 // return result;
293     //}
294 william 722
295 william 724 //internal static void RefreshCurrent()
296     //{
297     // s_currentIncludesUserConfig = false;
298     // s_current = null;
299     //}
300 william 722
301 william 723 //internal static ClientConfigPaths Current
302     //{
303     // get
304     // {
305     // return GetPaths(null, true);
306     // }
307     //}
308 william 722
309 william 724 //internal bool HasEntryAssembly
310     //{
311     // get
312     // {
313     // return _hasEntryAssembly;
314     // }
315     //}
316 william 722
317 william 724 //internal string ApplicationUri
318     //{
319     // get
320     // {
321     // return _applicationUri;
322     // }
323     //}
324 william 722
325 william 724 //internal string ApplicationConfigUri
326     //{
327     // get
328     // {
329     // return _applicationConfigUri;
330     // }
331     //}
332 william 722
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 william 724 //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 william 722
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 william 724 //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 william 722
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 william 723 //private string GetTypeAndHashSuffix(AppDomain appDomain, string exePath)
450 william 724 //private string GetTypeAndHashSuffix(Assembly appDomain, string exePath)
451     private string GetTypeAndHashSuffix(Assembly appDomain)
452 william 722 {
453     string suffix = null;
454     string typeName = null;
455     object evidenceObj = null;
456 william 724 //evidenceObj = GetEvidenceInfo(appDomain, exePath, out typeName);
457     evidenceObj = GetEvidenceInfo(appDomain, out typeName);
458 william 722
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 william 723 //private static object GetEvidenceInfo(AppDomain appDomain, string exePath, out string typeName)
479 william 724 //private static object GetEvidenceInfo(Assembly appDomain, string exePath, out string typeName)
480     private static object GetEvidenceInfo(Assembly appDomain, out string typeName)
481 william 722 {
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 william 724 //else if (exePath != null)
523     //{
524     // o = exePath;
525     // typeName = PathDesc;
526     //}
527 william 722 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 william 723 //private void SetNamesAndVersion(string applicationFilename, Assembly exeAssembly, bool isHttp)
574     private void SetNamesAndVersion(Assembly exeAssembly, bool isHttp)
575 william 722 {
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 william 723 //if (versionInfoFileName == null)
632     //{
633     // versionInfoFileName = applicationFilename;
634     //}
635 william 722
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     }