/// <summary> /// Gets the JavaScript to send to the specific client device based on the /// request context provided. /// </summary> /// <param name="context"></param> /// <returns></returns> private static string GetFeatureJavaScript(HttpContext context) { var queryString = context.Request.QueryString.ToString(); var match = WebProvider.GetMatch(context.Request); var features = new List <string>(); if (String.IsNullOrEmpty(queryString)) { foreach (var property in WebProvider.ActiveProvider.DataSet.Properties.Where(i => i._valueType != Entities.Property.PropertyValueType.JavaScript)) { GetFeatureJavaScript(match, features, property); } } else { foreach (var propertyName in HttpUtility.UrlDecode(queryString).Split( new char[] { ' ', ',', '&', '|' })) { var property = WebProvider.ActiveProvider.DataSet.Properties.FirstOrDefault(i => i.Name.Equals(propertyName, StringComparison.InvariantCultureIgnoreCase)); if (property != null) { GetFeatureJavaScript(match, features, property); } } } return(String.Format("var FODF={{{0}}};", String.Join(",", features.ToArray()))); }
/// <summary> /// Activates the data array containing the premium data. /// </summary> /// <param name="data">Data to activate</param> public static LicenceKeyResults Activate(byte[] data) { try { DataSet dataSet = null; // Validate the data provided is correct. try { dataSet = StreamFactory.Create(data); } catch (MobileException ex) { EventLog.Warn(ex); return(LicenceKeyResults.DataInvalid); } // Check the configuration. try { CheckConfig(); } catch (Exception ex) { EventLog.Warn(ex); return(LicenceKeyResults.Config); } // Write the file to the binary data path. try { File.WriteAllBytes(Detection.Configuration.Manager.BinaryFilePath, data); File.SetLastAccessTimeUtc(Detection.Configuration.Manager.BinaryFilePath, dataSet.Published); } catch (IOException ex) { EventLog.Warn(ex); return(LicenceKeyResults.WriteDataFile); } // Switch in the new data to complete activation. WebProvider.Refresh(); EventLog.Info(String.Format( "Activated binary data file '{0}' with new version " + "dated the '{1:d}'.", AutoUpdate.MasterBinaryDataFile.FullName, dataSet.Published)); } catch (Exception ex) { EventLog.Warn(ex); return(LicenceKeyResults.GenericFailure); } return(LicenceKeyResults.Success); }
/// <summary> /// Writes information about the data set being used by the provider. /// </summary> /// <param name="writer"></param> /// <param name="provider"></param> private static void WriteProvider(XmlWriter writer, WebProvider provider) { if (provider != null) { writer.WriteStartElement("DataSet"); writer.WriteElementString("Version", provider.DataSet.Version.ToString()); writer.WriteElementString("Name", provider.DataSet.Name); writer.WriteEndElement(); } }
/// <summary> /// Forces the application to reload the active provider on the next /// request. /// </summary> public static void Refresh() { var provider = _activeProvider; _activeProvider = null; _activeProviderCreated = false; if (provider != null) { // Dispose of the old provider. provider.Dispose(); } }
/// <summary> /// Downloads and updates the premium data file. /// </summary> internal static LicenceKeyResults Download(string[] licenceKeys) { var status = LicenceKeyResults.InProgress; WebClient client = new WebClient(); var compressedTempFile = WebProvider.GetTempFileName(); var uncompressedTempFile = String.Format("{0}.new", Manager.BinaryFilePath); try { // Wait until any other threads have finished executing. _autoDownloadUpdateSignal.WaitOne(); // Download the data file to the compressed temporary file. status = DownloadFile(client, Manager.BinaryFilePath, compressedTempFile, licenceKeys); // Validate the MD5 hash of the download. if (status == LicenceKeyResults.InProgress) { status = CheckedDownloadedFileMD5(client, compressedTempFile); } // Decompress the data file ready to create the data set. if (status == LicenceKeyResults.InProgress) { status = Decompress(compressedTempFile, uncompressedTempFile); } // Validate that the data file can be used to create a provider. if (status == LicenceKeyResults.InProgress) { status = ValidateDownloadedFile(uncompressedTempFile); } // Activate the data file downloaded for future use. if (status == LicenceKeyResults.InProgress) { status = ActivateDownloadedFile(client, uncompressedTempFile); } } catch (Exception) { status = LicenceKeyResults.GenericFailure; } finally { File.Delete(compressedTempFile); File.Delete(uncompressedTempFile); client.Dispose(); _autoDownloadUpdateSignal.Set(); } return(status); }
/// <summary> /// Creates a new provider and then sets it as active provider /// </summary> public static bool Reload() { var newProvider = Create(); if (newProvider == null) { return(false); } EventLog.Info("Replacing the active provider."); var oldProvider = _activeProvider; _activeProvider = newProvider; oldProvider?.Dispose(); return(true); }
/// <summary> /// The application is being disposed of either due to a recycle event or /// shutdown. Ensure the active provider is disposed of to release resources. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private static void OnProcessExit(object sender, EventArgs e) { try { var provider = _activeProvider; if (provider != null) { provider.Dispose(); } } finally { _activeProvider = null; _activeProviderCreated = false; } }
/// <summary> /// Checks if a new data file is available for download and if it is /// newer than the current data on disk, if enough time has passed /// between now and the write time of the current data in memory. See /// Constants.AutoUpdateWait. This method is designed to be used in a /// seperate thread from the one performing detection. /// </summary> internal static void CheckForUpdate(object state) { try { // If licence keys are available auto update. if (LicenceKey.Keys.Length > 0) { // Check that there is a binary file, and that either the // active provider is not available indicating no source // data file, or if is available that the next update is // in the past, or that the device data being used is the // free lite version. if (MasterBinaryDataFile != null && (WebProvider.ActiveProvider == null || WebProvider.ActiveProvider.DataSet.NextUpdate < DateTime.UtcNow || WebProvider.ActiveProvider.DataSet.Name == "Lite")) { var downloadResult = Download(LicenceKey.Keys); if (downloadResult == LicenceKeyResults.Success) { WebProvider.Refresh(); } } } } catch (ThreadAbortException ex) { EventLog.Warn(new MobileException( "Auto update download thread aborted", ex)); } catch (Exception ex) { if (MasterBinaryDataFile != null && MasterBinaryDataFile.FullName != null) { EventLog.Warn(new MobileException(String.Format( "Exception auto update download binary data file '{0}'.", MasterBinaryDataFile.FullName), ex)); } else { EventLog.Fatal(ex); } } }
/// <summary> /// Provides information to the web server about the requesting device. /// </summary> /// <param name="request">An HttpRequest that provides information about the source device.</param> /// <returns>A HttpBrowserCapabilities object containing information relevent to the device /// sources from 51Degrees.mobi.</returns> public override HttpBrowserCapabilities GetBrowserCapabilities(HttpRequest request) { var match = WebProvider.GetMatch(request); if (match != null) { // A provider is present so 51Degrees can be used to override // some of the returned values. return(new FiftyOneBrowserCapabilities( base.GetBrowserCapabilities(request), request, match)); } else { // No 51Degrees active provider is present so we have to use // the base capabilities only. return(base.GetBrowserCapabilities(request)); } }
/// <summary> /// Provides information to the web server about the requesting device. /// </summary> /// <param name="request"> /// HttpRequest that provides information about the source device. /// </param> /// <returns> /// A HttpBrowserCapabilities object containing information which /// retrieves device data from 51Degrees. /// </returns> public override HttpBrowserCapabilities GetBrowserCapabilities(HttpRequest request) { HttpBrowserCapabilities caps; var baseCaps = base.GetBrowserCapabilities(request); var match = WebProvider.GetMatch(request); if (match != null) { // A provider is present so 51Degrees can be used to override // some of the returned values. caps = new FiftyOneBrowserCapabilities( baseCaps, request, match); // Copy the adapters from the original. var adapters = baseCaps.Adapters.GetEnumerator(); while (adapters.MoveNext()) { caps.Adapters.Add(adapters.Key, adapters.Value); } // Copy the browsers from the original to prevent the Browsers // property returning null. if (baseCaps.Browsers != null) { foreach (string browser in baseCaps.Browsers) { caps.AddBrowser(browser); } } } else { // No 51Degrees active provider is present so we have to use // the base capabilities only. caps = baseCaps; } return(caps); }
/// <summary> /// A reference to the active provider. /// </summary> internal static WebProvider GetActiveProvider() { if (_activeProviderCreated == false) { lock (_lock) { if (_activeProviderCreated == false) { _activeProvider = Create(); // The DetectorModule should set to listen for the // application reycling or shutting down. This is belt // and braces in case thte HttpModule method fails to // fire the application end event. AppDomain.CurrentDomain.ProcessExit += OnProcessExit; _activeProviderCreated = true; } } } return _activeProvider; }
private static LicenceKeyResults ActivateDownloadedFile(WebClient client, string uncompressedTempFile) { var status = LicenceKeyResults.Success; // Rename the current master file to a temp file so enable the new // master file to take it's place and to rollback if there's a problem. var tempCopyofCurrentMaster = String.Format("{0}.tmp", BinaryFile.FullName); try { // Both the MD5 hash was good and the provider was created. // Save the data and force the factory to reload. if (BinaryFile.Exists) { // Keep a copy of the old data in case we need to go back to it. File.Move(BinaryFile.FullName, tempCopyofCurrentMaster); } // Copy the new file to the master file. File.Move(uncompressedTempFile, BinaryFile.FullName); // Get the published date from the new data file. var publishedDate = WebProvider.GetDataFileDate(BinaryFile.FullName); // Sets the last modified time of the file downloaded to the one // provided in the HTTP header, or if not valid then the published // date of the data set. DateTime lastModified; if (DateTime.TryParseExact( client.ResponseHeaders[HttpResponseHeader.LastModified], "R", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out lastModified) == false) { lastModified = publishedDate.Value; } BinaryFile.LastWriteTimeUtc = lastModified.ToUniversalTime(); EventLog.Info(String.Format( "Automatically updated binary data file '{0}' with version " + "published on the '{1:d}'.", BinaryFile.FullName, publishedDate)); } catch (Exception ex) { if (BinaryFile.Exists == false) { File.Move(tempCopyofCurrentMaster, BinaryFile.FullName); } EventLog.Warn(ex); status = LicenceKeyResults.WriteDataFile; } finally { File.Delete(tempCopyofCurrentMaster); } return(status); }
/// <summary> /// Forces the provider to update current ActiveProvider with new data. /// </summary> private static WebProvider Create() { WebProvider provider = null; CleanTemporaryFiles(); try { // Does a binary file exist? if (Manager.BinaryFilePath != null) { // Log API version for diagnosis. var assembly = Assembly.GetExecutingAssembly().GetName(); EventLog.Info(String.Format( "Creating data set from '{0}' version '{1}'", assembly.Name, assembly.Version)); if (File.Exists(Manager.BinaryFilePath)) { if (Manager.MemoryMode) { EventLog.Info(String.Format( "Creating memory byte array dataset and provider from binary data file '{0}'.", Manager.BinaryFilePath)); provider = new WebProvider(StreamFactory.Create(File.ReadAllBytes(Manager.BinaryFilePath))); } else { provider = new WebProvider(GetTempFileDataSet()); } EventLog.Info(String.Format( "Created provider from version '{0}' format '{1}' data published on '{2:u}' in master file '{3}'.", provider.DataSet.Version, provider.DataSet.Name, provider.DataSet.Published, Manager.BinaryFilePath)); } else { EventLog.Info("Data file at '{0}' could not be found. Either it does not exist or " + "there is insufficient permission to read it. Check the AppPool has read permissions " + "and the application is not running in medium trust if the data file is not in the " + "application directory.", Manager.BinaryFilePath); } } } catch (Exception ex) { // Record the exception in the log file. EventLog.Fatal( new MobileException(String.Format( "Exception processing device data from binary file '{0}'. " + "Enable debug level logging and try again to help identify cause.", Manager.BinaryFilePath), ex)); } // Does the provider exist and has data been loaded? if (provider == null || provider.DataSet == null) { EventLog.Fatal("No data source available to create provider."); } return provider; }
/// <summary> /// Forces the provider to update current ActiveProvider with new data. /// </summary> private static WebProvider Create() { WebProvider provider = null; CleanTemporaryFiles(); try { // Does a binary file exist? if (Manager.BinaryFilePath != null) { // Log API version for diagnosis. var assembly = Assembly.GetExecutingAssembly().GetName(); EventLog.Info(String.Format( "Creating data set from '{0}' version '{1}'", assembly.Name, assembly.Version)); if (File.Exists(Manager.BinaryFilePath)) { if (Manager.MemoryMode) { EventLog.Info(String.Format( "Creating memory byte array dataset and provider from binary data file '{0}'.", Manager.BinaryFilePath)); provider = new WebProvider(StreamFactory.Create(File.ReadAllBytes(Manager.BinaryFilePath))); } else { provider = new WebProvider(GetTempFileDataSet()); } EventLog.Info(String.Format( "Created provider from version '{0}' format '{1}' data published on '{2:u}' in master file '{3}'.", provider.DataSet.Version, provider.DataSet.Name, provider.DataSet.Published, Manager.BinaryFilePath)); } else { EventLog.Info("Data file at '{0}' could not be found. Either it does not exist or " + "there is insufficient permission to read it. Check the AppPool has read permissions " + "and the application is not running in medium trust if the data file is not in the " + "application directory.", Manager.BinaryFilePath); } } } catch (Exception ex) { // Record the exception in the log file. EventLog.Fatal( new MobileException(String.Format( "Exception processing device data from binary file '{0}'. " + "Enable debug level logging and try again to help identify cause.", Manager.BinaryFilePath), ex)); } // Does the provider exist and has data been loaded? if (provider == null || provider.DataSet == null) { EventLog.Fatal("No data source available to create provider."); } return(provider); }