PageRenderTime 4015ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/web/studio/ASC.Web.Studio/Core/Import/TextFileUserImporter.cs

https://gitlab.com/rekby-archive/onlyoffice-CommunityServer
C# | 251 lines | 204 code | 29 blank | 18 comment | 18 complexity | dfeb20a7f51337146e63a79b3a8eacc9 MD5 | raw file
  1. /*
  2. *
  3. * (c) Copyright Ascensio System Limited 2010-2021
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. *
  15. */
  16. using System;
  17. using System.Collections.Generic;
  18. using System.ComponentModel;
  19. using System.Globalization;
  20. using System.IO;
  21. using System.Linq;
  22. using System.Net.Mail;
  23. using System.Reflection;
  24. using System.Text;
  25. using System.Text.RegularExpressions;
  26. namespace ASC.Web.Studio.Core.Import
  27. {
  28. public class MultiFormatTextFileUserImporter : TextFileUserImporter
  29. {
  30. public MultiFormatTextFileUserImporter(Stream stream)
  31. : base(stream)
  32. {
  33. }
  34. public MultiFormatTextFileUserImporter(string csvText)
  35. : base(csvText)
  36. {
  37. }
  38. protected override ContactInfo GetExportedUser(string line, IDictionary<int, PropertyInfo> mappedProperties, int fieldsCount)
  39. {
  40. try
  41. {
  42. var address = new MailAddress(line);
  43. var info = new ContactInfo { Email = address.Address };
  44. if (!string.IsNullOrEmpty(address.DisplayName))
  45. {
  46. if (address.DisplayName.Contains(' '))
  47. {
  48. //Try split
  49. info.FirstName = address.DisplayName.Split(' ')[0];
  50. info.LastName = address.DisplayName.Split(' ')[1];
  51. }
  52. else
  53. {
  54. info.FirstName = address.DisplayName;
  55. }
  56. }
  57. return info;
  58. }
  59. catch (Exception)
  60. {
  61. //thats bad. Failed to parse an address
  62. }
  63. return base.GetExportedUser(line, mappedProperties, fieldsCount);
  64. }
  65. }
  66. public class TextFileUserImporter : IUserImporter
  67. {
  68. private readonly Stream stream;
  69. private readonly string text;
  70. private readonly Encoding encoding;
  71. protected Dictionary<string, string> NameMapping { get; set; }
  72. protected IList<string> ExcludeList { get; private set; }
  73. public char[] Separators { get; set; }
  74. public bool HasHeader { get; set; }
  75. public string TextDelmiter { get; set; }
  76. public string DefaultHeader { get; set; }
  77. public TextFileUserImporter(Stream stream)
  78. {
  79. this.stream = stream;
  80. try
  81. {
  82. encoding = Encoding.GetEncoding(CultureInfo.CurrentCulture.TextInfo.ANSICodePage);
  83. }
  84. catch
  85. {
  86. encoding = Encoding.UTF8;
  87. }
  88. HasHeader = false;
  89. Separators = new[] { ';', ',' };
  90. TextDelmiter = "\"";
  91. ExcludeList = new List<string> { "ID", "Status" };
  92. }
  93. public TextFileUserImporter(string csvText)
  94. {
  95. this.encoding = Encoding.UTF8;
  96. text = csvText;
  97. HasHeader = false;
  98. Separators = new[] { ';', ',' };
  99. TextDelmiter = "\"";
  100. ExcludeList = new List<string> { "ID", "Status" };
  101. }
  102. public IEnumerable<ContactInfo> GetDiscoveredUsers()
  103. {
  104. var users = new List<ContactInfo>();
  105. var fileLines = new List<string>();
  106. if (stream != null)
  107. {
  108. using (var reader = new StreamReader(stream, encoding, true))
  109. {
  110. fileLines.AddRange(reader.ReadToEnd().Split(new[] { Environment.NewLine, "\n", "\r\n" }, StringSplitOptions.RemoveEmptyEntries));
  111. }
  112. }
  113. else
  114. {
  115. fileLines.AddRange(text.Split(new[] { Environment.NewLine, "\n", "\r\n" }, StringSplitOptions.RemoveEmptyEntries));
  116. }
  117. if (!string.IsNullOrEmpty(DefaultHeader))
  118. {
  119. fileLines.Insert(0, DefaultHeader);
  120. }
  121. if (0 < fileLines.Count)
  122. {
  123. var mappedProperties = new Dictionary<int, PropertyInfo>();
  124. var infos = typeof(ContactInfo).GetProperties(BindingFlags.Public | BindingFlags.Instance);
  125. var fieldsCount = GetFieldsMapping(fileLines[0], infos, mappedProperties);
  126. for (int i = 1; i < fileLines.Count; i++)
  127. {
  128. users.Add(GetExportedUser(fileLines[i], mappedProperties, fieldsCount));
  129. }
  130. }
  131. return users;
  132. }
  133. protected virtual ContactInfo GetExportedUser(string line, IDictionary<int, PropertyInfo> mappedProperties, int fieldsCount)
  134. {
  135. var exportedUser = new ContactInfo();
  136. var dataFields = GetDataFields(line);
  137. for (int j = 0; j < Math.Min(fieldsCount, dataFields.Length); j++)
  138. {
  139. var propinfo = mappedProperties[j];
  140. if (propinfo != null)
  141. {
  142. var value = ConvertFromString(dataFields[j], propinfo.PropertyType);
  143. if (value != null)
  144. {
  145. value = Regex.Replace(value.ToString(), "(^')|(^\")|(\"$)|('$)", String.Empty);
  146. propinfo.SetValue(exportedUser, value, null);
  147. }
  148. }
  149. }
  150. try
  151. {
  152. if (string.IsNullOrEmpty(exportedUser.FirstName) && string.IsNullOrEmpty(exportedUser.LastName) && !string.IsNullOrEmpty(exportedUser.Email))
  153. {
  154. var username = exportedUser.Email.Contains('@') ? exportedUser.Email.Substring(0, exportedUser.Email.IndexOf('@')) : exportedUser.Email;
  155. if (username.Contains('.'))
  156. {
  157. exportedUser.FirstName = username.Split('.')[0];
  158. exportedUser.LastName = username.Split('.')[1];
  159. }
  160. }
  161. }
  162. catch { }
  163. return exportedUser;
  164. }
  165. private string[] GetDataFields(string line)
  166. {
  167. var pattern = String.Format("[{0}](?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))", string.Join("|", Array.ConvertAll(Separators, c => c.ToString())));
  168. var result = Regex.Split(line, pattern);
  169. return Array.ConvertAll<string, string>(result,
  170. original =>
  171. {
  172. return original.StartsWith(TextDelmiter) && original.EndsWith(TextDelmiter) ?
  173. original.Substring(1, original.Length - 2) :
  174. original;
  175. }
  176. );
  177. }
  178. private int GetFieldsMapping(string firstLine, IEnumerable<PropertyInfo> infos, IDictionary<int, PropertyInfo> mappedProperties)
  179. {
  180. var fields = firstLine.Split(Separators, StringSplitOptions.RemoveEmptyEntries);
  181. for (int i = 0; i < fields.Length; i++)
  182. {
  183. var field = fields[i];
  184. //Find apropriate field in UserInfo
  185. foreach (var info in infos)
  186. {
  187. var propertyField = field.Trim();
  188. propertyField = propertyField.Trim('"');
  189. if (NameMapping != null && NameMapping.ContainsKey(propertyField))
  190. {
  191. propertyField = NameMapping[propertyField];
  192. }
  193. if (!string.IsNullOrEmpty(propertyField) && !ExcludeList.Contains(propertyField) && propertyField.Equals(info.Name, StringComparison.OrdinalIgnoreCase))
  194. {
  195. //Add to map
  196. mappedProperties.Add(i, info);
  197. }
  198. }
  199. if (!mappedProperties.ContainsKey(i))
  200. {
  201. //No property was found
  202. mappedProperties.Add(i, null);
  203. }
  204. }
  205. if (!mappedProperties.Values.Any(p => p != null))
  206. {
  207. mappedProperties[2] = infos.First(p => p.Name == "Email");
  208. mappedProperties[0] = infos.First(p => p.Name == "FirstName");
  209. mappedProperties[1] = infos.First(p => p.Name == "LastName");
  210. }
  211. return fields.Length;
  212. }
  213. private static object ConvertFromString(string value, Type type)
  214. {
  215. var converter = TypeDescriptor.GetConverter(type);
  216. return converter != null && converter.CanConvertFrom(typeof(string)) ? converter.ConvertFromString(value) : null;
  217. }
  218. }
  219. }